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:
parent
501f30df45
commit
4f54fb8d43
29 changed files with 0 additions and 8635 deletions
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
cloud/azure
|
||||
destructive
|
||||
shippable/azure/incidental
|
|
@ -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 }}"
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
azure_rm_mariadbconfiguration_info.py
|
|
@ -1 +0,0 @@
|
|||
azure_rm_mariadbdatabase_info.py
|
|
@ -1 +0,0 @@
|
|||
azure_rm_mariadbfirewallrule_info.py
|
|
@ -1 +0,0 @@
|
|||
azure_rm_mariadbserver_info.py
|
|
@ -1 +0,0 @@
|
|||
azure_rm_resource_info.py
|
|
@ -1 +0,0 @@
|
|||
azure_rm_webapp_info.py
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
|||
cloud.sh
|
Loading…
Reference in a new issue