From 2108b5f7365f9ea8f91553ccf5475c82f77365f8 Mon Sep 17 00:00:00 2001 From: Fred-sun Date: Thu, 1 Aug 2024 17:12:34 +0800 Subject: [PATCH 1/4] Add support for list snapshot instance --- plugins/modules/azure_rm_snapshot_info.py | 261 ++++++++++++++++++ .../targets/azure_rm_gallery/tasks/main.yml | 10 + 2 files changed, 271 insertions(+) create mode 100644 plugins/modules/azure_rm_snapshot_info.py diff --git a/plugins/modules/azure_rm_snapshot_info.py b/plugins/modules/azure_rm_snapshot_info.py new file mode 100644 index 000000000..170ebd50b --- /dev/null +++ b/plugins/modules/azure_rm_snapshot_info.py @@ -0,0 +1,261 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# 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 + + +DOCUMENTATION = ''' +--- +module: azure_rm_snapshot_info +version_added: "2.7.0" +short_description: Get the Azure Snapshot instance facts +description: + - Get or list instance facts of Azure Snapshot. +options: + resource_group: + description: + - The name of the resource group. + required: true + type: str + name: + description: + - Resource name. + type: str + tags: + descrition: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + type: list + elements: str + +extends_documentation_fragment: + - azure.azcollection.azure + - azure.azcollection.azure_tags +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Get the snapshot instance by name + azure_rm_snapshot_info: + resource_group: myResourceGroup + name: mySnapshot + +- name: List all snapshots by resource group and filter by tags + azure_rm_snapshot_info: + resource_group: myResourceGroup + name: mySnapshot +''' + +RETURN = ''' +state: + descrition: + - The description of the snapshot instance facts. + type: complex + returned: always + contains: + id: + description: + - The Snapshot instance ID. + type: str + returned: always + sample: /subscription/xxx-xxx/resourceGroups/testRG/providers/Microsoft.Compute/snapshots/mySnapshot01 + location: + description: + - The Snapshot instance location. + type: str + returned: always + sample: eastus + name: + description: + - The Snapshot instance name. + type: str + returned: always + sample: mySnapshot01 + properties: + description: + - The properties of the snapshot instance. + type: dict + returned: always + sample: properties: { + "creationData": { + "createOption": "Import", + "sourceUri": "https://vmforimagerpfx01.blob.core.windows.net/vhds/vmforimagerpfx01.vhd" + }, + "diskSizeBytes": 32213303296, + "diskSizeGB": 30, + "diskState": "Unattached", + "encryption": { + "type": "EncryptionAtRestWithPlatformKey" + }, + "incremental": false, + "networkAccessPolicy": "AllowAll", + "provisioningState": "Succeeded", + "publicNetworkAccess": "Enabled", + "timeCreated": "2024-08-01T07:08:32.1635314+00:00", + "uniqueId": "85607f7a-ce44-40bd-a523-a7e2a10d72c3" + } + sku: + description: + - The snapshots sku option. + type: complex + returned: always + contains: + name: + description: + - The Sku name. + type: str + returned: always + sample: Standard_LRS + tier: + description: + - The Sku tier. + type: str + returned: always + sample: Standard + tags: + description: + - Resource tags. + type: dict + returned: always + sample: {'key1': 'value1'} + type: + description: + - Resource type. + type: str + returned: always + sample: Microsoft.Compute/snapshots +''' + +import json +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient + + +class AzureRMSnapshotsInfo(AzureRMModuleBaseExt): + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + name=dict( + type='str', + ), + tags=dict( + type='list', + elements='str' + ) + ) + + self.resource_group = None + self.name = None + self.tags = None + + self.results = dict(changed=False) + self.mgmt_client = None + self.url = None + + self.query_parameters = {} + self.status_code = [200, 201, 202] + self.query_parameters['api-version'] = '2022-03-02' + self.header_parameters = {} + self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' + + super(AzureRMSnapshotsInfo, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + facts_module=True, + supports_tags=False) + + def exec_module(self, **kwargs): + for key in list(self.module_arg_spec.keys()): + setattr(self, key, kwargs[key]) + + response = None + + self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + if self.name is not None: + self.results['state'] = self.get() + else: + self.results['state'] = self.list_by_resourcegroup() + + return self.results + + def get(self): + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/snapshots' + + '/{{ snapshot_name }}') + self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) + self.url = self.url.replace('{{ resource_group }}', self.resource_group) + self.url = self.url.replace('{{ snapshot_name }}', self.name) + response = None + try: + response = self.mgmt_client.query(url=self.url, + method='GET', + query_parameters=self.query_parameters, + header_parameters=self.header_parameters, + body=None, + expected_status_codes=self.status_code, + polling_timeout=600, + polling_interval=30) + response = json.loads(response.body()) + self.log("Response : {0}".format(response)) + except Exception as e: + self.log('Did not find the Snapshot instance.') + if response and self.has_tags(response['tags'], self.tags): + return [response] + else: + return [] + + def list_by_resourcegroup(self): + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/snapshots') + self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) + self.url = self.url.replace('{{ resource_group }}', self.resource_group) + response = None + results = [] + + try: + response = self.mgmt_client.query(url=self.url, + method='GET', + query_parameters=self.query_parameters, + header_parameters=self.header_parameters, + body=None, + expected_status_codes=self.status_code, + polling_timeout=600, + polling_interval=30) + response = json.loads(response.body()) + self.log("Response : {0}".format(response)) + # self.log("Snapshot instance : {0} found".format(response.name)) + except Exception as e: + self.log('Did not find the Snapshot instance.') + for item in response['value']: + if self.has_tags(item['tags'], self.tags): + results.append(item) + + return results + + +def main(): + AzureRMSnapshotsInfo() + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/azure_rm_gallery/tasks/main.yml b/tests/integration/targets/azure_rm_gallery/tasks/main.yml index 3389336dc..9cbdb2df3 100644 --- a/tests/integration/targets/azure_rm_gallery/tasks/main.yml +++ b/tests/integration/targets/azure_rm_gallery/tasks/main.yml @@ -126,6 +126,16 @@ that: - output.changed +- name: List the snapshot instance by resource group + azure_rm_snapshot_info: + resource_group: "{{ resource_group }}" + register: output + +- name: Assert there are two snapshots + ansible.builtin.assert: + that: + - output.state |length == 2 + - name: Create a managed disk azure_rm_manageddisk: resource_group: "{{ resource_group }}" From f18c69427fc9f077e68e96aa720954c6bec3d423 Mon Sep 17 00:00:00 2001 From: Fred-sun Date: Thu, 1 Aug 2024 18:22:06 +0800 Subject: [PATCH 2/4] small change --- meta/runtime.yml | 1 + plugins/modules/azure_rm_snapshot_info.py | 14 ++++++-------- pr-pipelines.yml | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index d8eeab9cf..bca4d790c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -238,6 +238,7 @@ action_groups: - azure.azcollection.azure_rm_servicebustopic - azure.azcollection.azure_rm_servicebustopicsubscription - azure.azcollection.azure_rm_snapshot + - azure.azcollection.azure_rm_snapshot_info - azure.azcollection.azure_rm_sqldatabase - azure.azcollection.azure_rm_sqldatabase_info - azure.azcollection.azure_rm_sqlelasticpool diff --git a/plugins/modules/azure_rm_snapshot_info.py b/plugins/modules/azure_rm_snapshot_info.py index 170ebd50b..8fd34e056 100644 --- a/plugins/modules/azure_rm_snapshot_info.py +++ b/plugins/modules/azure_rm_snapshot_info.py @@ -30,10 +30,8 @@ - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. type: list elements: str - extends_documentation_fragment: - azure.azcollection.azure - - azure.azcollection.azure_tags author: - xuzhang3 (@xuzhang3) - Fred-sun (@Fred-sun) @@ -82,7 +80,7 @@ - The properties of the snapshot instance. type: dict returned: always - sample: properties: { + sample: { "creationData": { "createOption": "Import", "sourceUri": "https://vmforimagerpfx01.blob.core.windows.net/vhds/vmforimagerpfx01.vhd" @@ -168,9 +166,9 @@ def __init__(self): self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' super(AzureRMSnapshotsInfo, self).__init__(derived_arg_spec=self.module_arg_spec, - supports_check_mode=True, - facts_module=True, - supports_tags=False) + supports_check_mode=True, + facts_module=True, + supports_tags=False) def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()): @@ -214,7 +212,7 @@ def get(self): self.log("Response : {0}".format(response)) except Exception as e: self.log('Did not find the Snapshot instance.') - if response and self.has_tags(response['tags'], self.tags): + if response and self.has_tags(response.get('tags'), self.tags): return [response] else: return [] @@ -247,7 +245,7 @@ def list_by_resourcegroup(self): except Exception as e: self.log('Did not find the Snapshot instance.') for item in response['value']: - if self.has_tags(item['tags'], self.tags): + if self.has_tags(item.get('tags'), self.tags): results.append(item) return results diff --git a/pr-pipelines.yml b/pr-pipelines.yml index f97a43d5c..530c16599 100644 --- a/pr-pipelines.yml +++ b/pr-pipelines.yml @@ -146,6 +146,7 @@ parameters: - "azure_rm_sqlmidbshorttermretentionpolicy" - "azure_rm_vmssnetworkinterface_info" - "azure_rm_sshpublickey" + - "azure_rm_snapshot" - "azure_rm_networkwatcher" - "inventory_azure" - "setup_azure" From cc3695e7899c715e5b794e984e4894f1a5a10211 Mon Sep 17 00:00:00 2001 From: Fred-sun Date: Thu, 1 Aug 2024 22:12:38 +0800 Subject: [PATCH 3/4] fix sanity error --- plugins/modules/azure_rm_snapshot_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/azure_rm_snapshot_info.py b/plugins/modules/azure_rm_snapshot_info.py index 8fd34e056..f1741474d 100644 --- a/plugins/modules/azure_rm_snapshot_info.py +++ b/plugins/modules/azure_rm_snapshot_info.py @@ -26,7 +26,7 @@ - Resource name. type: str tags: - descrition: + description: - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. type: list elements: str @@ -52,7 +52,7 @@ RETURN = ''' state: - descrition: + description: - The description of the snapshot instance facts. type: complex returned: always From 939340158f0a6df7bc397958098343ece1b86c24 Mon Sep 17 00:00:00 2001 From: Fred-sun Date: Thu, 1 Aug 2024 22:15:36 +0800 Subject: [PATCH 4/4] new change for test case --- .../targets/azure_rm_gallery/tasks/main.yml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/integration/targets/azure_rm_gallery/tasks/main.yml b/tests/integration/targets/azure_rm_gallery/tasks/main.yml index 9cbdb2df3..9610d3ae0 100644 --- a/tests/integration/targets/azure_rm_gallery/tasks/main.yml +++ b/tests/integration/targets/azure_rm_gallery/tasks/main.yml @@ -126,16 +126,6 @@ that: - output.changed -- name: List the snapshot instance by resource group - azure_rm_snapshot_info: - resource_group: "{{ resource_group }}" - register: output - -- name: Assert there are two snapshots - ansible.builtin.assert: - that: - - output.state |length == 2 - - name: Create a managed disk azure_rm_manageddisk: resource_group: "{{ resource_group }}" @@ -159,6 +149,16 @@ that: - output.changed +- name: List the snapshot instance by resource group + azure_rm_snapshot_info: + resource_group: "{{ resource_group }}" + register: output + +- name: Assert there are two snapshots + ansible.builtin.assert: + that: + - output.state |length == 2 + - name: Generalize VM azure_rm_virtualmachine: resource_group: "{{ resource_group }}"