diff --git a/files/sha.json b/files/sha.json index 3cbeb39..74d6b00 100644 --- a/files/sha.json +++ b/files/sha.json @@ -1,6 +1,6 @@ { "lib/ansible/module_utils/azure_rm_common.py": "8b1b22ddc7dad0d901ecbd96a982e34429bdfdb9", - "lib/ansible/modules/cloud/azure": "44c2061c708ca16cebcfbf4fa60a4c73cb86b630", + "lib/ansible/modules/cloud/azure": "22f666c9620396fb1ff7f4559b91182674e99008", "packaging/requirements/requirements-azure.txt": "8b1b22ddc7dad0d901ecbd96a982e34429bdfdb9", - "test/integration/targets": "025e9afe58fd2688ed4978f4710c795fcfdfd912" + "test/integration/targets": "dcbfa60413ece9d3e68fa44fa303a79003bbec75" } \ No newline at end of file diff --git a/library/azure_rm_aks.py b/library/azure_rm_aks.py index 4df1e7d..cd6d6e9 100644 --- a/library/azure_rm_aks.py +++ b/library/azure_rm_aks.py @@ -203,7 +203,7 @@ EXAMPLES = ''' - name: Create a managed Azure Container Services (AKS) instance azure_rm_aks: - name: acctestaks1 + name: myAKS location: eastus resource_group: myResourceGroup dns_prefix: akstest @@ -222,7 +222,7 @@ - name: Remove a managed Azure Container Services (AKS) instance azure_rm_aks: - name: acctestaks3 + name: myAKS resource_group: myResourceGroup state: absent ''' @@ -244,7 +244,7 @@ vnet_subnet_id: Null changed: false dns_prefix: aks9860bdcd89 - id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/yuwzhoaks/providers/Microsoft.ContainerService/managedClusters/aks9860bdc" + id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.ContainerService/managedClusters/aks9860bdc" kube_config: "......" kubernetes_version: 1.11.4 linux_profile: diff --git a/library/azure_rm_appgateway.py b/library/azure_rm_appgateway.py index 44e55e0..611dafb 100644 --- a/library/azure_rm_appgateway.py +++ b/library/azure_rm_appgateway.py @@ -377,7 +377,7 @@ - name: Create instance of Application Gateway azure_rm_appgateway: resource_group: myResourceGroup - name: myappgateway + name: myAppGateway sku: name: standard_small tier: standard diff --git a/library/azure_rm_appserviceplan_facts.py b/library/azure_rm_appserviceplan_facts.py index b5f198f..5d86778 100644 --- a/library/azure_rm_appserviceplan_facts.py +++ b/library/azure_rm_appserviceplan_facts.py @@ -46,7 +46,7 @@ - name: Get facts for app service plan by name azure_rm_appserviceplan_facts: resource_group: myResourceGroup - name: winwebapp1 + name: myAppServicePlan - name: Get azure_rm_appserviceplan_facts for app service plan in resource group azure_rm_webapp_facts: diff --git a/library/azure_rm_availabilityset.py b/library/azure_rm_availabilityset.py index 3fbfb4c..47f8585 100644 --- a/library/azure_rm_availabilityset.py +++ b/library/azure_rm_availabilityset.py @@ -70,13 +70,13 @@ EXAMPLES = ''' - name: Create an availability set with default options azure_rm_availabilityset: - name: myavailabilityset + name: myAvailabilitySet location: eastus resource_group: myResourceGroup - name: Create an availability set with advanced options azure_rm_availabilityset: - name: myavailabilityset + name: myAvailabilitySet location: eastus resource_group: myResourceGroup platform_update_domain_count: 5 @@ -85,7 +85,7 @@ - name: Delete an availability set azure_rm_availabilityset: - name: myavailabilityset + name: myAvailabilitySet location: eastus resource_group: myResourceGroup state: absent diff --git a/library/azure_rm_availabilityset_facts.py b/library/azure_rm_availabilityset_facts.py index aab729a..a9b029f 100644 --- a/library/azure_rm_availabilityset_facts.py +++ b/library/azure_rm_availabilityset_facts.py @@ -59,7 +59,7 @@ type: list example: [{ "location": "eastus2", - "name": "myavailabilityset", + "name": "myAvailabilitySet", "properties": { "platformFaultDomainCount": 3, "platformUpdateDomainCount": 2, diff --git a/library/azure_rm_cdnprofile.py b/library/azure_rm_cdnprofile.py index 793ee15..60b9897 100644 --- a/library/azure_rm_cdnprofile.py +++ b/library/azure_rm_cdnprofile.py @@ -63,7 +63,7 @@ - name: Create a CDN profile azure_rm_cdnprofile: resource_group: myResourceGroup - name: cdntest + name: myCDN sku: standard_akamai tags: testing: testing @@ -71,7 +71,7 @@ - name: Delete the CDN profile azure_rm_cdnprofile: resource_group: myResourceGroup - name: cdntest + name: myCDN state: absent ''' RETURN = ''' @@ -80,7 +80,7 @@ returned: always type: dict example: - id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/cdntest/providers/Microsoft.Cdn/profiles/cdntest + id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myCDN ''' from ansible.module_utils.azure_rm_common import AzureRMModuleBase diff --git a/library/azure_rm_cdnprofile_facts.py b/library/azure_rm_cdnprofile_facts.py index f4566df..65b3e88 100644 --- a/library/azure_rm_cdnprofile_facts.py +++ b/library/azure_rm_cdnprofile_facts.py @@ -84,7 +84,7 @@ description: - ID of the CDN profile. type: str - sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/cdntest + sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myCDN provisioning_state: description: - Provisioning status of the profile. diff --git a/library/azure_rm_containerinstance.py b/library/azure_rm_containerinstance.py index cfa3837..438b237 100644 --- a/library/azure_rm_containerinstance.py +++ b/library/azure_rm_containerinstance.py @@ -148,11 +148,11 @@ - name: Create sample container group azure_rm_containerinstance: resource_group: myResourceGroup - name: mynewcontainergroup + name: myContainerInstanceGroup os_type: linux ip_address: public containers: - - name: mycontainer1 + - name: myContainer1 image: httpd memory: 1.5 ports: diff --git a/library/azure_rm_containerinstance_facts.py b/library/azure_rm_containerinstance_facts.py index ac9c39a..d1bac9d 100644 --- a/library/azure_rm_containerinstance_facts.py +++ b/library/azure_rm_containerinstance_facts.py @@ -45,7 +45,7 @@ - name: Get specific Container Instance facts azure_rm_containerinstance_facts: resource_group: myResourceGroup - name: container_group_name + name: myContainer - name: List Container Instances in a specified resource group name azure_rm_containerinstance_facts: diff --git a/library/azure_rm_containerregistry.py b/library/azure_rm_containerregistry.py index 5873b45..7a3cfa4 100644 --- a/library/azure_rm_containerregistry.py +++ b/library/azure_rm_containerregistry.py @@ -64,7 +64,7 @@ EXAMPLES = ''' - name: Create an azure container registry azure_rm_containerregistry: - name: testacr1 + name: myRegistry location: eastus resource_group: myResourceGroup admin_user_enabled: true @@ -75,7 +75,7 @@ - name: Remove an azure container registry azure_rm_containerregistry: - name: testacr2 + name: myRegistry resource_group: myResourceGroup state: absent ''' diff --git a/library/azure_rm_containerregistry_facts.py b/library/azure_rm_containerregistry_facts.py index 7b05163..53c7a57 100644 --- a/library/azure_rm_containerregistry_facts.py +++ b/library/azure_rm_containerregistry_facts.py @@ -50,7 +50,7 @@ - name: Get instance of Registry azure_rm_containerregistry_facts: resource_group: myResourceGroup - name: sampleregistry + name: myRegistry - name: List instances of Registry azure_rm_containerregistry_facts: diff --git a/library/azure_rm_devtestlabcustomimage_facts.py b/library/azure_rm_devtestlabcustomimage_facts.py new file mode 100644 index 0000000..6806357 --- /dev/null +++ b/library/azure_rm_devtestlabcustomimage_facts.py @@ -0,0 +1,220 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Zim Kalinowski, (@zikalino) +# +# 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_devtestlabcustomimage_facts +version_added: "2.8" +short_description: Get Azure DevTest Lab Custom Image facts. +description: + - Get facts of Azure Azure DevTest Lab Custom Image. + +options: + resource_group: + description: + - The name of the resource group. + required: True + lab_name: + description: + - The name of the lab. + required: True + name: + description: + - The name of the custom image. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Zim Kalinowski (@zikalino)" + +''' + +EXAMPLES = ''' + - name: Get instance of Custom Image + azure_rm_devtestlabcustomimage_facts: + resource_group: myResourceGroup + lab_name: myLab + name: myImage + + - name: List instances of Custom Image in the lab + azure_rm_devtestlabcustomimage_facts: + resource_group: myResourceGroup + lab_name: myLab + name: myImage +''' + +RETURN = ''' +custom_images: + description: A list of dictionaries containing facts for Custom Image. + returned: always + type: complex + contains: + id: + description: + - The identifier of the artifact source. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DevTestLab/labs/myLab/cu + stomimages/myImage" + resource_group: + description: + - Name of the resource group. + returned: always + type: str + sample: myResourceGroup + lab_name: + description: + - Name of the lab. + returned: always + type: str + sample: myLab + name: + description: + - The name of the image. + returned: always + type: str + sample: myImage + managed_shapshot_id: + description: + - Managed snapshot id. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/microsoft.compute/snapshots/myImage" + source_vm_id: + description: + - Source VM id. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx//resourcegroups/myResourceGroup/providers/microsoft.devtestlab/labs/myLab/v + irtualmachines/myLabVm" + tags: + description: + - The tags of the resource. + returned: always + type: complex + sample: "{ 'MyTag': 'MyValue' }" +''' + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from msrestazure.azure_exceptions import CloudError + from azure.mgmt.devtestlabs import DevTestLabsClient + from msrest.serialization import Model +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMDtlCustomImageFacts(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + lab_name=dict( + type='str', + required=True + ), + name=dict( + type='str', + required=True + ), + tags=dict( + type='list' + ) + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.mgmt_client = None + self.resource_group = None + self.lab_name = None + self.name = None + self.tags = None + super(AzureRMDtlCustomImageFacts, 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(DevTestLabsClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + if self.name: + self.results['custom_images'] = self.get() + else: + self.results['custom_images'] = self.list() + return self.results + + def get(self): + response = None + results = [] + try: + response = self.mgmt_client.custom_images.get(resource_group_name=self.resource_group, + lab_name=self.lab_name, + name=self.name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Custom Image.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_response(response)) + + return results + + def list(self): + response = None + results = [] + try: + response = self.mgmt_client.custom_images.list(resource_group_name=self.resource_group, + lab_name=self.lab_name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Custom Image.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def format_response(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'lab_name': self.lab_name, + 'name': d.get('name'), + 'id': d.get('id'), + 'managed_snapshot_id': d.get('managed_snapshot_id'), + 'source_vm_id': d.get('vm', {}).get('source_vm_id'), + 'tags': d.get('tags') + } + return d + + +def main(): + AzureRMDtlCustomImageFacts() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_devtestlabenvironment_facts.py b/library/azure_rm_devtestlabenvironment_facts.py new file mode 100644 index 0000000..b12af4f --- /dev/null +++ b/library/azure_rm_devtestlabenvironment_facts.py @@ -0,0 +1,235 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Zim Kalinowski, (@zikalino) +# +# 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_devtestlabenvironment_facts +version_added: "2.8" +short_description: Get Azure Environment facts. +description: + - Get facts of Azure Environment. + +options: + resource_group: + description: + - The name of the resource group. + required: True + lab_name: + description: + - The name of the lab. + required: True + user_name: + description: + - The name of the user profile. + required: True + name: + description: + - The name of the environment. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Zim Kalinowski (@zikalino)" + +''' + +EXAMPLES = ''' + - name: Get instance of Environment + azure_rm_devtestlabenvironment_facts: + resource_group: myResourceGroup + lab_name: myLab + user_name: myUser + name: myEnvironment +''' + +RETURN = ''' +environments: + description: A list of dictionaries containing facts for Environment. + returned: always + type: complex + contains: + id: + description: + - The identifier of the artifact source. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DevTestLab/labs/myLab/sc + hedules/xxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxxx/environments/myEnvironment" + resource_group: + description: + - Name of the resource group. + returned: always + type: str + sample: myResourceGroup + lab_name: + description: + - Name of the lab. + returned: always + type: str + sample: myLab + name: + description: + - The name of the environment. + returned: always + type: str + sample: myEnvironment + deployment_template: + description: + - The identifier of the artifact source. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/microsoft.devtestlab/labs/mylab/art + ifactSources/public environment repo/armTemplates/WebApp" + resource_group_id: + description: + - Target resource group id. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myLab-myEnvironment-982571" + state: + description: + - Deployment state. + returned: always + type: str + sample: Succeeded + tags: + description: + - The tags of the resource. + returned: always + type: complex + sample: "{ 'MyTag': 'MyValue' }" +''' + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from msrestazure.azure_exceptions import CloudError + from azure.mgmt.devtestlabs import DevTestLabsClient + from msrest.serialization import Model +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMDtlEnvironmentFacts(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + lab_name=dict( + type='str', + required=True + ), + user_name=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.mgmt_client = None + self.resource_group = None + self.lab_name = None + self.user_name = None + self.name = None + self.tags = None + super(AzureRMDtlEnvironmentFacts, 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(DevTestLabsClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + if self.name: + self.results['environments'] = self.get() + else: + self.results['environments'] = self.list() + + return self.results + + def get(self): + response = None + results = [] + try: + response = self.mgmt_client.environments.get(resource_group_name=self.resource_group, + lab_name=self.lab_name, + user_name=self.user_name, + name=self.name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Environment.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_response(response)) + + return results + + def list(self): + response = None + results = [] + try: + response = self.mgmt_client.environments.list(resource_group_name=self.resource_group, + lab_name=self.lab_name, + user_name=self.user_name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Environment.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def format_response(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'lab_name': self.lab_name, + 'name': d.get('name'), + 'user_name': self.user_name, + 'id': d.get('id', None), + 'deployment_template': d.get('deployment_properties', {}).get('arm_template_id'), + 'location': d.get('location'), + 'provisioning_state': d.get('provisioning_state'), + 'resource_group_id': d.get('resource_group_id'), + 'tags': d.get('tags', None) + } + return d + + +def main(): + AzureRMDtlEnvironmentFacts() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_devtestlabpolicy_facts.py b/library/azure_rm_devtestlabpolicy_facts.py new file mode 100644 index 0000000..ab89d72 --- /dev/null +++ b/library/azure_rm_devtestlabpolicy_facts.py @@ -0,0 +1,233 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Zim Kalinowski, (@zikalino) +# +# 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_devtestlabpolicy_facts +version_added: "2.8" +short_description: Get Azure DTL Policy facts. +description: + - Get facts of Azure DTL Policy. + +options: + resource_group: + description: + - The name of the resource group. + required: True + lab_name: + description: + - The name of the lab. + required: True + policy_set_name: + description: + - The name of the policy set. + required: True + name: + description: + - The name of the policy. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Zim Kalinowski (@zikalino)" + +''' + +EXAMPLES = ''' + - name: Get instance of Policy + azure_rm_devtestlabpolicy_facts: + resource_group: myResourceGroup + lab_name: myLab + policy_set_name: myPolicySet + name: myPolicy +''' + +RETURN = ''' +policies: + description: A list of dictionaries containing facts for Policy. + returned: always + type: complex + contains: + id: + description: + - The identifier of the artifact source. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DevTestLab/labs/myLab/po + licysets/myPolicySet/policies/myPolicy" + resource_group: + description: + - Name of the resource group. + returned: always + type: str + sample: myResourceGroup + lab_name: + description: + - Name of the lab. + returned: always + type: str + sample: myLab + name: + description: + - The name of the artifact source. + returned: always + type: str + sample: myArtifactSource + fact_name: + description: + - The name of the policy fact. + returned: always + type: str + sample: UserOwnedLabVmCount + evaluator_type: + description: + - Evaluator type for policy fact. + returned: always + type: str + sample: MaxValuePolicy + threshold: + description: + - Fact's threshold. + returned: always + type: str + sample: 5 + tags: + description: + - The tags of the resource. + returned: always + type: complex + sample: "{ 'MyTag': 'MyValue' }" +''' + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from msrestazure.azure_exceptions import CloudError + from azure.mgmt.devtestlabs import DevTestLabsClient + from msrest.serialization import Model +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMDtlPolicyFacts(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + lab_name=dict( + type='str', + required=True + ), + policy_set_name=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.mgmt_client = None + self.resource_group = None + self.lab_name = None + self.policy_set_name = None + self.name = None + self.tags = None + super(AzureRMDtlPolicyFacts, 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(DevTestLabsClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + if self.name: + self.results['policies'] = self.get() + else: + self.results['policies'] = self.list() + + return self.results + + def get(self): + response = None + results = [] + try: + response = self.mgmt_client.policies.get(resource_group_name=self.resource_group, + lab_name=self.lab_name, + policy_set_name=self.policy_set_name, + name=self.name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Policy.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_response(response)) + + return results + + def list(self): + response = None + results = [] + try: + response = self.mgmt_client.policies.list(resource_group_name=self.resource_group, + lab_name=self.lab_name, + policy_set_name=self.policy_set_name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Policy.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def format_response(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'policy_set_name': self.policy_set_name, + 'name': d.get('name'), + 'id': d.get('id'), + 'tags': d.get('tags'), + 'status': d.get('status'), + 'threshold': d.get('threshold'), + 'fact_name': d.get('fact_name'), + 'evaluator_type': d.get('evaluator_type') + } + return d + + +def main(): + AzureRMDtlPolicyFacts() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_devtestlabschedule_facts.py b/library/azure_rm_devtestlabschedule_facts.py new file mode 100644 index 0000000..b95dc1f --- /dev/null +++ b/library/azure_rm_devtestlabschedule_facts.py @@ -0,0 +1,213 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Zim Kalinowski, (@zikalino) +# +# 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_devtestlabschedule_facts +version_added: "2.8" +short_description: Get Azure Schedule facts. +description: + - Get facts of Azure Schedule. + +options: + resource_group: + description: + - The name of the resource group. + required: True + lab_name: + description: + - The name of the lab. + required: True + name: + description: + - The name of the schedule. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Zim Kalinowski (@zikalino)" + +''' + +EXAMPLES = ''' + - name: Get instance of Schedule + azure_rm_devtestlabschedule_facts: + resource_group: myResourceGroup + lab_name: myLab + name: mySchedule +''' + +RETURN = ''' +schedules: + description: A list of dictionaries containing facts for Schedule. + returned: always + type: complex + contains: + id: + description: + - The identifier of the artifact source. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DevTestLab/labs/myLab/sc + hedules/labvmsshutdown" + resource_group: + description: + - Name of the resource group. + returned: always + type: str + sample: myResourceGroup + lab_name: + description: + - Name of the lab. + returned: always + type: str + sample: myLab + name: + description: + - The name of the environment. + returned: always + type: str + sample: lab_vms_shutdown + time: + description: + - Time of the schedule. + returned: always + type: str + sample: lab_vms_shutdown + time_zone_id: + description: + - Time zone id. + returned: always + type: str + sample: UTC+12 + tags: + description: + - The tags of the resource. + returned: always + type: complex + sample: "{ 'MyTag': 'MyValue' }" +''' + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.common.dict_transformations import _camel_to_snake, _snake_to_camel + +try: + from msrestazure.azure_exceptions import CloudError + from azure.mgmt.devtestlabs import DevTestLabsClient + from msrest.serialization import Model +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMDtlScheduleFacts(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + lab_name=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.mgmt_client = None + self.resource_group = None + self.lab_name = None + self.name = None + self.tags = None + super(AzureRMDtlScheduleFacts, 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(DevTestLabsClient, + base_url=self._cloud_environment.endpoints.resource_manager) + if self.name: + self.results['schedules'] = self.get() + else: + self.results['schedules'] = self.list() + + return self.results + + def get(self): + response = None + results = [] + try: + response = self.mgmt_client.schedules.get(resource_group_name=self.resource_group, + lab_name=self.lab_name, + name=_snake_to_camel(self.name)) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Schedule.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_response(response)) + + return results + + def list(self): + response = None + results = [] + try: + response = self.mgmt_client.schedules.list(resource_group_name=self.resource_group, + lab_name=self.lab_name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for Schedule.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def format_response(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'lab_name': self.lab_name, + 'name': _camel_to_snake(d.get('name')), + 'id': d.get('id', None), + 'tags': d.get('tags', None), + 'time': d.get('daily_recurrence', {}).get('time'), + 'time_zone_id': d.get('time_zone_id') + } + return d + + +def main(): + AzureRMDtlScheduleFacts() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_functionapp.py b/library/azure_rm_functionapp.py index 2a02af8..2a93626 100644 --- a/library/azure_rm_functionapp.py +++ b/library/azure_rm_functionapp.py @@ -87,24 +87,36 @@ EXAMPLES = ''' - name: Create a function app azure_rm_functionapp: - resource_group: myResourceGroup - name: myFunctionApp - storage_account: myStorageAccount + 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: myFunctionApp - storage_account: myStorageAccount - app_settings: - setting1: value1 - setting2: value2 + 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 + resource_group: myResourceGroup + name: myFunctionApp + state: absent ''' RETURN = ''' @@ -344,11 +356,16 @@ def necessary_functionapp_settings(self): """Construct the necessary app settings required for an Azure Function App""" function_app_settings = [] - 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)) + + 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')) + return function_app_settings def aggregated_app_settings(self): diff --git a/library/azure_rm_hdinsightcluster_facts.py b/library/azure_rm_hdinsightcluster_facts.py new file mode 100644 index 0000000..a5f9928 --- /dev/null +++ b/library/azure_rm_hdinsightcluster_facts.py @@ -0,0 +1,314 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Zim Kalinowski, (@zikalino) +# +# 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_hdinsightcluster_facts +version_added: "2.8" +short_description: Get Azure HDInsight Cluster facts. +description: + - Get facts of Azure HDInsight Cluster. + +options: + resource_group: + description: + - Name of an Azure resource group. + name: + description: + - HDInsight cluster name. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Zim Kalinowski (@zikalino)" + +''' + +EXAMPLES = ''' + - name: Get instance of HDInsight Cluster + azure_rm_hdinsightcluster_facts: + resource_group: myResourceGroup + name: myCluster + + - name: List instances of HDInsight Cluster + azure_rm_hdinsightcluster_facts: + resource_group: myResourceGroup +''' + +RETURN = ''' +clusters: + description: A list of dictionaries containing facts for HDInsight Cluster. + returned: always + type: complex + contains: + id: + description: + - The unique resource identifier of the HDInsight Cluster. + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.HDInsight/clusters/myCluster" + resource_group: + description: + - Name of an Azure resource group. + returned: always + type: str + sample: myResourceGroup + name: + description: + - The name of the HDInsight Cluster. + returned: always + type: str + sample: testaccount + location: + description: + - The location of the resource group to which the resource belongs. + returned: always + type: str + sample: westus + cluster_version: + description: + - The version of the cluster. + returned: always + type: str + sample: 3.6.1000.67 + os_type: + description: + - The type of operating system. + returned: always + type: str + sample: linux + tier: + description: + - The cluster tier. + returned: always + type: str + sample: standard + cluster_definition: + description: + - The cluster definition. + contains: + kind: + description: + - The type of cluster. + returned: always + type: str + sample: spark + compute_profile_roles: + description: + - The list of roles in the cluster. + type: list + suboptions: + name: + description: + - The name of the role. + returned: always + type: str + sample: headnode + target_instance_count: + description: + - The instance count of the cluster. + returned: always + type: int + sample: 2 + vm_size: + description: + - The size of the VM + returned: always + type: str + sample: Standard_D3 + linux_profile: + description: + - The Linux OS profile. + contains: + username: + description: + - User name + returned: always + type: str + sample: myuser + connectivity_endpoints: + description: + - Cluster's connectivity endpoints. + type: list + contains: + location: + description: + - Endpoint location. + returned: always + type: str + sample: myCluster-ssh.azurehdinsight.net + name: + description: + - Endpoint name. + returned: always + type: str + sample: SSH + port: + description: + - Endpoint port. + returned: always + type: int + sample: 22 + protocol: + description: + - Endpoint protocol. + returned: always + type: str + sample: TCP + tags: + description: + - Tags + returned: always + type: complex + sample: {} +''' + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.common.dict_transformations import _camel_to_snake + +try: + from msrestazure.azure_exceptions import CloudError + from azure.mgmt.hdinsight import HDInsightManagementClient + from msrest.serialization import Model +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMHDInsightclusterFacts(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str' + ), + name=dict( + type='str' + ), + tags=dict( + type='list' + ) + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.mgmt_client = None + self.resource_group = None + self.name = None + self.tags = None + + super(AzureRMHDInsightclusterFacts, 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(HDInsightManagementClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + if self.name is not None: + self.results['clusters'] = self.get() + elif self.resource_group is not None: + self.results['clusters'] = self.list_by_resource_group() + else: + self.results['clusters'] = self.list_all() + return self.results + + def get(self): + response = None + results = [] + try: + response = self.mgmt_client.clusters.get(resource_group_name=self.resource_group, + cluster_name=self.name) + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for HDInsight Cluster.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_response(response)) + + return results + + def list_by_resource_group(self): + response = None + results = [] + try: + response = self.mgmt_client.clusters.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 HDInsight Cluster.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def list_all(self): + response = None + results = [] + try: + response = self.mgmt_client.clusters.list() + self.log("Response : {0}".format(response)) + except CloudError as e: + self.log('Could not get facts for HDInsight Cluster.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_response(item)) + + return results + + def format_response(self, item): + d = item.as_dict() + d = { + 'id': d.get('id'), + 'resource_group': self.parse_resource_to_dict(d.get('id')).get('resource_group'), + 'name': d.get('name', None), + 'location': d.get('location', '').replace(' ', '').lower(), + + 'cluster_version': d.get('properties', {}).get('cluster_version'), + 'os_type': d.get('properties', {}).get('os_type'), + 'tier': d.get('properties', {}).get('tier'), + 'cluster_definition': { + 'kind': d.get('properties', {}).get('cluster_definition', {}).get('kind') + }, + 'compute_profile_roles': [{ + 'name': item.get('name'), + 'target_instance_count': item.get('target_instance_count'), + 'vm_size': item.get('hardware_profile', {}).get('vm_size'), + 'linux_profile': { + 'username': item.get('os_profile', {}).get('linux_operating_system_profile', {}).get('username') + } + } for item in d.get('properties', []).get('compute_profile', {}).get('roles', [])], + 'connectivity_endpoints': d.get('properties', {}).get('connectivity_endpoints'), + 'tags': d.get('tags', None) + } + + return d + + +def main(): + AzureRMHDInsightclusterFacts() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_rediscache.py b/library/azure_rm_rediscache.py index 308189a..41ccb9e 100644 --- a/library/azure_rm_rediscache.py +++ b/library/azure_rm_rediscache.py @@ -131,6 +131,14 @@ choices: - primary - secondary + wait_for_provisioning: + description: + - Wait till the Azure Cache for Redis instance provisioning_state is Succeeded. + - It takes several minutes for Azure Cache for Redis to be provisioned ready for use after creating/updating/rebooting. + - Set this option to true to wait for provisioning_state. Set to false if you don't care about provisioning_state. + - Poll wait timeout is 60 minutes. + type: bool + default: True state: description: - Assert the state of the Azure Cache for Redis. @@ -209,8 +217,8 @@ try: from msrestazure.azure_exceptions import CloudError - from msrest.polling import LROPoller from msrestazure.azure_operation import AzureOperationPoller + from msrest.polling import LROPoller from msrest.serialization import Model from azure.mgmt.redis import RedisManagementClient from azure.mgmt.redis.models import (RedisCreateParameters, RedisUpdateParameters, Sku) @@ -366,6 +374,10 @@ def __init__(self): regenerate_key=dict( type='dict', options=regenerate_key_spec + ), + wait_for_provisioning=dict( + type='bool', + default='True' ) ) @@ -386,6 +398,10 @@ def __init__(self): self.reboot = None self.regenerate_key = None + self.wait_for_provisioning = None + self.wait_for_provisioning_polling_interval_in_seconds = 30 + self.wait_for_provisioning_polling_times = 120 + self.tags = None self.results = dict( @@ -562,9 +578,12 @@ def create_rediscache(self): response = self._client.redis.create(resource_group_name=self.resource_group, name=self.name, parameters=params) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): response = self.get_poller_result(response) + if self.wait_for_provisioning: + self.wait_for_redis_running() + except CloudError as exc: self.log('Error attempting to create the Azure Cache for Redis instance.') self.fail( @@ -598,9 +617,12 @@ def update_rediscache(self): response = self._client.redis.update(resource_group_name=self.resource_group, name=self.name, parameters=params) - if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): response = self.get_poller_result(response) + if self.wait_for_provisioning: + self.wait_for_redis_running() + except CloudError as exc: self.log('Error attempting to update the Azure Cache for Redis instance.') self.fail( @@ -659,6 +681,11 @@ def force_reboot_rediscache(self): name=self.name, reboot_type=self.reboot['reboot_type'], shard_id=self.reboot.get('shard_id')) + if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller): + response = self.get_poller_result(response) + + if self.wait_for_provisioning: + self.wait_for_redis_running() except CloudError as e: self.log('Error attempting to force reboot the redis cache instance.') self.fail( @@ -718,6 +745,24 @@ def parse_subnet(self): subnet_id = self.subnet return subnet_id + def wait_for_redis_running(self): + try: + response = self._client.redis.get(resource_group_name=self.resource_group, name=self.name) + status = response.provisioning_state + polling_times = 0 + + while polling_times < self.wait_for_provisioning_polling_times: + if status.lower() != "succeeded": + polling_times += 1 + time.sleep(self.wait_for_provisioning_polling_interval_in_seconds) + response = self._client.redis.get(resource_group_name=self.resource_group, name=self.name) + status = response.provisioning_state + else: + return True + self.fail("Azure Cache for Redis is not running after 60 mins.") + except CloudError as e: + self.fail("Failed to get Azure Cache for Redis: {0}".format(str(e))) + def main(): """Main execution""" diff --git a/library/azure_rm_subnet.py b/library/azure_rm_subnet.py index f90e9af..99c22fe 100644 --- a/library/azure_rm_subnet.py +++ b/library/azure_rm_subnet.py @@ -84,7 +84,6 @@ extends_documentation_fragment: - azure - - azure_tags author: - "Chris Houseknecht (@chouseknecht)" @@ -219,7 +218,8 @@ def __init__(self): self.service_endpoints = None super(AzureRMSubnet, self).__init__(self.module_arg_spec, - supports_check_mode=True) + supports_check_mode=True, + supports_tags=False) def exec_module(self, **kwargs): diff --git a/library/azure_rm_virtualmachine.py b/library/azure_rm_virtualmachine.py index f03519b..2c931cd 100644 --- a/library/azure_rm_virtualmachine.py +++ b/library/azure_rm_virtualmachine.py @@ -314,6 +314,43 @@ - A list of Availability Zones for your virtual machine type: list version_added: "2.8" + license_type: + description: + - Specifies that the image or disk that is being used was licensed on-premises. This element is only + used for images that contain the Windows Server operating system. + - "Note: To unset this value, it has to be set to the string 'None'." + version_added: 2.8 + choices: + - Windows_Server + - Windows_Client + vm_identity: + description: + - Identity for the virtual machine. + version_added: 2.8 + choices: + - SystemAssigned + winrm: + description: + - List of Windows Remote Management configurations of the VM. + version_added: 2.8 + suboptions: + protocol: + description: + - Specifies the protocol of listener + required: true + choices: + - http + - https + source_vault: + description: + - The relative URL of the Key Vault containing the certificate + certificate_url: + description: + - This is the URL of a certificate that has been uploaded to Key Vault as a secret. + certificate_store: + description: + - Specifies the certificate store on the Virtual Machine to which the certificate + should be added. The specified certificate store is implicitly in the LocalMachine account. extends_documentation_fragment: - azure @@ -322,6 +359,8 @@ author: - "Chris Houseknecht (@chouseknecht)" - "Matt Davis (@nitzmahone)" + - "Christopher Perrin (@cperrin88)" + ''' EXAMPLES = ''' @@ -754,8 +793,11 @@ def __init__(self): generalized=dict(type='bool', default=False), data_disks=dict(type='list'), plan=dict(type='dict'), + zones=dict(type='list'), accept_terms=dict(type='bool', default=False), - zones=dict(type='list') + license_type=dict(type='str', choices=['Windows_Server', 'Windows_Client']), + vm_identity=dict(type='str', choices=['SystemAssigned']), + winrm=dict(type='list') ) self.resource_group = None @@ -797,6 +839,8 @@ def __init__(self): self.plan = None self.accept_terms = None self.zones = None + self.license_type = None + self.vm_identity = None self.results = dict( changed=False, @@ -996,6 +1040,9 @@ def exec_module(self, **kwargs): differences.append('Zones') changed = True + if self.license_type is not None and vm_dict['properties'].get('licenseType') != self.license_type: + differences.append('License Type') + changed = True self.differences = differences elif self.state == 'absent': @@ -1087,6 +1134,8 @@ def exec_module(self, **kwargs): publisher=self.plan.get('publisher'), promotion_code=self.plan.get('promotion_code')) + license_type = self.license_type + vm_resource = self.compute_models.VirtualMachine( location=self.location, tags=self.tags, @@ -1116,6 +1165,46 @@ def exec_module(self, **kwargs): zones=self.zones, ) + if self.license_type is not None: + vm_resource.license_type = self.license_type + + if self.vm_identity: + vm_resource.identity = self.compute_models.VirtualMachineIdentity(type=self.vm_identity) + + if self.winrm: + winrm_listeners = list() + for winrm_listener in self.winrm: + winrm_listeners.append(self.compute_models.WinRMListener( + protocol=winrm_listener.get('protocol'), + certificate_url=winrm_listener.get('certificate_url') + )) + if winrm_listener.get('source_vault'): + if not vm_resource.os_profile.secrets: + vm_resource.os_profile.secrets = list() + + vm_resource.os_profile.secrets.append(self.compute_models.VaultSecretGroup( + source_vault=self.compute_models.SubResource( + id=winrm_listener.get('source_vault') + ), + vault_certificates=[ + self.compute_models.VaultCertificate( + certificate_url=winrm_listener.get('certificate_url'), + certificate_store=winrm_listener.get('certificate_store') + ), + ] + )) + + winrm = self.compute_models.WinRMConfiguration( + listeners=winrm_listeners + ) + + if not vm_resource.os_profile.windows_configuration: + vm_resource.os_profile.windows_configuration = self.compute_models.WindowsConfiguration( + win_rm=winrm + ) + elif not vm_resource.os_profile.windows_configuration.win_rm: + vm_resource.os_profile.windows_configuration.win_rm = winrm + if self.admin_password: vm_resource.os_profile.admin_password = self.admin_password @@ -1263,6 +1352,9 @@ def exec_module(self, **kwargs): ) else: os_profile = None + license_type = None + if self.license_type is None: + license_type = "None" vm_resource = self.compute_models.VirtualMachine( location=vm_dict['location'], @@ -1285,9 +1377,12 @@ def exec_module(self, **kwargs): availability_set=availability_set_resource, network_profile=self.compute_models.NetworkProfile( network_interfaces=nics - ), + ) ) + if self.license_type is not None: + vm_resource.license_type = self.license_type + if vm_dict.get('tags'): vm_resource.tags = vm_dict['tags'] diff --git a/library/azure_rm_virtualnetworkgateway.py b/library/azure_rm_virtualnetworkgateway.py new file mode 100644 index 0000000..7e82228 --- /dev/null +++ b/library/azure_rm_virtualnetworkgateway.py @@ -0,0 +1,384 @@ +#!/usr/bin/python +# 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': 'certified'} + +DOCUMENTATION = ''' +--- +module: azure_rm_virtualnetworkgateway + +version_added: "2.8" + +short_description: Manage Azure virtual network gateways. + +description: + - Create, update or delete a virtual network gateway(VPN Gateway). When creating a VPN Gateway you must provide the name of an + existing virtual network. + +options: + resource_group: + description: + - Name of a resource group where VPN Gateway exists or will be created. + required: true + name: + description: + - Name of VPN Gateway. + required: true + state: + description: + - Assert the state of the VPN Gateway. Use 'present' to create or update VPN gateway and + 'absent' to delete VPN gateway. + default: present + choices: + - absent + - present + required: false + location: + description: + - Valid azure location. Defaults to location of the resource group. + required: false + virtual_network: + description: + - An existing virtual network with which the VPN Gateway will be associated. Required + when creating a VPN Gateway. + - It can be the virtual network's name. + - Make sure your virtual network is in the same resource group as VPN gateway when you give only the name. + - It can be the virtual network's resource id. + - It can be a dict which contains C(name) and C(resource_group) of the virtual network. + aliases: + - virtual_network_name + required: true + ip_configurations: + description: + - List of ip configurations + suboptions: + name: + description: + - Name of the ip configuration. + required: true + private_ip_allocation_method: + description: + - private ip allocation method. + choices: + - dynamic + - static + default: dynamic + public_ip_address_name: + description: + - Name of the public ip address. None for disable ip address. + subnet: + description: + - ID of the gateway subnet for VPN. + default: GatewaySubnet + gateway_type: + description: + - The type of this virtual network gateway + default: vpn + choices: + - vpn + - express_route + vpn_type: + description: + - The type of this virtual network gateway + default: route_based + choices: + - route_based + - policy_based + enable_bgp: + description: + - Whether BGP is enabled for this virtual network gateway or not + default: false + sku: + description: + - The reference of the VirtualNetworkGatewaySku resource which represents the SKU selected for Virtual network gateway. + default: VpnGw1 + choices: + - VpnGw1 + - VpnGw2 + - VpnGw3 + bgp_settings: + description: + - Virtual network gateway's BGP speaker settings. + suboptions: + asn: + description: + - The BGP speaker's ASN. + required: True + +extends_documentation_fragment: + - azure + - azure_tags + +author: + - "Madhura Naniwadekar (@Madhura-CSI)" +''' + +EXAMPLES = ''' + - name: Create virtual network gateway without bgp settings + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testipaddr + virtual_network: myVirtualNetwork + tags: + common: "xyz" + + - name: Create virtual network gateway with bgp + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + sku: vpn_gw1 + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testipaddr + enable_bgp: yes + virtual_network: myVirtualNetwork + bgp_settings: + asn: 65515 + bgp_peering_address: "169.254.54.209" + tags: + common: "xyz" + + - name: Delete instance of virtual network gateway + azure_rm_virtualnetworkgateway: + resource_group: myResourceGroup + name: myVirtualNetworkGateway + state: absent +''' + +RETURN = ''' +id: + description: + - Virtual Network Gateway resource ID + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworkGateways/myV + irtualNetworkGateway" +''' + +try: + from msrestazure.azure_exceptions import CloudError +except ImportError: + # This is handled in azure_rm_common + pass + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase, CIDR_PATTERN +from ansible.module_utils.common.dict_transformations import _snake_to_camel + + +AZURE_VPN_GATEWAY_OBJECT_CLASS = 'VirtualNetworkGateway' + + +ip_configuration_spec = dict( + name=dict(type='str', required=True), + private_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), + subnet=dict(type='str'), + public_ip_address_name=dict(type='str'), +) + + +sku_spec = dict( + name=dict(type='str', default='VpnGw1'), + tier=dict(type='str', default='VpnGw1') +) + + +bgp_spec = dict( + asn=dict(type='int', required=True), +) + + +def vgw_to_dict(vgw): + results = dict( + id=vgw.id, + name=vgw.name, + location=vgw.location, + gateway_type=vgw.gateway_type, + vpn_type=vgw.vpn_type, + enable_bgp=vgw.enable_bgp, + tags=vgw.tags, + provisioning_state=vgw.provisioning_state, + sku=dict( + name=vgw.sku.name, + tier=vgw.sku.tier + ), + bgp_settings=dict( + asn=vgw.bgp_settings.asn, + bgp_peering_address=vgw.bgp_settings.bgp_peering_address, + peer_weight=vgw.bgp_settings.peer_weight + ) if vgw.bgp_settings else None, + etag=vgw.etag + ) + return results + + +class AzureRMVirtualNetworkGateway(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str', required=True), + name=dict(type='str', required=True), + state=dict(type='str', default='present', choices=['present', 'absent']), + location=dict(type='str'), + ip_configurations=dict(type='list', default=None, elements='dict', options=ip_configuration_spec), + gateway_type=dict(type='str', default='vpn', choices=['vpn', 'express_route']), + vpn_type=dict(type='str', default='route_based', choices=['route_based', 'policy_based']), + enable_bgp=dict(type='bool', default=False), + sku=dict(default='VpnGw1', choices=['VpnGw1', 'VpnGw2', 'VpnGw3']), + bgp_settings=dict(type='dict', options=bgp_spec), + virtual_network=dict(type='raw', aliases=['virtual_network_name']) + ) + + self.resource_group = None + self.name = None + self.state = None + self.location = None + self.ip_configurations = None + self.gateway_type = None + self.vpn_type = None + self.enable_bgp = None + self.sku = None + self.bgp_settings = None + + self.results = dict( + changed=False, + state=dict() + ) + + super(AzureRMVirtualNetworkGateway, self).__init__(derived_arg_spec=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]) + + changed = False + results = dict() + vgw = None + + resource_group = self.get_resource_group(self.resource_group) + if not self.location: + self.location = resource_group.location + + self.virtual_network = self.parse_resource_to_dict(self.virtual_network) + resource_group = self.get_resource_group(self.resource_group) + + try: + vgw = self.network_client.virtual_network_gateways.get(self.resource_group, self.name) + if self.state == 'absent': + self.log("CHANGED: vnet exists but requested state is 'absent'") + changed = True + except CloudError: + if self.state == 'present': + self.log("CHANGED: VPN Gateway {0} does not exist but requested state is 'present'".format(self.name)) + changed = True + + if vgw: + results = vgw_to_dict(vgw) + if self.state == 'present': + update_tags, results['tags'] = self.update_tags(results['tags']) + if update_tags: + changed = True + sku = dict(name=self.sku, tier=self.sku) + if sku != results['sku']: + changed = True + if self.enable_bgp != results['enable_bgp']: + changed = True + if self.bgp_settings and self.bgp_settings['asn'] != results['bgp_settings']['asn']: + changed = True + + self.results['changed'] = changed + self.results['id'] = results.get('id') + + if self.check_mode: + return self.results + if changed: + if self.state == 'present': + if not self.sku: + self.fail('Parameter error: sku is required when creating a vpn gateway') + if not self.ip_configurations: + self.fail('Parameter error: ip_configurations required when creating a vpn gateway') + subnet = self.network_models.SubResource( + id='/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/virtualNetworks/{2}/subnets/GatewaySubnet'.format( + self.virtual_network['subscription_id'], + self.virtual_network['resource_group'], + self.virtual_network['name'])) + + public_ip_address = self.network_models.SubResource( + id='/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/publicIPAddresses/{2}'.format( + self.virtual_network['subscription_id'], + self.virtual_network['resource_group'], + self.ip_configurations[0]['public_ip_address_name'])) + + vgw_ip_configurations = [ + self.network_models.VirtualNetworkGatewayIPConfiguration( + private_ip_allocation_method=ip_config.get('private_ip_allocation_method'), + subnet=subnet, + public_ip_address=public_ip_address, + name='default' + ) for ip_config in self.ip_configurations + ] + + vgw_sku = self.network_models.VirtualNetworkGatewaySku( + name=self.sku, + tier=self.sku + ) + + vgw_bgp_settings = self.network_models.BgpSettings( + asn=self.bgp_settings.get('asn'), + ) if self.bgp_settings else None + vgw = self.network_models.VirtualNetworkGateway( + location=self.location, + ip_configurations=vgw_ip_configurations, + gateway_type=_snake_to_camel(self.gateway_type, True), + vpn_type=_snake_to_camel(self.vpn_type, True), + enable_bgp=self.enable_bgp, + sku=vgw_sku, + bgp_settings=vgw_bgp_settings + ) + if self.tags: + vgw.tags = self.tags + results = self.create_or_update_vgw(vgw) + + else: + results = self.delete_vgw() + + if self.state == 'present': + self.results['id'] = results.get('id') + return self.results + + def create_or_update_vgw(self, vgw): + try: + poller = self.network_client.virtual_network_gateways.create_or_update(self.resource_group, self.name, vgw) + new_vgw = self.get_poller_result(poller) + return vgw_to_dict(new_vgw) + except Exception as exc: + self.fail("Error creating or updating virtual network gateway {0} - {1}".format(self.name, str(exc))) + + def delete_vgw(self): + try: + poller = self.network_client.virtual_network_gateways.delete(self.resource_group, self.name) + self.get_poller_result(poller) + except Exception as exc: + self.fail("Error deleting virtual network gateway {0} - {1}".format(self.name, str(exc))) + return True + + +def main(): + AzureRMVirtualNetworkGateway() + + +if __name__ == '__main__': + main() diff --git a/library/azure_rm_webapp.py b/library/azure_rm_webapp.py index e6252c4..1aa56e1 100644 --- a/library/azure_rm_webapp.py +++ b/library/azure_rm_webapp.py @@ -189,21 +189,21 @@ EXAMPLES = ''' - name: Create a windows web app with non-exist app service plan azure_rm_webapp: - resource_group: myresourcegroup - name: mywinwebapp + resource_group: myResourceGroup + name: myWinWebapp plan: - resource_group: myappserviceplan_rg - name: myappserviceplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan is_linux: false sku: S1 - name: Create a docker web app with some app settings, with docker image azure_rm_webapp: - resource_group: myresourcegroup - name: mydockerwebapp + resource_group: myResourceGroup + name: myDockerWebapp plan: - resource_group: appserviceplan_test - name: myappplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan is_linux: true sku: S1 number_of_workers: 2 @@ -215,9 +215,9 @@ - name: Create a docker web app with private acr registry azure_rm_webapp: - resource_group: myresourcegroup - name: mydockerwebapp - plan: myappplan + resource_group: myResourceGroup + name: myDockerWebapp + plan: myAppServicePlan app_settings: testkey: testvalue container_settings: @@ -228,11 +228,11 @@ - name: Create a linux web app with Node 6.6 framework azure_rm_webapp: - resource_group: myresourcegroup - name: mylinuxwebapp + resource_group: myResourceGroup + name: myLinuxWebapp plan: - resource_group: appserviceplan_test - name: myappplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan app_settings: testkey: testvalue frameworks: @@ -241,11 +241,11 @@ - name: Create a windows web app with node, php azure_rm_webapp: - resource_group: myresourcegroup - name: mywinwebapp + resource_group: myResourceGroup + name: myWinWebapp plan: - resource_group: appserviceplan_test - name: myappplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan app_settings: testkey: testvalue frameworks: @@ -256,21 +256,21 @@ - name: Create a stage deployment slot for an existing web app azure_rm_webapp: - resource_group: myresourcegroup - name: mywebapp/slots/stage + resource_group: myResourceGroup + name: myWebapp/slots/stage plan: - resource_group: myresourcegroup - name: myappplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan app_settings: testkey:testvalue - name: Create a linux web app with java framework azure_rm_webapp: - resource_group: myresourcegroup - name: mylinuxwebapp + resource_group: myResourceGroup + name: myLinuxWebapp plan: - resource_group: appserviceplan_test - name: myappplan + resource_group: myAppServicePlan_rg + name: myAppServicePlan app_settings: testkey: testvalue frameworks: @@ -287,7 +287,7 @@ returned: always type: dict sample: { - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/ansiblewindowsaaa" + "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myWebApp" } ''' diff --git a/library/azure_rm_webapp_facts.py b/library/azure_rm_webapp_facts.py index bfe355f..012e9a1 100644 --- a/library/azure_rm_webapp_facts.py +++ b/library/azure_rm_webapp_facts.py @@ -75,7 +75,7 @@ - Id of the web app. returned: always type: str - sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/xx + sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myWebApp name: description: - Name of the web app. @@ -97,7 +97,7 @@ - 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/xxx + 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. diff --git a/tests/integration/targets/azure_rm_autoscale/aliases b/tests/integration/targets/azure_rm_autoscale/aliases index 19533b3..9b642b4 100644 --- a/tests/integration/targets/azure_rm_autoscale/aliases +++ b/tests/integration/targets/azure_rm_autoscale/aliases @@ -1,4 +1,4 @@ cloud/azure -shippable/azure/group5 +shippable/azure/group2 destructive azure_rm_autoscale diff --git a/tests/integration/targets/azure_rm_cdnprofile/aliases b/tests/integration/targets/azure_rm_cdnprofile/aliases index 0d2c6ef..f5c7265 100644 --- a/tests/integration/targets/azure_rm_cdnprofile/aliases +++ b/tests/integration/targets/azure_rm_cdnprofile/aliases @@ -1,5 +1,5 @@ cloud/azure -shippable/azure/group4 +shippable/azure/group2 destructive azure_rm_cdnprofile_facts -azure_rm_cdnendpoint \ No newline at end of file +azure_rm_cdnendpoint diff --git a/tests/integration/targets/azure_rm_hdinsightcluster/aliases b/tests/integration/targets/azure_rm_hdinsightcluster/aliases index 4fda298..cb8cb9a 100644 --- a/tests/integration/targets/azure_rm_hdinsightcluster/aliases +++ b/tests/integration/targets/azure_rm_hdinsightcluster/aliases @@ -2,3 +2,4 @@ cloud/azure destructive shippable/azure/group1 unstable # test is slow (~30 minute run time), not unstable, but this is better than unsupported +azure_rm_hdinsightcluster_facts diff --git a/tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml b/tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml index a7e8d8c..62c586b 100644 --- a/tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml +++ b/tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml @@ -199,6 +199,27 @@ that: - output.changed +- name: Get facts of Cluster + azure_rm_hdinsightcluster_facts: + resource_group: "{{ resource_group }}" + name: "cluster{{ rpfx }}" + register: output + +- name: Assert that facts are returned + assert: + that: + - output.changed == False + - output.clusters[0]['id'] != None + - output.clusters[0]['resource_group'] != None + - output.clusters[0]['name'] != None + - output.clusters[0]['location'] != None + - output.clusters[0]['cluster_version'] != None + - output.clusters[0]['os_type'] != None + - output.clusters[0]['tier'] != None + - output.clusters[0]['cluster_definition'] != None + - output.clusters[0]['compute_profile_roles'] != None + - output.clusters[0]['connectivity_endpoints'] != None + - name: Delete instance of Cluster -- check mode azure_rm_hdinsightcluster: resource_group: "{{ resource_group }}" diff --git a/tests/integration/targets/azure_rm_mariadbserver/aliases b/tests/integration/targets/azure_rm_mariadbserver/aliases index 1ca78d0..a606c7c 100644 --- a/tests/integration/targets/azure_rm_mariadbserver/aliases +++ b/tests/integration/targets/azure_rm_mariadbserver/aliases @@ -1,6 +1,6 @@ cloud/azure destructive -shippable/azure/group8 +shippable/azure/group3 azure_rm_mariadbserver_facts azure_rm_mariadbdatabase azure_rm_mariadbdatabase_facts diff --git a/tests/integration/targets/azure_rm_rediscache/tasks/main.yml b/tests/integration/targets/azure_rm_rediscache/tasks/main.yml index 72d46f7..dc0c61f 100644 --- a/tests/integration/targets/azure_rm_rediscache/tasks/main.yml +++ b/tests/integration/targets/azure_rm_rediscache/tasks/main.yml @@ -13,6 +13,7 @@ sku: name: basic size: C1 + wait_for_provisioning: False check_mode: yes register: output @@ -28,6 +29,7 @@ sku: name: basic size: C1 + wait_for_provisioning: False register: output - name: Assert creating redis cache @@ -59,6 +61,7 @@ sku: name: basic size: C1 + wait_for_provisioning: False register: output - name: assert output not changed @@ -92,6 +95,7 @@ enable_non_ssl_port: true tags: testing: foo + wait_for_provisioning: True register: output - name: assert output changed @@ -106,7 +110,7 @@ sku: name: basic size: C1 - enable_non_ssl_port: true + enable_non_ssl_port: True maxmemory_policy: allkeys_lru tags: testing: foo @@ -126,21 +130,13 @@ size: C1 tags: testing: foo + wait_for_provisioning: True register: output - assert: that: - output.changed - - name: Wait for Redis provisioning to complete - azure_rm_rediscache_facts: - resource_group: "{{ resource_group }}" - name: "{{ redis_name }}" - register: facts - until: facts.rediscaches[0]['provisioning_state'] == 'Succeeded' - retries: 30 - delay: 60 - - name: Force reboot redis cache azure_rm_rediscache: resource_group: "{{ resource_group }}" @@ -201,6 +197,7 @@ subnet: name: "{{ subnet_name }}" virtual_network_name: "{{ vnet_name }}" + wait_for_provisioning: False register: output - name: Assert creating redis cache diff --git a/tests/integration/targets/azure_rm_routetable/aliases b/tests/integration/targets/azure_rm_routetable/aliases index 239e365..759eafa 100644 --- a/tests/integration/targets/azure_rm_routetable/aliases +++ b/tests/integration/targets/azure_rm_routetable/aliases @@ -1,3 +1,3 @@ cloud/azure -shippable/azure/group4 +shippable/azure/group3 destructive diff --git a/tests/integration/targets/azure_rm_subnet/tasks/main.yml b/tests/integration/targets/azure_rm_subnet/tasks/main.yml index 1d8d71d..8b4efcc 100644 --- a/tests/integration/targets/azure_rm_subnet/tasks/main.yml +++ b/tests/integration/targets/azure_rm_subnet/tasks/main.yml @@ -77,9 +77,6 @@ locations: - eastus - westus - tags: - testing: testing - delete: on-fini - name: Should be idempotent azure_rm_subnet: @@ -92,9 +89,6 @@ locations: - eastus - westus - tags: - testing: testing - delete: on-fini register: output - assert: @@ -116,9 +110,6 @@ security_group: name: secgroupfoo resource_group: "{{ resource_group_secondary }}" - tags: - testing: testing - delete: on-fini register: output - assert: @@ -133,9 +124,6 @@ resource_group: "{{ resource_group }}" address_prefix_cidr: "10.1.0.0/16" security_group: "{{ nsg.state.id }}" - tags: - testing: testing - delete: on-fini register: output - assert: diff --git a/tests/integration/targets/azure_rm_trafficmanagerprofile/aliases b/tests/integration/targets/azure_rm_trafficmanagerprofile/aliases index 239e365..a31676e 100644 --- a/tests/integration/targets/azure_rm_trafficmanagerprofile/aliases +++ b/tests/integration/targets/azure_rm_trafficmanagerprofile/aliases @@ -1,3 +1,3 @@ cloud/azure -shippable/azure/group4 +shippable/azure/group6 destructive diff --git a/tests/integration/targets/azure_rm_virtualnetworkgateway/aliases b/tests/integration/targets/azure_rm_virtualnetworkgateway/aliases new file mode 100644 index 0000000..aa77c07 --- /dev/null +++ b/tests/integration/targets/azure_rm_virtualnetworkgateway/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group2 +destructive diff --git a/tests/integration/targets/azure_rm_virtualnetworkgateway/meta/main.yml b/tests/integration/targets/azure_rm_virtualnetworkgateway/meta/main.yml new file mode 100644 index 0000000..95e1952 --- /dev/null +++ b/tests/integration/targets/azure_rm_virtualnetworkgateway/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/tests/integration/targets/azure_rm_virtualnetworkgateway/tasks/main.yml b/tests/integration/targets/azure_rm_virtualnetworkgateway/tasks/main.yml new file mode 100644 index 0000000..146d376 --- /dev/null +++ b/tests/integration/targets/azure_rm_virtualnetworkgateway/tasks/main.yml @@ -0,0 +1,126 @@ +# FIXME: needs minimal tests (check mode?) that can run quickly, VNG creation takes > 20min + +- name: Prepare random number + set_fact: + vnetname: "vnet{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + vngname: "vng{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + +- name: Create virtual network gateway without bgp settings (check mode) + check_mode: yes + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testPublicIP + virtual_network: "{{ vnetname }}" + tags: + common: "xyz" + register: output + +- assert: + that: output.changed + +- name: long-running virtualnetworkgateway tests [run with `--tags long_run,untagged` to enable] + tags: [long_run, never] + block: + - name: Create virtual network + azure_rm_virtualnetwork: + resource_group: "{{ resource_group }}" + name: "{{ vnetname }}" + address_prefixes: "10.0.0.0/16" + + - name: Add subnet + azure_rm_subnet: + resource_group: "{{ resource_group }}" + name: GatewaySubnet + address_prefix: "10.0.2.0/24" + virtual_network: "{{ vnetname }}" + + - name: Create public IP address + azure_rm_publicipaddress: + resource_group: "{{ resource_group }}" + allocation_method: Dynamic + name: testPublicIP + + - name: Create virtual network gateway without bgp settings + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testPublicIP + virtual_network: "{{ vnetname }}" + tags: + common: "xyz" + register: output + + - assert: + that: output.changed + + - name: Create virtual network gateway without bgp settings + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testPublicIP + virtual_network: "{{ vnetname }}" + tags: + common: "xyz" + register: output + + - assert: + that: output.changed + + - name: Create virtual network gateway without bgp settings - idempotent + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testPublicIP + virtual_network: "{{ vnetname }}" + tags: + common: "xyz" + register: output + + - assert: + that: not output.changed + + - name: Update virtual network gateway + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + ip_configurations: + - name: testipconfig + private_ip_allocation_method: Dynamic + public_ip_address_name: testPublicIP + virtual_network: "{{ vnetname }}" + tags: + common: "mno" + register: output + - assert: + that: output.changed + + - name: Delete virtual network gateway + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + state: absent + register: output + - assert: + that: output.changed + +- name: Delete virtual network gateway - idempotent + azure_rm_virtualnetworkgateway: + resource_group: "{{ resource_group }}" + name: "{{ vngname }}" + state: absent + register: output +- assert: + that: not output.changed