Remove incidental azure tests (#71164)

Change:
- All incidental coverage from these tests has moved to intentional
  coverage.

Test Plan:
- CI

Signed-off-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
Rick Elrod 2020-08-08 00:56:53 -05:00 committed by GitHub
parent 501f30df45
commit 4f54fb8d43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 0 additions and 8635 deletions

View file

@ -139,8 +139,6 @@ matrix:
- env: T=i/aws/2.7/1
- env: T=i/aws/3.6/1
- env: T=i/azure/2.7/1
- env: T=i/azure/3.6/1
- env: T=i/vcenter//1
- env: T=i/cs//1
- env: T=i/tower//1

View file

@ -1,3 +0,0 @@
cloud/azure
destructive
shippable/azure/incidental

View file

@ -1,158 +0,0 @@
- name: Prepare random number
set_fact:
nsgname: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
storageaccountname: "stacc{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
dbname: "mdb{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
run_once: yes
- name: Call REST API
azure_rm_resource:
api_version: '2018-02-01'
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
resource_name: "{{ nsgname }}"
body:
location: eastus
idempotency: yes
register: output
- name: Assert that something has changed
assert:
that: output.changed
- name: Call REST API
azure_rm_resource:
api_version: '2018-02-01'
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
resource_name: "{{ nsgname }}"
body:
location: eastus
idempotency: yes
register: output
- name: Assert that nothing has changed
assert:
that: not output.changed
- name: Call REST API
azure_rm_resource:
api_version: '2018-02-01'
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
resource_name: "{{ nsgname }}"
body:
location: eastus
tags:
a: "abc"
b: "cde"
idempotency: yes
register: output
- name: Assert that something has changed
assert:
that: output.changed
- name: Try to get information about account
azure_rm_resource_facts:
api_version: '2018-02-01'
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
resource_name: "{{ nsgname }}"
register: output
- name: Assert value was returned
assert:
that:
- not output.changed
- output.response[0]['name'] != None
- output.response | length == 1
- name: Try to query a list
azure_rm_resource_facts:
api_version: '2018-02-01'
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
register: output
- name: Assert value was returned
assert:
that:
- not output.changed
- output.response[0]['name'] != None
- output.response | length >= 1
- name: Try to query a list - same without API version
azure_rm_resource_facts:
resource_group: "{{ resource_group }}"
provider: network
resource_type: networksecuritygroups
register: output
- name: Assert value was returned
assert:
that:
- not output.changed
- output.response[0]['name'] != None
- output.response | length >= 1
- name: Query all the resources in the resource group
azure_rm_resource_facts:
resource_group: "{{ resource_group }}"
resource_type: resources
register: output
- name: Assert value was returned
assert:
that:
- not output.changed
- output.response | length >= 1
- name: Create storage account that requires LRO polling
azure_rm_resource:
polling_timeout: 600
polling_interval: 60
api_version: '2018-07-01'
resource_group: "{{ resource_group }}"
provider: Storage
resource_type: storageAccounts
resource_name: "{{ storageaccountname }}"
body:
sku:
name: Standard_GRS
kind: Storage
location: eastus
register: output
- name: Assert that storage was successfully created
assert:
that: "output['response']['name'] == '{{ storageaccountname }}'"
- name: Try to storage keys -- special case when subresource part has no name
azure_rm_resource:
resource_group: "{{ resource_group }}"
provider: storage
resource_type: storageAccounts
resource_name: "{{ storageaccountname }}"
subresource:
- type: listkeys
api_version: '2018-03-01-preview'
method: POST
register: keys
- name: Assert that key was returned
assert:
that: keys['response']['keys'][0]['value'] | length > 0
- name: Delete storage - without API version
azure_rm_resource:
polling_timeout: 600
polling_interval: 60
method: DELETE
resource_group: "{{ resource_group }}"
provider: Storage
resource_type: storageAccounts
resource_name: "{{ storageaccountname }}"

View file

@ -236,10 +236,6 @@ test/lib/ansible_test/_data/setup/ConfigureRemotingForAnsible.ps1 pslint:PSCusto
test/lib/ansible_test/_data/setup/windows-httptester.ps1 pslint:PSCustomUseLiteralPath
test/support/integration/plugins/module_utils/ansible_tower.py future-import-boilerplate
test/support/integration/plugins/module_utils/ansible_tower.py metaclass-boilerplate
test/support/integration/plugins/module_utils/azure_rm_common.py future-import-boilerplate
test/support/integration/plugins/module_utils/azure_rm_common.py metaclass-boilerplate
test/support/integration/plugins/module_utils/azure_rm_common_rest.py future-import-boilerplate
test/support/integration/plugins/module_utils/azure_rm_common_rest.py metaclass-boilerplate
test/support/integration/plugins/module_utils/cloud.py future-import-boilerplate
test/support/integration/plugins/module_utils/cloud.py metaclass-boilerplate
test/support/integration/plugins/module_utils/compat/ipaddress.py future-import-boilerplate

View file

@ -1,97 +0,0 @@
# Copyright (c) 2018 Zim Kalinowski, <zikalino@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from ansible.module_utils.ansible_release import __version__ as ANSIBLE_VERSION
try:
from msrestazure.azure_exceptions import CloudError
from msrestazure.azure_configuration import AzureConfiguration
from msrest.service_client import ServiceClient
from msrest.pipeline import ClientRawResponse
from msrest.polling import LROPoller
from msrestazure.polling.arm_polling import ARMPolling
import uuid
import json
except ImportError:
# This is handled in azure_rm_common
AzureConfiguration = object
ANSIBLE_USER_AGENT = 'Ansible/{0}'.format(ANSIBLE_VERSION)
class GenericRestClientConfiguration(AzureConfiguration):
def __init__(self, credentials, subscription_id, base_url=None):
if credentials is None:
raise ValueError("Parameter 'credentials' must not be None.")
if subscription_id is None:
raise ValueError("Parameter 'subscription_id' must not be None.")
if not base_url:
base_url = 'https://management.azure.com'
super(GenericRestClientConfiguration, self).__init__(base_url)
self.add_user_agent(ANSIBLE_USER_AGENT)
self.credentials = credentials
self.subscription_id = subscription_id
class GenericRestClient(object):
def __init__(self, credentials, subscription_id, base_url=None):
self.config = GenericRestClientConfiguration(credentials, subscription_id, base_url)
self._client = ServiceClient(self.config.credentials, self.config)
self.models = None
def query(self, url, method, query_parameters, header_parameters, body, expected_status_codes, polling_timeout, polling_interval):
# Construct and send request
operation_config = {}
request = None
if header_parameters is None:
header_parameters = {}
header_parameters['x-ms-client-request-id'] = str(uuid.uuid1())
if method == 'GET':
request = self._client.get(url, query_parameters)
elif method == 'PUT':
request = self._client.put(url, query_parameters)
elif method == 'POST':
request = self._client.post(url, query_parameters)
elif method == 'HEAD':
request = self._client.head(url, query_parameters)
elif method == 'PATCH':
request = self._client.patch(url, query_parameters)
elif method == 'DELETE':
request = self._client.delete(url, query_parameters)
elif method == 'MERGE':
request = self._client.merge(url, query_parameters)
response = self._client.send(request, header_parameters, body, **operation_config)
if response.status_code not in expected_status_codes:
exp = CloudError(response)
exp.request_id = response.headers.get('x-ms-request-id')
raise exp
elif response.status_code == 202 and polling_timeout > 0:
def get_long_running_output(response):
return response
poller = LROPoller(self._client,
ClientRawResponse(None, response),
get_long_running_output,
ARMPolling(polling_interval, **operation_config))
response = self.get_poller_result(poller, polling_timeout)
return response
def get_poller_result(self, poller, timeout):
try:
poller.wait(timeout=timeout)
return poller.result()
except Exception as exc:
raise

View file

@ -1 +0,0 @@
azure_rm_mariadbconfiguration_info.py

View file

@ -1 +0,0 @@
azure_rm_mariadbdatabase_info.py

View file

@ -1 +0,0 @@
azure_rm_mariadbfirewallrule_info.py

View file

@ -1 +0,0 @@
azure_rm_mariadbserver_info.py

View file

@ -1 +0,0 @@
azure_rm_resource_info.py

View file

@ -1 +0,0 @@
azure_rm_webapp_info.py

View file

@ -1,379 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Yunge Zhu, <yungez@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_appserviceplan
version_added: "2.7"
short_description: Manage App Service Plan
description:
- Create, update and delete instance of App Service Plan.
options:
resource_group:
description:
- Name of the resource group to which the resource belongs.
required: True
name:
description:
- Unique name of the app service plan to create or update.
required: True
location:
description:
- Resource location. If not set, location from the resource group will be used as default.
sku:
description:
- The pricing tiers, e.g., C(F1), C(D1), C(B1), C(B2), C(B3), C(S1), C(P1), C(P1V2) etc.
- Please see U(https://azure.microsoft.com/en-us/pricing/details/app-service/plans/) for more detail.
- For Linux app service plan, please see U(https://azure.microsoft.com/en-us/pricing/details/app-service/linux/) for more detail.
is_linux:
description:
- Describe whether to host webapp on Linux worker.
type: bool
default: false
number_of_workers:
description:
- Describe number of workers to be allocated.
state:
description:
- Assert the state of the app service plan.
- Use C(present) to create or update an app service plan and C(absent) to delete it.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
- azure_tags
author:
- Yunge Zhu (@yungezz)
'''
EXAMPLES = '''
- name: Create a windows app service plan
azure_rm_appserviceplan:
resource_group: myResourceGroup
name: myAppPlan
location: eastus
sku: S1
- name: Create a linux app service plan
azure_rm_appserviceplan:
resource_group: myResourceGroup
name: myAppPlan
location: eastus
sku: S1
is_linux: true
number_of_workers: 1
- name: update sku of existing windows app service plan
azure_rm_appserviceplan:
resource_group: myResourceGroup
name: myAppPlan
location: eastus
sku: S2
'''
RETURN = '''
azure_appserviceplan:
description: Facts about the current state of the app service plan.
returned: always
type: dict
sample: {
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppPlan"
}
'''
import time
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from msrest.polling import LROPoller
from msrestazure.azure_operation import AzureOperationPoller
from msrest.serialization import Model
from azure.mgmt.web.models import (
app_service_plan, AppServicePlan, SkuDescription
)
except ImportError:
# This is handled in azure_rm_common
pass
def _normalize_sku(sku):
if sku is None:
return sku
sku = sku.upper()
if sku == 'FREE':
return 'F1'
elif sku == 'SHARED':
return 'D1'
return sku
def get_sku_name(tier):
tier = tier.upper()
if tier == 'F1' or tier == "FREE":
return 'FREE'
elif tier == 'D1' or tier == "SHARED":
return 'SHARED'
elif tier in ['B1', 'B2', 'B3', 'BASIC']:
return 'BASIC'
elif tier in ['S1', 'S2', 'S3']:
return 'STANDARD'
elif tier in ['P1', 'P2', 'P3']:
return 'PREMIUM'
elif tier in ['P1V2', 'P2V2', 'P3V2']:
return 'PREMIUMV2'
else:
return None
def appserviceplan_to_dict(plan):
return dict(
id=plan.id,
name=plan.name,
kind=plan.kind,
location=plan.location,
reserved=plan.reserved,
is_linux=plan.reserved,
provisioning_state=plan.provisioning_state,
status=plan.status,
target_worker_count=plan.target_worker_count,
sku=dict(
name=plan.sku.name,
size=plan.sku.size,
tier=plan.sku.tier,
family=plan.sku.family,
capacity=plan.sku.capacity
),
resource_group=plan.resource_group,
number_of_sites=plan.number_of_sites,
tags=plan.tags if plan.tags else None
)
class AzureRMAppServicePlans(AzureRMModuleBase):
"""Configuration class for an Azure RM App Service Plan resource"""
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
name=dict(
type='str',
required=True
),
location=dict(
type='str'
),
sku=dict(
type='str'
),
is_linux=dict(
type='bool',
default=False
),
number_of_workers=dict(
type='str'
),
state=dict(
type='str',
default='present',
choices=['present', 'absent']
)
)
self.resource_group = None
self.name = None
self.location = None
self.sku = None
self.is_linux = None
self.number_of_workers = 1
self.tags = None
self.results = dict(
changed=False,
ansible_facts=dict(azure_appserviceplan=None)
)
self.state = None
super(AzureRMAppServicePlans, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=True)
def exec_module(self, **kwargs):
"""Main module execution method"""
for key in list(self.module_arg_spec.keys()) + ['tags']:
if kwargs[key]:
setattr(self, key, kwargs[key])
old_response = None
response = None
to_be_updated = False
# set location
resource_group = self.get_resource_group(self.resource_group)
if not self.location:
self.location = resource_group.location
# get app service plan
old_response = self.get_plan()
# if not existing
if not old_response:
self.log("App Service plan doesn't exist")
if self.state == "present":
to_be_updated = True
if not self.sku:
self.fail('Please specify sku in plan when creation')
else:
# existing app service plan, do update
self.log("App Service Plan already exists")
if self.state == 'present':
self.log('Result: {0}'.format(old_response))
update_tags, newtags = self.update_tags(old_response.get('tags', dict()))
if update_tags:
to_be_updated = True
self.tags = newtags
# check if sku changed
if self.sku and _normalize_sku(self.sku) != old_response['sku']['size']:
to_be_updated = True
# check if number_of_workers changed
if self.number_of_workers and int(self.number_of_workers) != old_response['sku']['capacity']:
to_be_updated = True
if self.is_linux and self.is_linux != old_response['reserved']:
self.fail("Operation not allowed: cannot update reserved of app service plan.")
if old_response:
self.results['id'] = old_response['id']
if to_be_updated:
self.log('Need to Create/Update app service plan')
self.results['changed'] = True
if self.check_mode:
return self.results
response = self.create_or_update_plan()
self.results['id'] = response['id']
if self.state == 'absent' and old_response:
self.log("Delete app service plan")
self.results['changed'] = True
if self.check_mode:
return self.results
self.delete_plan()
self.log('App service plan instance deleted')
return self.results
def get_plan(self):
'''
Gets app service plan
:return: deserialized app service plan dictionary
'''
self.log("Get App Service Plan {0}".format(self.name))
try:
response = self.web_client.app_service_plans.get(self.resource_group, self.name)
if response:
self.log("Response : {0}".format(response))
self.log("App Service Plan : {0} found".format(response.name))
return appserviceplan_to_dict(response)
except CloudError as ex:
self.log("Didn't find app service plan {0} in resource group {1}".format(self.name, self.resource_group))
return False
def create_or_update_plan(self):
'''
Creates app service plan
:return: deserialized app service plan dictionary
'''
self.log("Create App Service Plan {0}".format(self.name))
try:
# normalize sku
sku = _normalize_sku(self.sku)
sku_def = SkuDescription(tier=get_sku_name(
sku), name=sku, capacity=self.number_of_workers)
plan_def = AppServicePlan(
location=self.location, app_service_plan_name=self.name, sku=sku_def, reserved=self.is_linux, tags=self.tags if self.tags else None)
response = self.web_client.app_service_plans.create_or_update(self.resource_group, self.name, plan_def)
if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller):
response = self.get_poller_result(response)
self.log("Response : {0}".format(response))
return appserviceplan_to_dict(response)
except CloudError as ex:
self.fail("Failed to create app service plan {0} in resource group {1}: {2}".format(self.name, self.resource_group, str(ex)))
def delete_plan(self):
'''
Deletes specified App service plan in the specified subscription and resource group.
:return: True
'''
self.log("Deleting the App service plan {0}".format(self.name))
try:
response = self.web_client.app_service_plans.delete(resource_group_name=self.resource_group,
name=self.name)
except CloudError as e:
self.log('Error attempting to delete App service plan.')
self.fail(
"Error deleting the App service plan : {0}".format(str(e)))
return True
def main():
"""Main execution"""
AzureRMAppServicePlans()
if __name__ == '__main__':
main()

View file

@ -1,421 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2016, Thomas Stringer <tomstr@microsoft.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_functionapp
version_added: "2.4"
short_description: Manage Azure Function Apps
description:
- Create, update or delete an Azure Function App.
options:
resource_group:
description:
- Name of resource group.
required: true
aliases:
- resource_group_name
name:
description:
- Name of the Azure Function App.
required: true
location:
description:
- Valid Azure location. Defaults to location of the resource group.
plan:
description:
- App service plan.
- It can be name of existing app service plan in same resource group as function app.
- It can be resource id of existing app service plan.
- Resource id. For example /subscriptions/<subs_id>/resourceGroups/<resource_group>/providers/Microsoft.Web/serverFarms/<plan_name>.
- It can be a dict which contains C(name), C(resource_group).
- C(name). Name of app service plan.
- C(resource_group). Resource group name of app service plan.
version_added: "2.8"
container_settings:
description: Web app container settings.
suboptions:
name:
description:
- Name of container. For example "imagename:tag".
registry_server_url:
description:
- Container registry server url. For example C(mydockerregistry.io).
registry_server_user:
description:
- The container registry server user name.
registry_server_password:
description:
- The container registry server password.
version_added: "2.8"
storage_account:
description:
- Name of the storage account to use.
required: true
aliases:
- storage
- storage_account_name
app_settings:
description:
- Dictionary containing application settings.
state:
description:
- Assert the state of the Function App. Use C(present) to create or update a Function App and C(absent) to delete.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
- azure_tags
author:
- Thomas Stringer (@trstringer)
'''
EXAMPLES = '''
- name: Create a function app
azure_rm_functionapp:
resource_group: myResourceGroup
name: myFunctionApp
storage_account: myStorageAccount
- name: Create a function app with app settings
azure_rm_functionapp:
resource_group: myResourceGroup
name: myFunctionApp
storage_account: myStorageAccount
app_settings:
setting1: value1
setting2: value2
- name: Create container based function app
azure_rm_functionapp:
resource_group: myResourceGroup
name: myFunctionApp
storage_account: myStorageAccount
plan:
resource_group: myResourceGroup
name: myAppPlan
container_settings:
name: httpd
registry_server_url: index.docker.io
- name: Delete a function app
azure_rm_functionapp:
resource_group: myResourceGroup
name: myFunctionApp
state: absent
'''
RETURN = '''
state:
description:
- Current state of the Azure Function App.
returned: success
type: dict
example:
id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myFunctionApp
name: myfunctionapp
kind: functionapp
location: East US
type: Microsoft.Web/sites
state: Running
host_names:
- myfunctionapp.azurewebsites.net
repository_site_name: myfunctionapp
usage_state: Normal
enabled: true
enabled_host_names:
- myfunctionapp.azurewebsites.net
- myfunctionapp.scm.azurewebsites.net
availability_state: Normal
host_name_ssl_states:
- name: myfunctionapp.azurewebsites.net
ssl_state: Disabled
host_type: Standard
- name: myfunctionapp.scm.azurewebsites.net
ssl_state: Disabled
host_type: Repository
server_farm_id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/EastUSPlan
reserved: false
last_modified_time_utc: 2017-08-22T18:54:01.190Z
scm_site_also_stopped: false
client_affinity_enabled: true
client_cert_enabled: false
host_names_disabled: false
outbound_ip_addresses: ............
container_size: 1536
daily_memory_time_quota: 0
resource_group: myResourceGroup
default_host_name: myfunctionapp.azurewebsites.net
''' # NOQA
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from azure.mgmt.web.models import (
site_config, app_service_plan, Site, SiteConfig, NameValuePair, SiteSourceControl,
AppServicePlan, SkuDescription
)
from azure.mgmt.resource.resources import ResourceManagementClient
from msrest.polling import LROPoller
except ImportError:
# This is handled in azure_rm_common
pass
container_settings_spec = dict(
name=dict(type='str', required=True),
registry_server_url=dict(type='str'),
registry_server_user=dict(type='str'),
registry_server_password=dict(type='str', no_log=True)
)
class AzureRMFunctionApp(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(type='str', required=True, aliases=['resource_group_name']),
name=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present', 'absent']),
location=dict(type='str'),
storage_account=dict(
type='str',
aliases=['storage', 'storage_account_name']
),
app_settings=dict(type='dict'),
plan=dict(
type='raw'
),
container_settings=dict(
type='dict',
options=container_settings_spec
)
)
self.results = dict(
changed=False,
state=dict()
)
self.resource_group = None
self.name = None
self.state = None
self.location = None
self.storage_account = None
self.app_settings = None
self.plan = None
self.container_settings = None
required_if = [('state', 'present', ['storage_account'])]
super(AzureRMFunctionApp, self).__init__(
self.module_arg_spec,
supports_check_mode=True,
required_if=required_if
)
def exec_module(self, **kwargs):
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
if self.app_settings is None:
self.app_settings = dict()
try:
resource_group = self.rm_client.resource_groups.get(self.resource_group)
except CloudError:
self.fail('Unable to retrieve resource group')
self.location = self.location or resource_group.location
try:
function_app = self.web_client.web_apps.get(
resource_group_name=self.resource_group,
name=self.name
)
# Newer SDK versions (0.40.0+) seem to return None if it doesn't exist instead of raising CloudError
exists = function_app is not None
except CloudError as exc:
exists = False
if self.state == 'absent':
if exists:
if self.check_mode:
self.results['changed'] = True
return self.results
try:
self.web_client.web_apps.delete(
resource_group_name=self.resource_group,
name=self.name
)
self.results['changed'] = True
except CloudError as exc:
self.fail('Failure while deleting web app: {0}'.format(exc))
else:
self.results['changed'] = False
else:
kind = 'functionapp'
linux_fx_version = None
if self.container_settings and self.container_settings.get('name'):
kind = 'functionapp,linux,container'
linux_fx_version = 'DOCKER|'
if self.container_settings.get('registry_server_url'):
self.app_settings['DOCKER_REGISTRY_SERVER_URL'] = 'https://' + self.container_settings['registry_server_url']
linux_fx_version += self.container_settings['registry_server_url'] + '/'
linux_fx_version += self.container_settings['name']
if self.container_settings.get('registry_server_user'):
self.app_settings['DOCKER_REGISTRY_SERVER_USERNAME'] = self.container_settings.get('registry_server_user')
if self.container_settings.get('registry_server_password'):
self.app_settings['DOCKER_REGISTRY_SERVER_PASSWORD'] = self.container_settings.get('registry_server_password')
if not self.plan and function_app:
self.plan = function_app.server_farm_id
if not exists:
function_app = Site(
location=self.location,
kind=kind,
site_config=SiteConfig(
app_settings=self.aggregated_app_settings(),
scm_type='LocalGit'
)
)
self.results['changed'] = True
else:
self.results['changed'], function_app = self.update(function_app)
# get app service plan
if self.plan:
if isinstance(self.plan, dict):
self.plan = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/serverfarms/{2}".format(
self.subscription_id,
self.plan.get('resource_group', self.resource_group),
self.plan.get('name')
)
function_app.server_farm_id = self.plan
# set linux fx version
if linux_fx_version:
function_app.site_config.linux_fx_version = linux_fx_version
if self.check_mode:
self.results['state'] = function_app.as_dict()
elif self.results['changed']:
try:
new_function_app = self.web_client.web_apps.create_or_update(
resource_group_name=self.resource_group,
name=self.name,
site_envelope=function_app
).result()
self.results['state'] = new_function_app.as_dict()
except CloudError as exc:
self.fail('Error creating or updating web app: {0}'.format(exc))
return self.results
def update(self, source_function_app):
"""Update the Site object if there are any changes"""
source_app_settings = self.web_client.web_apps.list_application_settings(
resource_group_name=self.resource_group,
name=self.name
)
changed, target_app_settings = self.update_app_settings(source_app_settings.properties)
source_function_app.site_config = SiteConfig(
app_settings=target_app_settings,
scm_type='LocalGit'
)
return changed, source_function_app
def update_app_settings(self, source_app_settings):
"""Update app settings"""
target_app_settings = self.aggregated_app_settings()
target_app_settings_dict = dict([(i.name, i.value) for i in target_app_settings])
return target_app_settings_dict != source_app_settings, target_app_settings
def necessary_functionapp_settings(self):
"""Construct the necessary app settings required for an Azure Function App"""
function_app_settings = []
if self.container_settings is None:
for key in ['AzureWebJobsStorage', 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING', 'AzureWebJobsDashboard']:
function_app_settings.append(NameValuePair(name=key, value=self.storage_connection_string))
function_app_settings.append(NameValuePair(name='FUNCTIONS_EXTENSION_VERSION', value='~1'))
function_app_settings.append(NameValuePair(name='WEBSITE_NODE_DEFAULT_VERSION', value='6.5.0'))
function_app_settings.append(NameValuePair(name='WEBSITE_CONTENTSHARE', value=self.name))
else:
function_app_settings.append(NameValuePair(name='FUNCTIONS_EXTENSION_VERSION', value='~2'))
function_app_settings.append(NameValuePair(name='WEBSITES_ENABLE_APP_SERVICE_STORAGE', value=False))
function_app_settings.append(NameValuePair(name='AzureWebJobsStorage', value=self.storage_connection_string))
return function_app_settings
def aggregated_app_settings(self):
"""Combine both system and user app settings"""
function_app_settings = self.necessary_functionapp_settings()
for app_setting_key in self.app_settings:
found_setting = None
for s in function_app_settings:
if s.name == app_setting_key:
found_setting = s
break
if found_setting:
found_setting.value = self.app_settings[app_setting_key]
else:
function_app_settings.append(NameValuePair(
name=app_setting_key,
value=self.app_settings[app_setting_key]
))
return function_app_settings
@property
def storage_connection_string(self):
"""Construct the storage account connection string"""
return 'DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}'.format(
self.storage_account,
self.storage_key
)
@property
def storage_key(self):
"""Retrieve the storage account key"""
return self.storage_client.storage_accounts.list_keys(
resource_group_name=self.resource_group,
account_name=self.storage_account
).keys[0].value
def main():
"""Main function execution"""
AzureRMFunctionApp()
if __name__ == '__main__':
main()

View file

@ -1,207 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2016 Thomas Stringer, <tomstr@microsoft.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_functionapp_info
version_added: "2.9"
short_description: Get Azure Function App facts
description:
- Get facts for one Azure Function App or all Function Apps within a resource group.
options:
name:
description:
- Only show results for a specific Function App.
resource_group:
description:
- Limit results to a resource group. Required when filtering by name.
aliases:
- resource_group_name
tags:
description:
- Limit results by providing a list of tags. Format tags as 'key' or 'key:value'.
extends_documentation_fragment:
- azure
author:
- Thomas Stringer (@trstringer)
'''
EXAMPLES = '''
- name: Get facts for one Function App
azure_rm_functionapp_info:
resource_group: myResourceGroup
name: myfunctionapp
- name: Get facts for all Function Apps in a resource group
azure_rm_functionapp_info:
resource_group: myResourceGroup
- name: Get facts for all Function Apps by tags
azure_rm_functionapp_info:
tags:
- testing
'''
RETURN = '''
azure_functionapps:
description:
- List of Azure Function Apps dicts.
returned: always
type: list
example:
id: /subscriptions/.../resourceGroups/ansible-rg/providers/Microsoft.Web/sites/myfunctionapp
name: myfunctionapp
kind: functionapp
location: East US
type: Microsoft.Web/sites
state: Running
host_names:
- myfunctionapp.azurewebsites.net
repository_site_name: myfunctionapp
usage_state: Normal
enabled: true
enabled_host_names:
- myfunctionapp.azurewebsites.net
- myfunctionapp.scm.azurewebsites.net
availability_state: Normal
host_name_ssl_states:
- name: myfunctionapp.azurewebsites.net
ssl_state: Disabled
host_type: Standard
- name: myfunctionapp.scm.azurewebsites.net
ssl_state: Disabled
host_type: Repository
server_farm_id: /subscriptions/.../resourceGroups/ansible-rg/providers/Microsoft.Web/serverfarms/EastUSPlan
reserved: false
last_modified_time_utc: 2017-08-22T18:54:01.190Z
scm_site_also_stopped: false
client_affinity_enabled: true
client_cert_enabled: false
host_names_disabled: false
outbound_ip_addresses: ............
container_size: 1536
daily_memory_time_quota: 0
resource_group: myResourceGroup
default_host_name: myfunctionapp.azurewebsites.net
'''
try:
from msrestazure.azure_exceptions import CloudError
except Exception:
# This is handled in azure_rm_common
pass
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
class AzureRMFunctionAppInfo(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
name=dict(type='str'),
resource_group=dict(type='str', aliases=['resource_group_name']),
tags=dict(type='list'),
)
self.results = dict(
changed=False,
ansible_info=dict(azure_functionapps=[])
)
self.name = None
self.resource_group = None
self.tags = None
super(AzureRMFunctionAppInfo, self).__init__(
self.module_arg_spec,
supports_tags=False,
facts_module=True
)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_functionapp_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_functionapp_facts' module has been renamed to 'azure_rm_functionapp_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
if self.name and not self.resource_group:
self.fail("Parameter error: resource group required when filtering by name.")
if self.name:
self.results['ansible_info']['azure_functionapps'] = self.get_functionapp()
elif self.resource_group:
self.results['ansible_info']['azure_functionapps'] = self.list_resource_group()
else:
self.results['ansible_info']['azure_functionapps'] = self.list_all()
return self.results
def get_functionapp(self):
self.log('Get properties for Function App {0}'.format(self.name))
function_app = None
result = []
try:
function_app = self.web_client.web_apps.get(
self.resource_group,
self.name
)
except CloudError:
pass
if function_app and self.has_tags(function_app.tags, self.tags):
result = function_app.as_dict()
return [result]
def list_resource_group(self):
self.log('List items')
try:
response = self.web_client.web_apps.list_by_resource_group(self.resource_group)
except Exception as exc:
self.fail("Error listing for resource group {0} - {1}".format(self.resource_group, str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(item.as_dict())
return results
def list_all(self):
self.log('List all items')
try:
response = self.web_client.web_apps.list_by_resource_group(self.resource_group)
except Exception as exc:
self.fail("Error listing all items - {0}".format(str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(item.as_dict())
return results
def main():
AzureRMFunctionAppInfo()
if __name__ == '__main__':
main()

View file

@ -1,241 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbconfiguration
version_added: "2.8"
short_description: Manage Configuration instance
description:
- Create, update and delete instance of Configuration.
options:
resource_group:
description:
- The name of the resource group that contains the resource.
required: True
server_name:
description:
- The name of the server.
required: True
name:
description:
- The name of the server configuration.
required: True
value:
description:
- Value of the configuration.
state:
description:
- Assert the state of the MariaDB configuration. Use C(present) to update setting, or C(absent) to reset to default value.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Update SQL Server setting
azure_rm_mariadbconfiguration:
resource_group: myResourceGroup
server_name: myServer
name: event_scheduler
value: "ON"
'''
RETURN = '''
id:
description:
- Resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/myServer/confi
gurations/event_scheduler"
'''
import time
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from msrest.polling import LROPoller
from azure.mgmt.rdbms.mysql import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class Actions:
NoAction, Create, Update, Delete = range(4)
class AzureRMMariaDbConfiguration(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str',
required=True
),
value=dict(
type='str'
),
state=dict(
type='str',
default='present',
choices=['present', 'absent']
)
)
self.resource_group = None
self.server_name = None
self.name = None
self.value = None
self.results = dict(changed=False)
self.state = None
self.to_do = Actions.NoAction
super(AzureRMMariaDbConfiguration, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=False)
def exec_module(self, **kwargs):
for key in list(self.module_arg_spec.keys()):
if hasattr(self, key):
setattr(self, key, kwargs[key])
old_response = None
response = None
old_response = self.get_configuration()
if not old_response:
self.log("Configuration instance doesn't exist")
if self.state == 'absent':
self.log("Old instance didn't exist")
else:
self.to_do = Actions.Create
else:
self.log("Configuration instance already exists")
if self.state == 'absent' and old_response['source'] == 'user-override':
self.to_do = Actions.Delete
elif self.state == 'present':
self.log("Need to check if Configuration instance has to be deleted or may be updated")
if self.value != old_response.get('value'):
self.to_do = Actions.Update
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
self.log("Need to Create / Update the Configuration instance")
if self.check_mode:
self.results['changed'] = True
return self.results
response = self.create_update_configuration()
self.results['changed'] = True
self.log("Creation / Update done")
elif self.to_do == Actions.Delete:
self.log("Configuration instance deleted")
self.results['changed'] = True
if self.check_mode:
return self.results
self.delete_configuration()
else:
self.log("Configuration instance unchanged")
self.results['changed'] = False
response = old_response
if response:
self.results["id"] = response["id"]
return self.results
def create_update_configuration(self):
self.log("Creating / Updating the Configuration instance {0}".format(self.name))
try:
response = self.mariadb_client.configurations.create_or_update(resource_group_name=self.resource_group,
server_name=self.server_name,
configuration_name=self.name,
value=self.value,
source='user-override')
if isinstance(response, LROPoller):
response = self.get_poller_result(response)
except CloudError as exc:
self.log('Error attempting to create the Configuration instance.')
self.fail("Error creating the Configuration instance: {0}".format(str(exc)))
return response.as_dict()
def delete_configuration(self):
self.log("Deleting the Configuration instance {0}".format(self.name))
try:
response = self.mariadb_client.configurations.create_or_update(resource_group_name=self.resource_group,
server_name=self.server_name,
configuration_name=self.name,
source='system-default')
except CloudError as e:
self.log('Error attempting to delete the Configuration instance.')
self.fail("Error deleting the Configuration instance: {0}".format(str(e)))
return True
def get_configuration(self):
self.log("Checking if the Configuration instance {0} is present".format(self.name))
found = False
try:
response = self.mariadb_client.configurations.get(resource_group_name=self.resource_group,
server_name=self.server_name,
configuration_name=self.name)
found = True
self.log("Response : {0}".format(response))
self.log("Configuration instance : {0} found".format(response.name))
except CloudError as e:
self.log('Did not find the Configuration instance.')
if found is True:
return response.as_dict()
return False
def main():
"""Main execution"""
AzureRMMariaDbConfiguration()
if __name__ == '__main__':
main()

View file

@ -1,217 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbconfiguration_info
version_added: "2.9"
short_description: Get Azure MariaDB Configuration facts
description:
- Get facts of Azure MariaDB Configuration.
options:
resource_group:
description:
- The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
required: True
type: str
server_name:
description:
- The name of the server.
required: True
type: str
name:
description:
- Setting name.
type: str
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Get specific setting of MariaDB Server
azure_rm_mariadbconfiguration_info:
resource_group: myResourceGroup
server_name: testserver
name: deadlock_timeout
- name: Get all settings of MariaDB Server
azure_rm_mariadbconfiguration_info:
resource_group: myResourceGroup
server_name: server_name
'''
RETURN = '''
settings:
description:
- A list of dictionaries containing MariaDB Server settings.
returned: always
type: complex
contains:
id:
description:
- Setting resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/testserver
/configurations/deadlock_timeout"
name:
description:
- Setting name.
returned: always
type: str
sample: deadlock_timeout
value:
description:
- Setting value.
returned: always
type: raw
sample: 1000
description:
description:
- Description of the configuration.
returned: always
type: str
sample: Deadlock timeout.
source:
description:
- Source of the configuration.
returned: always
type: str
sample: system-default
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from msrestazure.azure_operation import AzureOperationPoller
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMMariaDbConfigurationInfo(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str'
)
)
# store the results of the module operation
self.results = dict(changed=False)
self.mgmt_client = None
self.resource_group = None
self.server_name = None
self.name = None
super(AzureRMMariaDbConfigurationInfo, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_mariadbconfiguration_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_mariadbconfiguration_facts' module has been renamed to 'azure_rm_mariadbconfiguration_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
self.mgmt_client = self.get_mgmt_svc_client(MariaDBManagementClient,
base_url=self._cloud_environment.endpoints.resource_manager)
if self.name is not None:
self.results['settings'] = self.get()
else:
self.results['settings'] = self.list_by_server()
return self.results
def get(self):
'''
Gets facts of the specified MariaDB Configuration.
:return: deserialized MariaDB Configurationinstance state dictionary
'''
response = None
results = []
try:
response = self.mgmt_client.configurations.get(resource_group_name=self.resource_group,
server_name=self.server_name,
configuration_name=self.name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for Configurations.')
if response is not None:
results.append(self.format_item(response))
return results
def list_by_server(self):
'''
Gets facts of the specified MariaDB Configuration.
:return: deserialized MariaDB Configurationinstance state dictionary
'''
response = None
results = []
try:
response = self.mgmt_client.configurations.list_by_server(resource_group_name=self.resource_group,
server_name=self.server_name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for Configurations.')
if response is not None:
for item in response:
results.append(self.format_item(item))
return results
def format_item(self, item):
d = item.as_dict()
d = {
'resource_group': self.resource_group,
'server_name': self.server_name,
'id': d['id'],
'name': d['name'],
'value': d['value'],
'description': d['description'],
'source': d['source']
}
return d
def main():
AzureRMMariaDbConfigurationInfo()
if __name__ == '__main__':
main()

View file

@ -1,304 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2017 Zim Kalinowski, <zikalino@microsoft.com>
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbdatabase
version_added: "2.8"
short_description: Manage MariaDB Database instance
description:
- Create, update and delete instance of MariaDB Database.
options:
resource_group:
description:
- The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
required: True
server_name:
description:
- The name of the server.
required: True
name:
description:
- The name of the database.
required: True
charset:
description:
- The charset of the database. Check MariaDB documentation for possible values.
- This is only set on creation, use I(force_update) to recreate a database if the values don't match.
collation:
description:
- The collation of the database. Check MariaDB documentation for possible values.
- This is only set on creation, use I(force_update) to recreate a database if the values don't match.
force_update:
description:
- When set to C(true), will delete and recreate the existing MariaDB database if any of the properties don't match what is set.
- When set to C(false), no change will occur to the database even if any of the properties do not match.
type: bool
default: 'no'
state:
description:
- Assert the state of the MariaDB Database. Use C(present) to create or update a database and C(absent) to delete it.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Create (or update) MariaDB Database
azure_rm_mariadbdatabase:
resource_group: myResourceGroup
server_name: testserver
name: db1
'''
RETURN = '''
id:
description:
- Resource ID.
returned: always
type: str
sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/testserver/databases/db1
name:
description:
- Resource name.
returned: always
type: str
sample: db1
'''
import time
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrestazure.azure_exceptions import CloudError
from msrest.polling import LROPoller
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class Actions:
NoAction, Create, Update, Delete = range(4)
class AzureRMMariaDbDatabase(AzureRMModuleBase):
"""Configuration class for an Azure RM MariaDB Database resource"""
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str',
required=True
),
charset=dict(
type='str'
),
collation=dict(
type='str'
),
force_update=dict(
type='bool',
default=False
),
state=dict(
type='str',
default='present',
choices=['present', 'absent']
)
)
self.resource_group = None
self.server_name = None
self.name = None
self.force_update = None
self.parameters = dict()
self.results = dict(changed=False)
self.mgmt_client = None
self.state = None
self.to_do = Actions.NoAction
super(AzureRMMariaDbDatabase, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=False)
def exec_module(self, **kwargs):
"""Main module execution method"""
for key in list(self.module_arg_spec.keys()):
if hasattr(self, key):
setattr(self, key, kwargs[key])
elif kwargs[key] is not None:
if key == "charset":
self.parameters["charset"] = kwargs[key]
elif key == "collation":
self.parameters["collation"] = kwargs[key]
old_response = None
response = None
self.mgmt_client = self.get_mgmt_svc_client(MariaDBManagementClient,
base_url=self._cloud_environment.endpoints.resource_manager)
resource_group = self.get_resource_group(self.resource_group)
old_response = self.get_mariadbdatabase()
if not old_response:
self.log("MariaDB Database instance doesn't exist")
if self.state == 'absent':
self.log("Old instance didn't exist")
else:
self.to_do = Actions.Create
else:
self.log("MariaDB Database instance already exists")
if self.state == 'absent':
self.to_do = Actions.Delete
elif self.state == 'present':
self.log("Need to check if MariaDB Database instance has to be deleted or may be updated")
if ('collation' in self.parameters) and (self.parameters['collation'] != old_response['collation']):
self.to_do = Actions.Update
if ('charset' in self.parameters) and (self.parameters['charset'] != old_response['charset']):
self.to_do = Actions.Update
if self.to_do == Actions.Update:
if self.force_update:
if not self.check_mode:
self.delete_mariadbdatabase()
else:
self.fail("Database properties cannot be updated without setting 'force_update' option")
self.to_do = Actions.NoAction
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
self.log("Need to Create / Update the MariaDB Database instance")
if self.check_mode:
self.results['changed'] = True
return self.results
response = self.create_update_mariadbdatabase()
self.results['changed'] = True
self.log("Creation / Update done")
elif self.to_do == Actions.Delete:
self.log("MariaDB Database instance deleted")
self.results['changed'] = True
if self.check_mode:
return self.results
self.delete_mariadbdatabase()
# make sure instance is actually deleted, for some Azure resources, instance is hanging around
# for some time after deletion -- this should be really fixed in Azure
while self.get_mariadbdatabase():
time.sleep(20)
else:
self.log("MariaDB Database instance unchanged")
self.results['changed'] = False
response = old_response
if response:
self.results["id"] = response["id"]
self.results["name"] = response["name"]
return self.results
def create_update_mariadbdatabase(self):
'''
Creates or updates MariaDB Database with the specified configuration.
:return: deserialized MariaDB Database instance state dictionary
'''
self.log("Creating / Updating the MariaDB Database instance {0}".format(self.name))
try:
response = self.mgmt_client.databases.create_or_update(resource_group_name=self.resource_group,
server_name=self.server_name,
database_name=self.name,
parameters=self.parameters)
if isinstance(response, LROPoller):
response = self.get_poller_result(response)
except CloudError as exc:
self.log('Error attempting to create the MariaDB Database instance.')
self.fail("Error creating the MariaDB Database instance: {0}".format(str(exc)))
return response.as_dict()
def delete_mariadbdatabase(self):
'''
Deletes specified MariaDB Database instance in the specified subscription and resource group.
:return: True
'''
self.log("Deleting the MariaDB Database instance {0}".format(self.name))
try:
response = self.mgmt_client.databases.delete(resource_group_name=self.resource_group,
server_name=self.server_name,
database_name=self.name)
except CloudError as e:
self.log('Error attempting to delete the MariaDB Database instance.')
self.fail("Error deleting the MariaDB Database instance: {0}".format(str(e)))
return True
def get_mariadbdatabase(self):
'''
Gets the properties of the specified MariaDB Database.
:return: deserialized MariaDB Database instance state dictionary
'''
self.log("Checking if the MariaDB Database instance {0} is present".format(self.name))
found = False
try:
response = self.mgmt_client.databases.get(resource_group_name=self.resource_group,
server_name=self.server_name,
database_name=self.name)
found = True
self.log("Response : {0}".format(response))
self.log("MariaDB Database instance : {0} found".format(response.name))
except CloudError as e:
self.log('Did not find the MariaDB Database instance.')
if found is True:
return response.as_dict()
return False
def main():
"""Main execution"""
AzureRMMariaDbDatabase()
if __name__ == '__main__':
main()

View file

@ -1,212 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2017 Zim Kalinowski, <zikalino@microsoft.com>
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbdatabase_info
version_added: "2.9"
short_description: Get Azure MariaDB Database facts
description:
- Get facts of MariaDB Database.
options:
resource_group:
description:
- The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
required: True
type: str
server_name:
description:
- The name of the server.
required: True
type: str
name:
description:
- The name of the database.
type: str
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Get instance of MariaDB Database
azure_rm_mariadbdatabase_info:
resource_group: myResourceGroup
server_name: server_name
name: database_name
- name: List instances of MariaDB Database
azure_rm_mariadbdatabase_info:
resource_group: myResourceGroup
server_name: server_name
'''
RETURN = '''
databases:
description:
- A list of dictionaries containing facts for MariaDB Databases.
returned: always
type: complex
contains:
id:
description:
- Resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/testser
ver/databases/db1"
resource_group:
description:
- Resource group name.
returned: always
type: str
sample: testrg
server_name:
description:
- Server name.
returned: always
type: str
sample: testserver
name:
description:
- Resource name.
returned: always
type: str
sample: db1
charset:
description:
- The charset of the database.
returned: always
type: str
sample: UTF8
collation:
description:
- The collation of the database.
returned: always
type: str
sample: English_United States.1252
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMMariaDbDatabaseInfo(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str'
)
)
# store the results of the module operation
self.results = dict(
changed=False
)
self.resource_group = None
self.server_name = None
self.name = None
super(AzureRMMariaDbDatabaseInfo, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_mariadbdatabase_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_mariadbdatabase_facts' module has been renamed to 'azure_rm_mariadbdatabase_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
if (self.resource_group is not None and
self.server_name is not None and
self.name is not None):
self.results['databases'] = self.get()
elif (self.resource_group is not None and
self.server_name is not None):
self.results['databases'] = self.list_by_server()
return self.results
def get(self):
response = None
results = []
try:
response = self.mariadb_client.databases.get(resource_group_name=self.resource_group,
server_name=self.server_name,
database_name=self.name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for Databases.')
if response is not None:
results.append(self.format_item(response))
return results
def list_by_server(self):
response = None
results = []
try:
response = self.mariadb_client.databases.list_by_server(resource_group_name=self.resource_group,
server_name=self.server_name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.fail("Error listing for server {0} - {1}".format(self.server_name, str(e)))
if response is not None:
for item in response:
results.append(self.format_item(item))
return results
def format_item(self, item):
d = item.as_dict()
d = {
'resource_group': self.resource_group,
'server_name': self.server_name,
'name': d['name'],
'charset': d['charset'],
'collation': d['collation']
}
return d
def main():
AzureRMMariaDbDatabaseInfo()
if __name__ == '__main__':
main()

View file

@ -1,277 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Zim Kalinowski, <zikalino@microsoft.com>
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbfirewallrule
version_added: "2.8"
short_description: Manage MariaDB firewall rule instance
description:
- Create, update and delete instance of MariaDB firewall rule.
options:
resource_group:
description:
- The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
required: True
server_name:
description:
- The name of the server.
required: True
name:
description:
- The name of the MariaDB firewall rule.
required: True
start_ip_address:
description:
- The start IP address of the MariaDB firewall rule. Must be IPv4 format.
end_ip_address:
description:
- The end IP address of the MariaDB firewall rule. Must be IPv4 format.
state:
description:
- Assert the state of the MariaDB firewall rule. Use C(present) to create or update a rule and C(absent) to ensure it is not present.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Create (or update) MariaDB firewall rule
azure_rm_mariadbfirewallrule:
resource_group: myResourceGroup
server_name: testserver
name: rule1
start_ip_address: 10.0.0.17
end_ip_address: 10.0.0.20
'''
RETURN = '''
id:
description:
- Resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/testserver/fire
wallRules/rule1"
'''
import time
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from msrest.polling import LROPoller
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class Actions:
NoAction, Create, Update, Delete = range(4)
class AzureRMMariaDbFirewallRule(AzureRMModuleBase):
"""Configuration class for an Azure RM MariaDB firewall rule resource"""
def __init__(self):
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str',
required=True
),
start_ip_address=dict(
type='str'
),
end_ip_address=dict(
type='str'
),
state=dict(
type='str',
default='present',
choices=['present', 'absent']
)
)
self.resource_group = None
self.server_name = None
self.name = None
self.start_ip_address = None
self.end_ip_address = None
self.results = dict(changed=False)
self.state = None
self.to_do = Actions.NoAction
super(AzureRMMariaDbFirewallRule, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=False)
def exec_module(self, **kwargs):
"""Main module execution method"""
for key in list(self.module_arg_spec.keys()):
if hasattr(self, key):
setattr(self, key, kwargs[key])
old_response = None
response = None
resource_group = self.get_resource_group(self.resource_group)
old_response = self.get_firewallrule()
if not old_response:
self.log("MariaDB firewall rule instance doesn't exist")
if self.state == 'absent':
self.log("Old instance didn't exist")
else:
self.to_do = Actions.Create
else:
self.log("MariaDB firewall rule instance already exists")
if self.state == 'absent':
self.to_do = Actions.Delete
elif self.state == 'present':
self.log("Need to check if MariaDB firewall rule instance has to be deleted or may be updated")
if (self.start_ip_address is not None) and (self.start_ip_address != old_response['start_ip_address']):
self.to_do = Actions.Update
if (self.end_ip_address is not None) and (self.end_ip_address != old_response['end_ip_address']):
self.to_do = Actions.Update
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
self.log("Need to Create / Update the MariaDB firewall rule instance")
if self.check_mode:
self.results['changed'] = True
return self.results
response = self.create_update_firewallrule()
if not old_response:
self.results['changed'] = True
else:
self.results['changed'] = old_response.__ne__(response)
self.log("Creation / Update done")
elif self.to_do == Actions.Delete:
self.log("MariaDB firewall rule instance deleted")
self.results['changed'] = True
if self.check_mode:
return self.results
self.delete_firewallrule()
# make sure instance is actually deleted, for some Azure resources, instance is hanging around
# for some time after deletion -- this should be really fixed in Azure
while self.get_firewallrule():
time.sleep(20)
else:
self.log("MariaDB firewall rule instance unchanged")
self.results['changed'] = False
response = old_response
if response:
self.results["id"] = response["id"]
return self.results
def create_update_firewallrule(self):
'''
Creates or updates MariaDB firewall rule with the specified configuration.
:return: deserialized MariaDB firewall rule instance state dictionary
'''
self.log("Creating / Updating the MariaDB firewall rule instance {0}".format(self.name))
try:
response = self.mariadb_client.firewall_rules.create_or_update(resource_group_name=self.resource_group,
server_name=self.server_name,
firewall_rule_name=self.name,
start_ip_address=self.start_ip_address,
end_ip_address=self.end_ip_address)
if isinstance(response, LROPoller):
response = self.get_poller_result(response)
except CloudError as exc:
self.log('Error attempting to create the MariaDB firewall rule instance.')
self.fail("Error creating the MariaDB firewall rule instance: {0}".format(str(exc)))
return response.as_dict()
def delete_firewallrule(self):
'''
Deletes specified MariaDB firewall rule instance in the specified subscription and resource group.
:return: True
'''
self.log("Deleting the MariaDB firewall rule instance {0}".format(self.name))
try:
response = self.mariadb_client.firewall_rules.delete(resource_group_name=self.resource_group,
server_name=self.server_name,
firewall_rule_name=self.name)
except CloudError as e:
self.log('Error attempting to delete the MariaDB firewall rule instance.')
self.fail("Error deleting the MariaDB firewall rule instance: {0}".format(str(e)))
return True
def get_firewallrule(self):
'''
Gets the properties of the specified MariaDB firewall rule.
:return: deserialized MariaDB firewall rule instance state dictionary
'''
self.log("Checking if the MariaDB firewall rule instance {0} is present".format(self.name))
found = False
try:
response = self.mariadb_client.firewall_rules.get(resource_group_name=self.resource_group,
server_name=self.server_name,
firewall_rule_name=self.name)
found = True
self.log("Response : {0}".format(response))
self.log("MariaDB firewall rule instance : {0} found".format(response.name))
except CloudError as e:
self.log('Did not find the MariaDB firewall rule instance.')
if found is True:
return response.as_dict()
return False
def main():
"""Main execution"""
AzureRMMariaDbFirewallRule()
if __name__ == '__main__':
main()

View file

@ -1,208 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Zim Kalinowski, <zikalino@microsoft.com>
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbfirewallrule_info
version_added: "2.9"
short_description: Get Azure MariaDB Firewall Rule facts
description:
- Get facts of Azure MariaDB Firewall Rule.
options:
resource_group:
description:
- The name of the resource group.
required: True
type: str
server_name:
description:
- The name of the server.
required: True
type: str
name:
description:
- The name of the server firewall rule.
type: str
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Get instance of MariaDB Firewall Rule
azure_rm_mariadbfirewallrule_info:
resource_group: myResourceGroup
server_name: server_name
name: firewall_rule_name
- name: List instances of MariaDB Firewall Rule
azure_rm_mariadbfirewallrule_info:
resource_group: myResourceGroup
server_name: server_name
'''
RETURN = '''
rules:
description:
- A list of dictionaries containing facts for MariaDB Firewall Rule.
returned: always
type: complex
contains:
id:
description:
- Resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/TestGroup/providers/Microsoft.DBforMariaDB/servers/testserver/fire
wallRules/rule1"
server_name:
description:
- The name of the server.
returned: always
type: str
sample: testserver
name:
description:
- Resource name.
returned: always
type: str
sample: rule1
start_ip_address:
description:
- The start IP address of the MariaDB firewall rule.
returned: always
type: str
sample: 10.0.0.16
end_ip_address:
description:
- The end IP address of the MariaDB firewall rule.
returned: always
type: str
sample: 10.0.0.18
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from msrestazure.azure_operation import AzureOperationPoller
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMMariaDbFirewallRuleInfo(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
server_name=dict(
type='str',
required=True
),
name=dict(
type='str'
)
)
# store the results of the module operation
self.results = dict(
changed=False
)
self.mgmt_client = None
self.resource_group = None
self.server_name = None
self.name = None
super(AzureRMMariaDbFirewallRuleInfo, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_mariadbfirewallrule_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_mariadbfirewallrule_facts' module has been renamed to 'azure_rm_mariadbfirewallrule_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
self.mgmt_client = self.get_mgmt_svc_client(MariaDBManagementClient,
base_url=self._cloud_environment.endpoints.resource_manager)
if (self.name is not None):
self.results['rules'] = self.get()
else:
self.results['rules'] = self.list_by_server()
return self.results
def get(self):
response = None
results = []
try:
response = self.mgmt_client.firewall_rules.get(resource_group_name=self.resource_group,
server_name=self.server_name,
firewall_rule_name=self.name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for FirewallRules.')
if response is not None:
results.append(self.format_item(response))
return results
def list_by_server(self):
response = None
results = []
try:
response = self.mgmt_client.firewall_rules.list_by_server(resource_group_name=self.resource_group,
server_name=self.server_name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for FirewallRules.')
if response is not None:
for item in response:
results.append(self.format_item(item))
return results
def format_item(self, item):
d = item.as_dict()
d = {
'resource_group': self.resource_group,
'id': d['id'],
'server_name': self.server_name,
'name': d['name'],
'start_ip_address': d['start_ip_address'],
'end_ip_address': d['end_ip_address']
}
return d
def main():
AzureRMMariaDbFirewallRuleInfo()
if __name__ == '__main__':
main()

View file

@ -1,265 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2017 Zim Kalinowski, <zikalino@microsoft.com>
# Copyright (c) 2019 Matti Ranta, (@techknowlogick)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_mariadbserver_info
version_added: "2.9"
short_description: Get Azure MariaDB Server facts
description:
- Get facts of MariaDB Server.
options:
resource_group:
description:
- The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal.
required: True
type: str
name:
description:
- The name of the server.
type: str
tags:
description:
- Limit results by providing a list of tags. Format tags as 'key' or 'key:value'.
type: list
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
- Matti Ranta (@techknowlogick)
'''
EXAMPLES = '''
- name: Get instance of MariaDB Server
azure_rm_mariadbserver_info:
resource_group: myResourceGroup
name: server_name
- name: List instances of MariaDB Server
azure_rm_mariadbserver_info:
resource_group: myResourceGroup
'''
RETURN = '''
servers:
description:
- A list of dictionaries containing facts for MariaDB servers.
returned: always
type: complex
contains:
id:
description:
- Resource ID.
returned: always
type: str
sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforMariaDB/servers/myabdud1223
resource_group:
description:
- Resource group name.
returned: always
type: str
sample: myResourceGroup
name:
description:
- Resource name.
returned: always
type: str
sample: myabdud1223
location:
description:
- The location the resource resides in.
returned: always
type: str
sample: eastus
sku:
description:
- The SKU of the server.
returned: always
type: complex
contains:
name:
description:
- The name of the SKU.
returned: always
type: str
sample: GP_Gen4_2
tier:
description:
- The tier of the particular SKU.
returned: always
type: str
sample: GeneralPurpose
capacity:
description:
- The scale capacity.
returned: always
type: int
sample: 2
storage_mb:
description:
- The maximum storage allowed for a server.
returned: always
type: int
sample: 128000
enforce_ssl:
description:
- Enable SSL enforcement.
returned: always
type: bool
sample: False
admin_username:
description:
- The administrator's login name of a server.
returned: always
type: str
sample: serveradmin
version:
description:
- Server version.
returned: always
type: str
sample: "9.6"
user_visible_state:
description:
- A state of a server that is visible to user.
returned: always
type: str
sample: Ready
fully_qualified_domain_name:
description:
- The fully qualified domain name of a server.
returned: always
type: str
sample: myabdud1223.mys.database.azure.com
tags:
description:
- Tags assigned to the resource. Dictionary of string:string pairs.
type: dict
sample: { tag1: abc }
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
try:
from msrestazure.azure_exceptions import CloudError
from azure.mgmt.rdbms.mariadb import MariaDBManagementClient
from msrest.serialization import Model
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMMariaDbServerInfo(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
resource_group=dict(
type='str',
required=True
),
name=dict(
type='str'
),
tags=dict(
type='list'
)
)
# store the results of the module operation
self.results = dict(
changed=False
)
self.resource_group = None
self.name = None
self.tags = None
super(AzureRMMariaDbServerInfo, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_mariadbserver_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_mariadbserver_facts' module has been renamed to 'azure_rm_mariadbserver_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
if (self.resource_group is not None and
self.name is not None):
self.results['servers'] = self.get()
elif (self.resource_group is not None):
self.results['servers'] = self.list_by_resource_group()
return self.results
def get(self):
response = None
results = []
try:
response = self.mariadb_client.servers.get(resource_group_name=self.resource_group,
server_name=self.name)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for MariaDB Server.')
if response and self.has_tags(response.tags, self.tags):
results.append(self.format_item(response))
return results
def list_by_resource_group(self):
response = None
results = []
try:
response = self.mariadb_client.servers.list_by_resource_group(resource_group_name=self.resource_group)
self.log("Response : {0}".format(response))
except CloudError as e:
self.log('Could not get facts for MariaDB Servers.')
if response is not None:
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(self.format_item(item))
return results
def format_item(self, item):
d = item.as_dict()
d = {
'id': d['id'],
'resource_group': self.resource_group,
'name': d['name'],
'sku': d['sku'],
'location': d['location'],
'storage_mb': d['storage_profile']['storage_mb'],
'version': d['version'],
'enforce_ssl': (d['ssl_enforcement'] == 'Enabled'),
'admin_username': d['administrator_login'],
'user_visible_state': d['user_visible_state'],
'fully_qualified_domain_name': d['fully_qualified_domain_name'],
'tags': d.get('tags')
}
return d
def main():
AzureRMMariaDbServerInfo()
if __name__ == '__main__':
main()

View file

@ -1,427 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Zim Kalinowski, <zikalino@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_resource
version_added: "2.6"
short_description: Create any Azure resource
description:
- Create, update or delete any Azure resource using Azure REST API.
- This module gives access to resources that are not supported via Ansible modules.
- Refer to U(https://docs.microsoft.com/en-us/rest/api/) regarding details related to specific resource REST API.
options:
url:
description:
- Azure RM Resource URL.
api_version:
description:
- Specific API version to be used.
provider:
description:
- Provider type.
- Required if URL is not specified.
resource_group:
description:
- Resource group to be used.
- Required if URL is not specified.
resource_type:
description:
- Resource type.
- Required if URL is not specified.
resource_name:
description:
- Resource name.
- Required if URL Is not specified.
subresource:
description:
- List of subresources.
suboptions:
namespace:
description:
- Subresource namespace.
type:
description:
- Subresource type.
name:
description:
- Subresource name.
body:
description:
- The body of the HTTP request/response to the web service.
method:
description:
- The HTTP method of the request or response. It must be uppercase.
choices:
- GET
- PUT
- POST
- HEAD
- PATCH
- DELETE
- MERGE
default: "PUT"
status_code:
description:
- A valid, numeric, HTTP status code that signifies success of the request. Can also be comma separated list of status codes.
type: list
default: [ 200, 201, 202 ]
idempotency:
description:
- If enabled, idempotency check will be done by using I(method=GET) first and then comparing with I(body).
default: no
type: bool
polling_timeout:
description:
- If enabled, idempotency check will be done by using I(method=GET) first and then comparing with I(body).
default: 0
type: int
version_added: "2.8"
polling_interval:
description:
- If enabled, idempotency check will be done by using I(method=GET) first and then comparing with I(body).
default: 60
type: int
version_added: "2.8"
state:
description:
- Assert the state of the resource. Use C(present) to create or update resource or C(absent) to delete resource.
default: present
choices:
- absent
- present
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
'''
EXAMPLES = '''
- name: Update scaleset info using azure_rm_resource
azure_rm_resource:
resource_group: myResourceGroup
provider: compute
resource_type: virtualmachinescalesets
resource_name: myVmss
api_version: "2017-12-01"
body: { body }
'''
RETURN = '''
response:
description:
- Response specific to resource type.
returned: always
type: complex
contains:
id:
description:
- Resource ID.
type: str
returned: always
sample: "/subscriptions/xxxx...xxxx/resourceGroups/v-xisuRG/providers/Microsoft.Storage/storageAccounts/staccb57dc95183"
kind:
description:
- The kind of storage.
type: str
returned: always
sample: Storage
location:
description:
- The resource location, defaults to location of the resource group.
type: str
returned: always
sample: eastus
name:
description:
The storage account name.
type: str
returned: always
sample: staccb57dc95183
properties:
description:
- The storage account's related properties.
type: dict
returned: always
sample: {
"creationTime": "2019-06-13T06:34:33.0996676Z",
"encryption": {
"keySource": "Microsoft.Storage",
"services": {
"blob": {
"enabled": true,
"lastEnabledTime": "2019-06-13T06:34:33.1934074Z"
},
"file": {
"enabled": true,
"lastEnabledTime": "2019-06-13T06:34:33.1934074Z"
}
}
},
"networkAcls": {
"bypass": "AzureServices",
"defaultAction": "Allow",
"ipRules": [],
"virtualNetworkRules": []
},
"primaryEndpoints": {
"blob": "https://staccb57dc95183.blob.core.windows.net/",
"file": "https://staccb57dc95183.file.core.windows.net/",
"queue": "https://staccb57dc95183.queue.core.windows.net/",
"table": "https://staccb57dc95183.table.core.windows.net/"
},
"primaryLocation": "eastus",
"provisioningState": "Succeeded",
"secondaryLocation": "westus",
"statusOfPrimary": "available",
"statusOfSecondary": "available",
"supportsHttpsTrafficOnly": false
}
sku:
description:
- The storage account SKU.
type: dict
returned: always
sample: {
"name": "Standard_GRS",
"tier": "Standard"
}
tags:
description:
- Resource tags.
type: dict
returned: always
sample: { 'key1': 'value1' }
type:
description:
- The resource type.
type: str
returned: always
sample: "Microsoft.Storage/storageAccounts"
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
from ansible.module_utils.azure_rm_common_rest import GenericRestClient
from ansible.module_utils.common.dict_transformations import dict_merge
try:
from msrestazure.azure_exceptions import CloudError
from msrest.service_client import ServiceClient
from msrestazure.tools import resource_id, is_valid_resource_id
import json
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMResource(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
url=dict(
type='str'
),
provider=dict(
type='str',
),
resource_group=dict(
type='str',
),
resource_type=dict(
type='str',
),
resource_name=dict(
type='str',
),
subresource=dict(
type='list',
default=[]
),
api_version=dict(
type='str'
),
method=dict(
type='str',
default='PUT',
choices=["GET", "PUT", "POST", "HEAD", "PATCH", "DELETE", "MERGE"]
),
body=dict(
type='raw'
),
status_code=dict(
type='list',
default=[200, 201, 202]
),
idempotency=dict(
type='bool',
default=False
),
polling_timeout=dict(
type='int',
default=0
),
polling_interval=dict(
type='int',
default=60
),
state=dict(
type='str',
default='present',
choices=['present', 'absent']
)
)
# store the results of the module operation
self.results = dict(
changed=False,
response=None
)
self.mgmt_client = None
self.url = None
self.api_version = None
self.provider = None
self.resource_group = None
self.resource_type = None
self.resource_name = None
self.subresource_type = None
self.subresource_name = None
self.subresource = []
self.method = None
self.status_code = []
self.idempotency = False
self.polling_timeout = None
self.polling_interval = None
self.state = None
self.body = None
super(AzureRMResource, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient,
base_url=self._cloud_environment.endpoints.resource_manager)
if self.state == 'absent':
self.method = 'DELETE'
self.status_code.append(204)
if self.url is None:
orphan = None
rargs = dict()
rargs['subscription'] = self.subscription_id
rargs['resource_group'] = self.resource_group
if not (self.provider is None or self.provider.lower().startswith('.microsoft')):
rargs['namespace'] = "Microsoft." + self.provider
else:
rargs['namespace'] = self.provider
if self.resource_type is not None and self.resource_name is not None:
rargs['type'] = self.resource_type
rargs['name'] = self.resource_name
for i in range(len(self.subresource)):
resource_ns = self.subresource[i].get('namespace', None)
resource_type = self.subresource[i].get('type', None)
resource_name = self.subresource[i].get('name', None)
if resource_type is not None and resource_name is not None:
rargs['child_namespace_' + str(i + 1)] = resource_ns
rargs['child_type_' + str(i + 1)] = resource_type
rargs['child_name_' + str(i + 1)] = resource_name
else:
orphan = resource_type
else:
orphan = self.resource_type
self.url = resource_id(**rargs)
if orphan is not None:
self.url += '/' + orphan
# if api_version was not specified, get latest one
if not self.api_version:
try:
# extract provider and resource type
if "/providers/" in self.url:
provider = self.url.split("/providers/")[1].split("/")[0]
resourceType = self.url.split(provider + "/")[1].split("/")[0]
url = "/subscriptions/" + self.subscription_id + "/providers/" + provider
api_versions = json.loads(self.mgmt_client.query(url, "GET", {'api-version': '2015-01-01'}, None, None, [200], 0, 0).text)
for rt in api_versions['resourceTypes']:
if rt['resourceType'].lower() == resourceType.lower():
self.api_version = rt['apiVersions'][0]
break
else:
# if there's no provider in API version, assume Microsoft.Resources
self.api_version = '2018-05-01'
if not self.api_version:
self.fail("Couldn't find api version for {0}/{1}".format(provider, resourceType))
except Exception as exc:
self.fail("Failed to obtain API version: {0}".format(str(exc)))
query_parameters = {}
query_parameters['api-version'] = self.api_version
header_parameters = {}
header_parameters['Content-Type'] = 'application/json; charset=utf-8'
needs_update = True
response = None
if self.idempotency:
original = self.mgmt_client.query(self.url, "GET", query_parameters, None, None, [200, 404], 0, 0)
if original.status_code == 404:
if self.state == 'absent':
needs_update = False
else:
try:
response = json.loads(original.text)
needs_update = (dict_merge(response, self.body) != response)
except Exception:
pass
if needs_update:
response = self.mgmt_client.query(self.url,
self.method,
query_parameters,
header_parameters,
self.body,
self.status_code,
self.polling_timeout,
self.polling_interval)
if self.state == 'present':
try:
response = json.loads(response.text)
except Exception:
response = response.text
else:
response = None
self.results['response'] = response
self.results['changed'] = needs_update
return self.results
def main():
AzureRMResource()
if __name__ == '__main__':
main()

View file

@ -1,432 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Zim Kalinowski, <zikalino@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_resource_info
version_added: "2.9"
short_description: Generic facts of Azure resources
description:
- Obtain facts of any resource using Azure REST API.
- This module gives access to resources that are not supported via Ansible modules.
- Refer to U(https://docs.microsoft.com/en-us/rest/api/) regarding details related to specific resource REST API.
options:
url:
description:
- Azure RM Resource URL.
api_version:
description:
- Specific API version to be used.
provider:
description:
- Provider type, should be specified in no URL is given.
resource_group:
description:
- Resource group to be used.
- Required if URL is not specified.
resource_type:
description:
- Resource type.
resource_name:
description:
- Resource name.
subresource:
description:
- List of subresources.
suboptions:
namespace:
description:
- Subresource namespace.
type:
description:
- Subresource type.
name:
description:
- Subresource name.
extends_documentation_fragment:
- azure
author:
- Zim Kalinowski (@zikalino)
'''
EXAMPLES = '''
- name: Get scaleset info
azure_rm_resource_info:
resource_group: myResourceGroup
provider: compute
resource_type: virtualmachinescalesets
resource_name: myVmss
api_version: "2017-12-01"
- name: Query all the resources in the resource group
azure_rm_resource_info:
resource_group: "{{ resource_group }}"
resource_type: resources
'''
RETURN = '''
response:
description:
- Response specific to resource type.
returned: always
type: complex
contains:
id:
description:
- Id of the Azure resource.
type: str
returned: always
sample: "/subscriptions/xxxx...xxxx/resourceGroups/v-xisuRG/providers/Microsoft.Compute/virtualMachines/myVM"
location:
description:
- Resource location.
type: str
returned: always
sample: eastus
name:
description:
- Resource name.
type: str
returned: always
sample: myVM
properties:
description:
- Specifies the virtual machine's property.
type: complex
returned: always
contains:
diagnosticsProfile:
description:
- Specifies the boot diagnostic settings state.
type: complex
returned: always
contains:
bootDiagnostics:
description:
- A debugging feature, which to view Console Output and Screenshot to diagnose VM status.
type: dict
returned: always
sample: {
"enabled": true,
"storageUri": "https://vxisurgdiag.blob.core.windows.net/"
}
hardwareProfile:
description:
- Specifies the hardware settings for the virtual machine.
type: dict
returned: always
sample: {
"vmSize": "Standard_D2s_v3"
}
networkProfile:
description:
- Specifies the network interfaces of the virtual machine.
type: complex
returned: always
contains:
networkInterfaces:
description:
- Describes a network interface reference.
type: list
returned: always
sample:
- {
"id": "/subscriptions/xxxx...xxxx/resourceGroups/v-xisuRG/providers/Microsoft.Network/networkInterfaces/myvm441"
}
osProfile:
description:
- Specifies the operating system settings for the virtual machine.
type: complex
returned: always
contains:
adminUsername:
description:
- Specifies the name of the administrator account.
type: str
returned: always
sample: azureuser
allowExtensionOperations:
description:
- Specifies whether extension operations should be allowed on the virtual machine.
- This may only be set to False when no extensions are present on the virtual machine.
type: bool
returned: always
sample: true
computerName:
description:
- Specifies the host OS name of the virtual machine.
type: str
returned: always
sample: myVM
requireGuestProvisionSignale:
description:
- Specifies the host require guest provision signal or not.
type: bool
returned: always
sample: true
secrets:
description:
- Specifies set of certificates that should be installed onto the virtual machine.
type: list
returned: always
sample: []
linuxConfiguration:
description:
- Specifies the Linux operating system settings on the virtual machine.
type: dict
returned: when OS type is Linux
sample: {
"disablePasswordAuthentication": false,
"provisionVMAgent": true
}
provisioningState:
description:
- The provisioning state.
type: str
returned: always
sample: Succeeded
vmID:
description:
- Specifies the VM unique ID which is a 128-bits identifier that is encoded and stored in all Azure laaS VMs SMBIOS.
- It can be read using platform BIOS commands.
type: str
returned: always
sample: "eb86d9bb-6725-4787-a487-2e497d5b340c"
storageProfile:
description:
- Specifies the storage account type for the managed disk.
type: complex
returned: always
contains:
dataDisks:
description:
- Specifies the parameters that are used to add a data disk to virtual machine.
type: list
returned: always
sample:
- {
"caching": "None",
"createOption": "Attach",
"diskSizeGB": 1023,
"lun": 2,
"managedDisk": {
"id": "/subscriptions/xxxx....xxxx/resourceGroups/V-XISURG/providers/Microsoft.Compute/disks/testdisk2",
"storageAccountType": "StandardSSD_LRS"
},
"name": "testdisk2"
}
- {
"caching": "None",
"createOption": "Attach",
"diskSizeGB": 1023,
"lun": 1,
"managedDisk": {
"id": "/subscriptions/xxxx...xxxx/resourceGroups/V-XISURG/providers/Microsoft.Compute/disks/testdisk3",
"storageAccountType": "StandardSSD_LRS"
},
"name": "testdisk3"
}
imageReference:
description:
- Specifies information about the image to use.
type: dict
returned: always
sample: {
"offer": "UbuntuServer",
"publisher": "Canonical",
"sku": "18.04-LTS",
"version": "latest"
}
osDisk:
description:
- Specifies information about the operating system disk used by the virtual machine.
type: dict
returned: always
sample: {
"caching": "ReadWrite",
"createOption": "FromImage",
"diskSizeGB": 30,
"managedDisk": {
"id": "/subscriptions/xxx...xxxx/resourceGroups/v-xisuRG/providers/Microsoft.Compute/disks/myVM_disk1_xxx",
"storageAccountType": "Premium_LRS"
},
"name": "myVM_disk1_xxx",
"osType": "Linux"
}
type:
description:
- The type of identity used for the virtual machine.
type: str
returned: always
sample: "Microsoft.Compute/virtualMachines"
'''
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
from ansible.module_utils.azure_rm_common_rest import GenericRestClient
try:
from msrestazure.azure_exceptions import CloudError
from msrest.service_client import ServiceClient
from msrestazure.tools import resource_id, is_valid_resource_id
import json
except ImportError:
# This is handled in azure_rm_common
pass
class AzureRMResourceInfo(AzureRMModuleBase):
def __init__(self):
# define user inputs into argument
self.module_arg_spec = dict(
url=dict(
type='str'
),
provider=dict(
type='str'
),
resource_group=dict(
type='str'
),
resource_type=dict(
type='str'
),
resource_name=dict(
type='str'
),
subresource=dict(
type='list',
default=[]
),
api_version=dict(
type='str'
)
)
# store the results of the module operation
self.results = dict(
response=[]
)
self.mgmt_client = None
self.url = None
self.api_version = None
self.provider = None
self.resource_group = None
self.resource_type = None
self.resource_name = None
self.subresource = []
super(AzureRMResourceInfo, self).__init__(self.module_arg_spec, supports_tags=False)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_resource_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_resource_facts' module has been renamed to 'azure_rm_resource_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient,
base_url=self._cloud_environment.endpoints.resource_manager)
if self.url is None:
orphan = None
rargs = dict()
rargs['subscription'] = self.subscription_id
rargs['resource_group'] = self.resource_group
if not (self.provider is None or self.provider.lower().startswith('.microsoft')):
rargs['namespace'] = "Microsoft." + self.provider
else:
rargs['namespace'] = self.provider
if self.resource_type is not None and self.resource_name is not None:
rargs['type'] = self.resource_type
rargs['name'] = self.resource_name
for i in range(len(self.subresource)):
resource_ns = self.subresource[i].get('namespace', None)
resource_type = self.subresource[i].get('type', None)
resource_name = self.subresource[i].get('name', None)
if resource_type is not None and resource_name is not None:
rargs['child_namespace_' + str(i + 1)] = resource_ns
rargs['child_type_' + str(i + 1)] = resource_type
rargs['child_name_' + str(i + 1)] = resource_name
else:
orphan = resource_type
else:
orphan = self.resource_type
self.url = resource_id(**rargs)
if orphan is not None:
self.url += '/' + orphan
# if api_version was not specified, get latest one
if not self.api_version:
try:
# extract provider and resource type
if "/providers/" in self.url:
provider = self.url.split("/providers/")[1].split("/")[0]
resourceType = self.url.split(provider + "/")[1].split("/")[0]
url = "/subscriptions/" + self.subscription_id + "/providers/" + provider
api_versions = json.loads(self.mgmt_client.query(url, "GET", {'api-version': '2015-01-01'}, None, None, [200], 0, 0).text)
for rt in api_versions['resourceTypes']:
if rt['resourceType'].lower() == resourceType.lower():
self.api_version = rt['apiVersions'][0]
break
else:
# if there's no provider in API version, assume Microsoft.Resources
self.api_version = '2018-05-01'
if not self.api_version:
self.fail("Couldn't find api version for {0}/{1}".format(provider, resourceType))
except Exception as exc:
self.fail("Failed to obtain API version: {0}".format(str(exc)))
self.results['url'] = self.url
query_parameters = {}
query_parameters['api-version'] = self.api_version
header_parameters = {}
header_parameters['Content-Type'] = 'application/json; charset=utf-8'
skiptoken = None
while True:
if skiptoken:
query_parameters['skiptoken'] = skiptoken
response = self.mgmt_client.query(self.url, "GET", query_parameters, header_parameters, None, [200, 404], 0, 0)
try:
response = json.loads(response.text)
if isinstance(response, dict):
if response.get('value'):
self.results['response'] = self.results['response'] + response['value']
skiptoken = response.get('nextLink')
else:
self.results['response'] = self.results['response'] + [response]
except Exception as e:
self.fail('Failed to parse response: ' + str(e))
if not skiptoken:
break
return self.results
def main():
AzureRMResourceInfo()
if __name__ == '__main__':
main()

View file

@ -1,684 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2016 Matt Davis, <mdavis@ansible.com>
# Chris Houseknecht, <house@redhat.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_storageaccount
version_added: "2.1"
short_description: Manage Azure storage accounts
description:
- Create, update or delete a storage account.
options:
resource_group:
description:
- Name of the resource group to use.
required: true
aliases:
- resource_group_name
name:
description:
- Name of the storage account to update or create.
state:
description:
- State of the storage account. Use C(present) to create or update a storage account and use C(absent) to delete an account.
default: present
choices:
- absent
- present
location:
description:
- Valid Azure location. Defaults to location of the resource group.
account_type:
description:
- Type of storage account. Required when creating a storage account.
- C(Standard_ZRS) and C(Premium_LRS) accounts cannot be changed to other account types.
- Other account types cannot be changed to C(Standard_ZRS) or C(Premium_LRS).
choices:
- Premium_LRS
- Standard_GRS
- Standard_LRS
- StandardSSD_LRS
- Standard_RAGRS
- Standard_ZRS
- Premium_ZRS
aliases:
- type
custom_domain:
description:
- User domain assigned to the storage account.
- Must be a dictionary with I(name) and I(use_sub_domain) keys where I(name) is the CNAME source.
- Only one custom domain is supported per storage account at this time.
- To clear the existing custom domain, use an empty string for the custom domain name property.
- Can be added to an existing storage account. Will be ignored during storage account creation.
aliases:
- custom_dns_domain_suffix
kind:
description:
- The kind of storage.
default: 'Storage'
choices:
- Storage
- StorageV2
- BlobStorage
version_added: "2.2"
access_tier:
description:
- The access tier for this storage account. Required when I(kind=BlobStorage).
choices:
- Hot
- Cool
version_added: "2.4"
force_delete_nonempty:
description:
- Attempt deletion if resource already exists and cannot be updated.
type: bool
aliases:
- force
https_only:
description:
- Allows https traffic only to storage service when set to C(true).
type: bool
version_added: "2.8"
blob_cors:
description:
- Specifies CORS rules for the Blob service.
- You can include up to five CorsRule elements in the request.
- If no blob_cors elements are included in the argument list, nothing about CORS will be changed.
- If you want to delete all CORS rules and disable CORS for the Blob service, explicitly set I(blob_cors=[]).
type: list
version_added: "2.8"
suboptions:
allowed_origins:
description:
- A list of origin domains that will be allowed via CORS, or "*" to allow all domains.
type: list
required: true
allowed_methods:
description:
- A list of HTTP methods that are allowed to be executed by the origin.
type: list
required: true
max_age_in_seconds:
description:
- The number of seconds that the client/browser should cache a preflight response.
type: int
required: true
exposed_headers:
description:
- A list of response headers to expose to CORS clients.
type: list
required: true
allowed_headers:
description:
- A list of headers allowed to be part of the cross-origin request.
type: list
required: true
extends_documentation_fragment:
- azure
- azure_tags
author:
- Chris Houseknecht (@chouseknecht)
- Matt Davis (@nitzmahone)
'''
EXAMPLES = '''
- name: remove account, if it exists
azure_rm_storageaccount:
resource_group: myResourceGroup
name: clh0002
state: absent
- name: create an account
azure_rm_storageaccount:
resource_group: myResourceGroup
name: clh0002
type: Standard_RAGRS
tags:
testing: testing
delete: on-exit
- name: create an account with blob CORS
azure_rm_storageaccount:
resource_group: myResourceGroup
name: clh002
type: Standard_RAGRS
blob_cors:
- allowed_origins:
- http://www.example.com/
allowed_methods:
- GET
- POST
allowed_headers:
- x-ms-meta-data*
- x-ms-meta-target*
- x-ms-meta-abc
exposed_headers:
- x-ms-meta-*
max_age_in_seconds: 200
'''
RETURN = '''
state:
description:
- Current state of the storage account.
returned: always
type: complex
contains:
account_type:
description:
- Type of storage account.
returned: always
type: str
sample: Standard_RAGRS
custom_domain:
description:
- User domain assigned to the storage account.
returned: always
type: complex
contains:
name:
description:
- CNAME source.
returned: always
type: str
sample: testaccount
use_sub_domain:
description:
- Whether to use sub domain.
returned: always
type: bool
sample: true
id:
description:
- Resource ID.
returned: always
type: str
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/clh0003"
location:
description:
- Valid Azure location. Defaults to location of the resource group.
returned: always
type: str
sample: eastus2
name:
description:
- Name of the storage account to update or create.
returned: always
type: str
sample: clh0003
primary_endpoints:
description:
- The URLs to retrieve the public I(blob), I(queue), or I(table) object from the primary location.
returned: always
type: dict
sample: {
"blob": "https://clh0003.blob.core.windows.net/",
"queue": "https://clh0003.queue.core.windows.net/",
"table": "https://clh0003.table.core.windows.net/"
}
primary_location:
description:
- The location of the primary data center for the storage account.
returned: always
type: str
sample: eastus2
provisioning_state:
description:
- The status of the storage account.
- Possible values include C(Creating), C(ResolvingDNS), C(Succeeded).
returned: always
type: str
sample: Succeeded
resource_group:
description:
- The resource group's name.
returned: always
type: str
sample: Testing
secondary_endpoints:
description:
- The URLs to retrieve the public I(blob), I(queue), or I(table) object from the secondary location.
returned: always
type: dict
sample: {
"blob": "https://clh0003-secondary.blob.core.windows.net/",
"queue": "https://clh0003-secondary.queue.core.windows.net/",
"table": "https://clh0003-secondary.table.core.windows.net/"
}
secondary_location:
description:
- The location of the geo-replicated secondary for the storage account.
returned: always
type: str
sample: centralus
status_of_primary:
description:
- The status of the primary location of the storage account; either C(available) or C(unavailable).
returned: always
type: str
sample: available
status_of_secondary:
description:
- The status of the secondary location of the storage account; either C(available) or C(unavailable).
returned: always
type: str
sample: available
tags:
description:
- Resource tags.
returned: always
type: dict
sample: { 'tags1': 'value1' }
type:
description:
- The storage account type.
returned: always
type: str
sample: "Microsoft.Storage/storageAccounts"
'''
try:
from msrestazure.azure_exceptions import CloudError
from azure.storage.cloudstorageaccount import CloudStorageAccount
from azure.common import AzureMissingResourceHttpError
except ImportError:
# This is handled in azure_rm_common
pass
import copy
from ansible.module_utils.azure_rm_common import AZURE_SUCCESS_STATE, AzureRMModuleBase
from ansible.module_utils._text import to_native
cors_rule_spec = dict(
allowed_origins=dict(type='list', elements='str', required=True),
allowed_methods=dict(type='list', elements='str', required=True),
max_age_in_seconds=dict(type='int', required=True),
exposed_headers=dict(type='list', elements='str', required=True),
allowed_headers=dict(type='list', elements='str', required=True),
)
def compare_cors(cors1, cors2):
if len(cors1) != len(cors2):
return False
copy2 = copy.copy(cors2)
for rule1 in cors1:
matched = False
for rule2 in copy2:
if (rule1['max_age_in_seconds'] == rule2['max_age_in_seconds']
and set(rule1['allowed_methods']) == set(rule2['allowed_methods'])
and set(rule1['allowed_origins']) == set(rule2['allowed_origins'])
and set(rule1['allowed_headers']) == set(rule2['allowed_headers'])
and set(rule1['exposed_headers']) == set(rule2['exposed_headers'])):
matched = True
copy2.remove(rule2)
if not matched:
return False
return True
class AzureRMStorageAccount(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
account_type=dict(type='str',
choices=['Premium_LRS', 'Standard_GRS', 'Standard_LRS', 'StandardSSD_LRS', 'Standard_RAGRS', 'Standard_ZRS', 'Premium_ZRS'],
aliases=['type']),
custom_domain=dict(type='dict', aliases=['custom_dns_domain_suffix']),
location=dict(type='str'),
name=dict(type='str', required=True),
resource_group=dict(required=True, type='str', aliases=['resource_group_name']),
state=dict(default='present', choices=['present', 'absent']),
force_delete_nonempty=dict(type='bool', default=False, aliases=['force']),
tags=dict(type='dict'),
kind=dict(type='str', default='Storage', choices=['Storage', 'StorageV2', 'BlobStorage']),
access_tier=dict(type='str', choices=['Hot', 'Cool']),
https_only=dict(type='bool', default=False),
blob_cors=dict(type='list', options=cors_rule_spec, elements='dict')
)
self.results = dict(
changed=False,
state=dict()
)
self.account_dict = None
self.resource_group = None
self.name = None
self.state = None
self.location = None
self.account_type = None
self.custom_domain = None
self.tags = None
self.force_delete_nonempty = None
self.kind = None
self.access_tier = None
self.https_only = None
self.blob_cors = None
super(AzureRMStorageAccount, self).__init__(self.module_arg_spec,
supports_check_mode=True)
def exec_module(self, **kwargs):
for key in list(self.module_arg_spec.keys()) + ['tags']:
setattr(self, key, kwargs[key])
resource_group = self.get_resource_group(self.resource_group)
if not self.location:
# Set default location
self.location = resource_group.location
if len(self.name) < 3 or len(self.name) > 24:
self.fail("Parameter error: name length must be between 3 and 24 characters.")
if self.custom_domain:
if self.custom_domain.get('name', None) is None:
self.fail("Parameter error: expecting custom_domain to have a name attribute of type string.")
if self.custom_domain.get('use_sub_domain', None) is None:
self.fail("Parameter error: expecting custom_domain to have a use_sub_domain "
"attribute of type boolean.")
self.account_dict = self.get_account()
if self.state == 'present' and self.account_dict and \
self.account_dict['provisioning_state'] != AZURE_SUCCESS_STATE:
self.fail("Error: storage account {0} has not completed provisioning. State is {1}. Expecting state "
"to be {2}.".format(self.name, self.account_dict['provisioning_state'], AZURE_SUCCESS_STATE))
if self.account_dict is not None:
self.results['state'] = self.account_dict
else:
self.results['state'] = dict()
if self.state == 'present':
if not self.account_dict:
self.results['state'] = self.create_account()
else:
self.update_account()
elif self.state == 'absent' and self.account_dict:
self.delete_account()
self.results['state'] = dict(Status='Deleted')
return self.results
def check_name_availability(self):
self.log('Checking name availability for {0}'.format(self.name))
try:
response = self.storage_client.storage_accounts.check_name_availability(self.name)
except CloudError as e:
self.log('Error attempting to validate name.')
self.fail("Error checking name availability: {0}".format(str(e)))
if not response.name_available:
self.log('Error name not available.')
self.fail("{0} - {1}".format(response.message, response.reason))
def get_account(self):
self.log('Get properties for account {0}'.format(self.name))
account_obj = None
blob_service_props = None
account_dict = None
try:
account_obj = self.storage_client.storage_accounts.get_properties(self.resource_group, self.name)
blob_service_props = self.storage_client.blob_services.get_service_properties(self.resource_group, self.name)
except CloudError:
pass
if account_obj:
account_dict = self.account_obj_to_dict(account_obj, blob_service_props)
return account_dict
def account_obj_to_dict(self, account_obj, blob_service_props=None):
account_dict = dict(
id=account_obj.id,
name=account_obj.name,
location=account_obj.location,
resource_group=self.resource_group,
type=account_obj.type,
access_tier=(account_obj.access_tier.value
if account_obj.access_tier is not None else None),
sku_tier=account_obj.sku.tier.value,
sku_name=account_obj.sku.name.value,
provisioning_state=account_obj.provisioning_state.value,
secondary_location=account_obj.secondary_location,
status_of_primary=(account_obj.status_of_primary.value
if account_obj.status_of_primary is not None else None),
status_of_secondary=(account_obj.status_of_secondary.value
if account_obj.status_of_secondary is not None else None),
primary_location=account_obj.primary_location,
https_only=account_obj.enable_https_traffic_only
)
account_dict['custom_domain'] = None
if account_obj.custom_domain:
account_dict['custom_domain'] = dict(
name=account_obj.custom_domain.name,
use_sub_domain=account_obj.custom_domain.use_sub_domain
)
account_dict['primary_endpoints'] = None
if account_obj.primary_endpoints:
account_dict['primary_endpoints'] = dict(
blob=account_obj.primary_endpoints.blob,
queue=account_obj.primary_endpoints.queue,
table=account_obj.primary_endpoints.table
)
account_dict['secondary_endpoints'] = None
if account_obj.secondary_endpoints:
account_dict['secondary_endpoints'] = dict(
blob=account_obj.secondary_endpoints.blob,
queue=account_obj.secondary_endpoints.queue,
table=account_obj.secondary_endpoints.table
)
account_dict['tags'] = None
if account_obj.tags:
account_dict['tags'] = account_obj.tags
if blob_service_props and blob_service_props.cors and blob_service_props.cors.cors_rules:
account_dict['blob_cors'] = [dict(
allowed_origins=[to_native(y) for y in x.allowed_origins],
allowed_methods=[to_native(y) for y in x.allowed_methods],
max_age_in_seconds=x.max_age_in_seconds,
exposed_headers=[to_native(y) for y in x.exposed_headers],
allowed_headers=[to_native(y) for y in x.allowed_headers]
) for x in blob_service_props.cors.cors_rules]
return account_dict
def update_account(self):
self.log('Update storage account {0}'.format(self.name))
if bool(self.https_only) != bool(self.account_dict.get('https_only')):
self.results['changed'] = True
self.account_dict['https_only'] = self.https_only
if not self.check_mode:
try:
parameters = self.storage_models.StorageAccountUpdateParameters(enable_https_traffic_only=self.https_only)
self.storage_client.storage_accounts.update(self.resource_group,
self.name,
parameters)
except Exception as exc:
self.fail("Failed to update account type: {0}".format(str(exc)))
if self.account_type:
if self.account_type != self.account_dict['sku_name']:
# change the account type
SkuName = self.storage_models.SkuName
if self.account_dict['sku_name'] in [SkuName.premium_lrs, SkuName.standard_zrs]:
self.fail("Storage accounts of type {0} and {1} cannot be changed.".format(
SkuName.premium_lrs, SkuName.standard_zrs))
if self.account_type in [SkuName.premium_lrs, SkuName.standard_zrs]:
self.fail("Storage account of type {0} cannot be changed to a type of {1} or {2}.".format(
self.account_dict['sku_name'], SkuName.premium_lrs, SkuName.standard_zrs))
self.results['changed'] = True
self.account_dict['sku_name'] = self.account_type
if self.results['changed'] and not self.check_mode:
# Perform the update. The API only allows changing one attribute per call.
try:
self.log("sku_name: %s" % self.account_dict['sku_name'])
self.log("sku_tier: %s" % self.account_dict['sku_tier'])
sku = self.storage_models.Sku(name=SkuName(self.account_dict['sku_name']))
sku.tier = self.storage_models.SkuTier(self.account_dict['sku_tier'])
parameters = self.storage_models.StorageAccountUpdateParameters(sku=sku)
self.storage_client.storage_accounts.update(self.resource_group,
self.name,
parameters)
except Exception as exc:
self.fail("Failed to update account type: {0}".format(str(exc)))
if self.custom_domain:
if not self.account_dict['custom_domain'] or self.account_dict['custom_domain'] != self.custom_domain:
self.results['changed'] = True
self.account_dict['custom_domain'] = self.custom_domain
if self.results['changed'] and not self.check_mode:
new_domain = self.storage_models.CustomDomain(name=self.custom_domain['name'],
use_sub_domain=self.custom_domain['use_sub_domain'])
parameters = self.storage_models.StorageAccountUpdateParameters(custom_domain=new_domain)
try:
self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters)
except Exception as exc:
self.fail("Failed to update custom domain: {0}".format(str(exc)))
if self.access_tier:
if not self.account_dict['access_tier'] or self.account_dict['access_tier'] != self.access_tier:
self.results['changed'] = True
self.account_dict['access_tier'] = self.access_tier
if self.results['changed'] and not self.check_mode:
parameters = self.storage_models.StorageAccountUpdateParameters(access_tier=self.access_tier)
try:
self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters)
except Exception as exc:
self.fail("Failed to update access tier: {0}".format(str(exc)))
update_tags, self.account_dict['tags'] = self.update_tags(self.account_dict['tags'])
if update_tags:
self.results['changed'] = True
if not self.check_mode:
parameters = self.storage_models.StorageAccountUpdateParameters(tags=self.account_dict['tags'])
try:
self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters)
except Exception as exc:
self.fail("Failed to update tags: {0}".format(str(exc)))
if self.blob_cors and not compare_cors(self.account_dict.get('blob_cors', []), self.blob_cors):
self.results['changed'] = True
if not self.check_mode:
self.set_blob_cors()
def create_account(self):
self.log("Creating account {0}".format(self.name))
if not self.location:
self.fail('Parameter error: location required when creating a storage account.')
if not self.account_type:
self.fail('Parameter error: account_type required when creating a storage account.')
if not self.access_tier and self.kind == 'BlobStorage':
self.fail('Parameter error: access_tier required when creating a storage account of type BlobStorage.')
self.check_name_availability()
self.results['changed'] = True
if self.check_mode:
account_dict = dict(
location=self.location,
account_type=self.account_type,
name=self.name,
resource_group=self.resource_group,
enable_https_traffic_only=self.https_only,
tags=dict()
)
if self.tags:
account_dict['tags'] = self.tags
if self.blob_cors:
account_dict['blob_cors'] = self.blob_cors
return account_dict
sku = self.storage_models.Sku(name=self.storage_models.SkuName(self.account_type))
sku.tier = self.storage_models.SkuTier.standard if 'Standard' in self.account_type else \
self.storage_models.SkuTier.premium
parameters = self.storage_models.StorageAccountCreateParameters(sku=sku,
kind=self.kind,
location=self.location,
tags=self.tags,
access_tier=self.access_tier)
self.log(str(parameters))
try:
poller = self.storage_client.storage_accounts.create(self.resource_group, self.name, parameters)
self.get_poller_result(poller)
except CloudError as e:
self.log('Error creating storage account.')
self.fail("Failed to create account: {0}".format(str(e)))
if self.blob_cors:
self.set_blob_cors()
# the poller doesn't actually return anything
return self.get_account()
def delete_account(self):
if self.account_dict['provisioning_state'] == self.storage_models.ProvisioningState.succeeded.value and \
not self.force_delete_nonempty and self.account_has_blob_containers():
self.fail("Account contains blob containers. Is it in use? Use the force_delete_nonempty option to attempt deletion.")
self.log('Delete storage account {0}'.format(self.name))
self.results['changed'] = True
if not self.check_mode:
try:
status = self.storage_client.storage_accounts.delete(self.resource_group, self.name)
self.log("delete status: ")
self.log(str(status))
except CloudError as e:
self.fail("Failed to delete the account: {0}".format(str(e)))
return True
def account_has_blob_containers(self):
'''
If there are blob containers, then there are likely VMs depending on this account and it should
not be deleted.
'''
self.log('Checking for existing blob containers')
blob_service = self.get_blob_client(self.resource_group, self.name)
try:
response = blob_service.list_containers()
except AzureMissingResourceHttpError:
# No blob storage available?
return False
if len(response.items) > 0:
return True
return False
def set_blob_cors(self):
try:
cors_rules = self.storage_models.CorsRules(cors_rules=[self.storage_models.CorsRule(**x) for x in self.blob_cors])
self.storage_client.blob_services.set_service_properties(self.resource_group,
self.name,
self.storage_models.BlobServiceProperties(cors=cors_rules))
except Exception as exc:
self.fail("Failed to set CORS rules: {0}".format(str(exc)))
def main():
AzureRMStorageAccount()
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load diff

View file

@ -1,489 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) 2018 Yunge Zhu, <yungez@microsoft.com>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: azure_rm_webapp_info
version_added: "2.9"
short_description: Get Azure web app facts
description:
- Get facts for a specific web app or all web app in a resource group, or all web app in current subscription.
options:
name:
description:
- Only show results for a specific web app.
resource_group:
description:
- Limit results by resource group.
return_publish_profile:
description:
- Indicate whether to return publishing profile of the web app.
default: False
type: bool
tags:
description:
- Limit results by providing a list of tags. Format tags as 'key' or 'key:value'.
extends_documentation_fragment:
- azure
author:
- Yunge Zhu (@yungezz)
'''
EXAMPLES = '''
- name: Get facts for web app by name
azure_rm_webapp_info:
resource_group: myResourceGroup
name: winwebapp1
- name: Get facts for web apps in resource group
azure_rm_webapp_info:
resource_group: myResourceGroup
- name: Get facts for web apps with tags
azure_rm_webapp_info:
tags:
- testtag
- foo:bar
'''
RETURN = '''
webapps:
description:
- List of web apps.
returned: always
type: complex
contains:
id:
description:
- ID of the web app.
returned: always
type: str
sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myWebApp
name:
description:
- Name of the web app.
returned: always
type: str
sample: winwebapp1
resource_group:
description:
- Resource group of the web app.
returned: always
type: str
sample: myResourceGroup
location:
description:
- Location of the web app.
returned: always
type: str
sample: eastus
plan:
description:
- ID of app service plan used by the web app.
returned: always
type: str
sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan
app_settings:
description:
- App settings of the application. Only returned when web app has app settings.
returned: always
type: dict
sample: {
"testkey": "testvalue",
"testkey2": "testvalue2"
}
frameworks:
description:
- Frameworks of the application. Only returned when web app has frameworks.
returned: always
type: list
sample: [
{
"name": "net_framework",
"version": "v4.0"
},
{
"name": "java",
"settings": {
"java_container": "tomcat",
"java_container_version": "8.5"
},
"version": "1.7"
},
{
"name": "php",
"version": "5.6"
}
]
availability_state:
description:
- Availability of this web app.
returned: always
type: str
sample: Normal
default_host_name:
description:
- Host name of the web app.
returned: always
type: str
sample: vxxisurg397winapp4.azurewebsites.net
enabled:
description:
- Indicates the web app enabled or not.
returned: always
type: bool
sample: true
enabled_host_names:
description:
- Enabled host names of the web app.
returned: always
type: list
sample: [
"vxxisurg397winapp4.azurewebsites.net",
"vxxisurg397winapp4.scm.azurewebsites.net"
]
host_name_ssl_states:
description:
- SSL state per host names of the web app.
returned: always
type: list
sample: [
{
"hostType": "Standard",
"name": "vxxisurg397winapp4.azurewebsites.net",
"sslState": "Disabled"
},
{
"hostType": "Repository",
"name": "vxxisurg397winapp4.scm.azurewebsites.net",
"sslState": "Disabled"
}
]
host_names:
description:
- Host names of the web app.
returned: always
type: list
sample: [
"vxxisurg397winapp4.azurewebsites.net"
]
outbound_ip_addresses:
description:
- Outbound IP address of the web app.
returned: always
type: str
sample: "40.71.11.131,40.85.166.200,168.62.166.67,137.135.126.248,137.135.121.45"
ftp_publish_url:
description:
- Publishing URL of the web app when deployment type is FTP.
returned: always
type: str
sample: ftp://xxxx.ftp.azurewebsites.windows.net
state:
description:
- State of the web app.
returned: always
type: str
sample: running
publishing_username:
description:
- Publishing profile user name.
returned: only when I(return_publish_profile=True).
type: str
sample: "$vxxisuRG397winapp4"
publishing_password:
description:
- Publishing profile password.
returned: only when I(return_publish_profile=True).
type: str
sample: "uvANsPQpGjWJmrFfm4Ssd5rpBSqGhjMk11pMSgW2vCsQtNx9tcgZ0xN26s9A"
tags:
description:
- Tags assigned to the resource. Dictionary of string:string pairs.
returned: always
type: dict
sample: { tag1: abc }
'''
try:
from msrestazure.azure_exceptions import CloudError
from msrest.polling import LROPoller
from azure.common import AzureMissingResourceHttpError, AzureHttpError
except Exception:
# This is handled in azure_rm_common
pass
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
AZURE_OBJECT_CLASS = 'WebApp'
class AzureRMWebAppInfo(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
name=dict(type='str'),
resource_group=dict(type='str'),
tags=dict(type='list'),
return_publish_profile=dict(type='bool', default=False),
)
self.results = dict(
changed=False,
webapps=[],
)
self.name = None
self.resource_group = None
self.tags = None
self.return_publish_profile = False
self.framework_names = ['net_framework', 'java', 'php', 'node', 'python', 'dotnetcore', 'ruby']
super(AzureRMWebAppInfo, self).__init__(self.module_arg_spec,
supports_tags=False,
facts_module=True)
def exec_module(self, **kwargs):
is_old_facts = self.module._name == 'azure_rm_webapp_facts'
if is_old_facts:
self.module.deprecate("The 'azure_rm_webapp_facts' module has been renamed to 'azure_rm_webapp_info'",
version='2.13', collection_name='ansible.builtin')
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])
if self.name:
self.results['webapps'] = self.list_by_name()
elif self.resource_group:
self.results['webapps'] = self.list_by_resource_group()
else:
self.results['webapps'] = self.list_all()
return self.results
def list_by_name(self):
self.log('Get web app {0}'.format(self.name))
item = None
result = []
try:
item = self.web_client.web_apps.get(self.resource_group, self.name)
except CloudError:
pass
if item and self.has_tags(item.tags, self.tags):
curated_result = self.get_curated_webapp(self.resource_group, self.name, item)
result = [curated_result]
return result
def list_by_resource_group(self):
self.log('List web apps in resource groups {0}'.format(self.resource_group))
try:
response = list(self.web_client.web_apps.list_by_resource_group(self.resource_group))
except CloudError as exc:
request_id = exc.request_id if exc.request_id else ''
self.fail("Error listing web apps in resource groups {0}, request id: {1} - {2}".format(self.resource_group, request_id, str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
curated_output = self.get_curated_webapp(self.resource_group, item.name, item)
results.append(curated_output)
return results
def list_all(self):
self.log('List web apps in current subscription')
try:
response = list(self.web_client.web_apps.list())
except CloudError as exc:
request_id = exc.request_id if exc.request_id else ''
self.fail("Error listing web apps, request id {0} - {1}".format(request_id, str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
curated_output = self.get_curated_webapp(item.resource_group, item.name, item)
results.append(curated_output)
return results
def list_webapp_configuration(self, resource_group, name):
self.log('Get web app {0} configuration'.format(name))
response = []
try:
response = self.web_client.web_apps.get_configuration(resource_group_name=resource_group, name=name)
except CloudError as ex:
request_id = ex.request_id if ex.request_id else ''
self.fail('Error getting web app {0} configuration, request id {1} - {2}'.format(name, request_id, str(ex)))
return response.as_dict()
def list_webapp_appsettings(self, resource_group, name):
self.log('Get web app {0} app settings'.format(name))
response = []
try:
response = self.web_client.web_apps.list_application_settings(resource_group_name=resource_group, name=name)
except CloudError as ex:
request_id = ex.request_id if ex.request_id else ''
self.fail('Error getting web app {0} app settings, request id {1} - {2}'.format(name, request_id, str(ex)))
return response.as_dict()
def get_publish_credentials(self, resource_group, name):
self.log('Get web app {0} publish credentials'.format(name))
try:
poller = self.web_client.web_apps.list_publishing_credentials(resource_group, name)
if isinstance(poller, LROPoller):
response = self.get_poller_result(poller)
except CloudError as ex:
request_id = ex.request_id if ex.request_id else ''
self.fail('Error getting web app {0} publishing credentials - {1}'.format(request_id, str(ex)))
return response
def get_webapp_ftp_publish_url(self, resource_group, name):
import xmltodict
self.log('Get web app {0} app publish profile'.format(name))
url = None
try:
content = self.web_client.web_apps.list_publishing_profile_xml_with_secrets(resource_group_name=resource_group, name=name)
if not content:
return url
full_xml = ''
for f in content:
full_xml += f.decode()
profiles = xmltodict.parse(full_xml, xml_attribs=True)['publishData']['publishProfile']
if not profiles:
return url
for profile in profiles:
if profile['@publishMethod'] == 'FTP':
url = profile['@publishUrl']
except CloudError as ex:
self.fail('Error getting web app {0} app settings'.format(name))
return url
def get_curated_webapp(self, resource_group, name, webapp):
pip = self.serialize_obj(webapp, AZURE_OBJECT_CLASS)
try:
site_config = self.list_webapp_configuration(resource_group, name)
app_settings = self.list_webapp_appsettings(resource_group, name)
publish_cred = self.get_publish_credentials(resource_group, name)
ftp_publish_url = self.get_webapp_ftp_publish_url(resource_group, name)
except CloudError as ex:
pass
return self.construct_curated_webapp(webapp=pip,
configuration=site_config,
app_settings=app_settings,
deployment_slot=None,
ftp_publish_url=ftp_publish_url,
publish_credentials=publish_cred)
def construct_curated_webapp(self,
webapp,
configuration=None,
app_settings=None,
deployment_slot=None,
ftp_publish_url=None,
publish_credentials=None):
curated_output = dict()
curated_output['id'] = webapp['id']
curated_output['name'] = webapp['name']
curated_output['resource_group'] = webapp['properties']['resourceGroup']
curated_output['location'] = webapp['location']
curated_output['plan'] = webapp['properties']['serverFarmId']
curated_output['tags'] = webapp.get('tags', None)
# important properties from output. not match input arguments.
curated_output['app_state'] = webapp['properties']['state']
curated_output['availability_state'] = webapp['properties']['availabilityState']
curated_output['default_host_name'] = webapp['properties']['defaultHostName']
curated_output['host_names'] = webapp['properties']['hostNames']
curated_output['enabled'] = webapp['properties']['enabled']
curated_output['enabled_host_names'] = webapp['properties']['enabledHostNames']
curated_output['host_name_ssl_states'] = webapp['properties']['hostNameSslStates']
curated_output['outbound_ip_addresses'] = webapp['properties']['outboundIpAddresses']
# curated site_config
if configuration:
curated_output['frameworks'] = []
for fx_name in self.framework_names:
fx_version = configuration.get(fx_name + '_version', None)
if fx_version:
fx = {
'name': fx_name,
'version': fx_version
}
# java container setting
if fx_name == 'java':
if configuration['java_container'] and configuration['java_container_version']:
settings = {
'java_container': configuration['java_container'].lower(),
'java_container_version': configuration['java_container_version']
}
fx['settings'] = settings
curated_output['frameworks'].append(fx)
# linux_fx_version
if configuration.get('linux_fx_version', None):
tmp = configuration.get('linux_fx_version').split("|")
if len(tmp) == 2:
curated_output['frameworks'].append({'name': tmp[0].lower(), 'version': tmp[1]})
# curated app_settings
if app_settings and app_settings.get('properties', None):
curated_output['app_settings'] = dict()
for item in app_settings['properties']:
curated_output['app_settings'][item] = app_settings['properties'][item]
# curated deploymenet_slot
if deployment_slot:
curated_output['deployment_slot'] = deployment_slot
# ftp_publish_url
if ftp_publish_url:
curated_output['ftp_publish_url'] = ftp_publish_url
# curated publish credentials
if publish_credentials and self.return_publish_profile:
curated_output['publishing_username'] = publish_credentials.publishing_user_name
curated_output['publishing_password'] = publish_credentials.publishing_password
return curated_output
def main():
AzureRMWebAppInfo()
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
cloud.sh