From 8f0bf3e453b2fc97e510944187dd553481f15546 Mon Sep 17 00:00:00 2001 From: smile37773 <34502364+smile37773@users.noreply.github.com> Date: Wed, 3 Jul 2019 13:48:14 +0800 Subject: [PATCH] Add the azure_rm_..._info modules (#58576) --- .../cloud/azure/azure_rm_gallery_info.py | 263 +++++++++++++++++ .../cloud/azure/azure_rm_galleryimage_info.py | 278 ++++++++++++++++++ .../azure_rm_galleryimageversion_info.py | 276 +++++++++++++++++ .../targets/azure_rm_gallery/tasks/main.yml | 49 +++ 4 files changed, 866 insertions(+) create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_gallery_info.py create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_galleryimage_info.py create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion_info.py diff --git a/lib/ansible/modules/cloud/azure/azure_rm_gallery_info.py b/lib/ansible/modules/cloud/azure/azure_rm_gallery_info.py new file mode 100644 index 00000000000..745e3b2efd8 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_gallery_info.py @@ -0,0 +1,263 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Liu Qingyi, (@smile37773) +# +# 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_gallery_info +version_added: '2.9' +short_description: Get Azure Shared Image Gallery info. +description: + - Get info of Azure Shared Image Gallery. +options: + resource_group: + description: + - The name of the resource group. + type: str + name: + description: + - Resource name + type: str +extends_documentation_fragment: + - azure +author: + - Liu Qingyi (@smile37773) + +''' + +EXAMPLES = ''' +- name: List galleries in a subscription. + azure_rm_gallery_info: +- name: List galleries in a resource group. + azure_rm_gallery_info: + resource_group: myResourceGroup +- name: Get a gallery. + azure_rm_gallery_info: + resource_group: myResourceGroup + name: myGallery + +''' + +RETURN = ''' +galleries: + description: >- + A list of dict results where the key is the name of the gallery and the + values are the info for that gallery. + returned: always + type: complex + contains: + id: + description: + - Resource Id + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + /resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGallery" + name: + description: + - Resource name + returned: always + type: str + sample: "myGallery" + location: + description: + - Resource location + returned: always + type: str + sample: "eastus" + tags: + description: + - Resource tags + returned: always + type: dict + sample: { "tag": "value" } + description: + description: + - This is the gallery description. + type: str + sample: "This is the gallery description." + provisioning_state: + description: + - The current state of the gallery. + type: str + sample: "Succeeded" + +''' + +import time +import json +from ansible.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.azure_rm_common_rest import GenericRestClient +from copy import deepcopy +try: + from msrestazure.azure_exceptions import CloudError +except Exception: + # handled in azure_rm_common + pass + + +class AzureRMGalleriesInfo(AzureRMModuleBase): + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str' + ), + name=dict( + type='str' + ) + ) + + self.resource_group = None + self.name = None + + self.results = dict(changed=False) + self.mgmt_client = None + self.state = None + self.url = None + self.status_code = [200] + + self.query_parameters = {} + self.query_parameters['api-version'] = '2019-03-01' + self.header_parameters = {} + self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' + + self.mgmt_client = None + super(AzureRMGalleriesInfo, 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.resource_group is not None and self.name is not None): + # self.results['galleries'] = self.format_item(self.get()) + self.results['galleries'] = self.get() + elif (self.resource_group is not None): + # self.results['galleries'] = self.format_item(self.listbyresourcegroup()) + self.results['galleries'] = self.listbyresourcegroup() + else: + # self.results['galleries'] = [self.format_item(self.list())] + self.results['galleries'] = self.list() + return self.results + + def get(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries' + + '/{{ gallery_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('{{ gallery_name }}', self.name) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return self.format_item(results) + + def listbyresourcegroup(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries') + self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) + self.url = self.url.replace('{{ resource_group }}', self.resource_group) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return [self.format_item(x) for x in results['value']] if results['value'] else [] + + def list(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries') + self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return [self.format_item(x) for x in results['value']] if results['value'] else [] + + def format_item(self, item): + d = { + 'id': item['id'], + 'name': item['name'], + 'location': item['location'], + 'tags': item.get('tags'), + 'description': item['properties']['description'], + 'provisioning_state': item['properties']['provisioningState'] + } + return d + + +def main(): + AzureRMGalleriesInfo() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/azure/azure_rm_galleryimage_info.py b/lib/ansible/modules/cloud/azure/azure_rm_galleryimage_info.py new file mode 100644 index 00000000000..e58a1f4e027 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_galleryimage_info.py @@ -0,0 +1,278 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Liu Qingyi, (@smile37773) +# +# 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_galleryimage_info +version_added: '2.9' +short_description: Get Azure SIG Image info. +description: + - Get info of Azure SIG Image. +options: + resource_group: + description: + - The name of the resource group. + type: str + required: true + gallery_name: + description: + - >- + The name of the shared image gallery from which the image definitions + are to be retrieved. + type: str + required: true + name: + description: + - Resource name + type: str +extends_documentation_fragment: + - azure +author: + - Liu Qingyi (@smile37773) + +''' + +EXAMPLES = ''' +- name: List gallery images in a gallery. + azure_rm_galleryimage_info: + resource_group: myResourceGroup + gallery_name: myGallery +- name: Get a gallery image. + azure_rm_galleryimage_info: + resource_group: myResourceGroup + gallery_name: myGallery + name: myImage + +''' + +RETURN = ''' +images: + description: >- + A list of dict results where the key is the name of the image and the + values are the info for that image. + returned: always + type: complex + contains: + id: + description: + - Resource Id + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup + /providers/Microsoft.Compute/galleries/myGallery/images/myImage" + name: + description: + - Resource name + returned: always + type: str + sample: myImage + location: + description: + - Resource location + returned: always + type: str + sample: "eastus" + tags: + description: + - Resource tags + returned: always + type: dict + sample: { "tag": "value" } + os_state: + description: + - The allowed values for OS State are 'Generalized'. + type: OperatingSystemStateTypes + sample: "Generalized" + os_type: + description: >- + This property allows you to specify the type of the OS that is included in the disk + when creating a VM from a managed image. + type: OperatingSystemTypes + sample: "linux/windows" + identifier: + description: + - This is the gallery image definition identifier. + type: dict + contains: + offer: + description: + - The name of the gallery image definition offer. + type: str + sample: "myOfferName" + publisher: + description: + - The name of the gallery image definition publisher. + type: str + sample: "myPublisherName" + sku: + description: + - The name of the gallery image definition sku. + type: str + sample: "mySkuName" + +''' + +import time +import json +from ansible.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.azure_rm_common_rest import GenericRestClient +from copy import deepcopy +try: + from msrestazure.azure_exceptions import CloudError +except Exception: + # handled in azure_rm_common + pass + + +class AzureRMGalleryImagesInfo(AzureRMModuleBase): + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + gallery_name=dict( + type='str', + required=True + ), + name=dict( + type='str' + ) + ) + + self.resource_group = None + self.gallery_name = None + self.name = None + + self.results = dict(changed=False) + self.mgmt_client = None + self.state = None + self.url = None + self.status_code = [200] + + self.query_parameters = {} + self.query_parameters['api-version'] = '2019-03-01' + self.header_parameters = {} + self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' + + self.mgmt_client = None + super(AzureRMGalleryImagesInfo, 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.resource_group is not None and + self.gallery_name is not None and + self.name is not None): + # self.results['gallery_images'] = self.format_item(self.get()) + self.results['images'] = self.get() + elif (self.resource_group is not None and + self.gallery_name is not None): + # self.results['gallery_images'] = self.format_item(self.listbygallery()) + self.results['images'] = self.listbygallery() + return self.results + + def get(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries' + + '/{{ gallery_name }}' + + '/images' + + '/{{ image_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('{{ gallery_name }}', self.gallery_name) + self.url = self.url.replace('{{ image_name }}', self.name) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return self.format_item(results) + + def listbygallery(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries' + + '/{{ gallery_name }}' + + '/images') + 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('{{ gallery_name }}', self.gallery_name) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return [self.format_item(x) for x in results['value']] if results['value'] else [] + + def format_item(self, item): + d = { + 'id': item['id'], + 'name': item['name'], + 'location': item['location'], + 'tags': item.get('tags'), + 'os_state': item['properties']['osState'], + 'os_type': item['properties']['osType'], + 'identifier': item['properties']['identifier'] + } + return d + + +def main(): + AzureRMGalleryImagesInfo() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion_info.py b/lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion_info.py new file mode 100644 index 00000000000..3e61b48ca18 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion_info.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# +# Copyright (c) 2019 Liu Qingyi, (@smile37773) +# +# 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_galleryimageversion_info +version_added: '2.9' +short_description: Get Azure SIG Image Version info. +description: + - Get info of Azure SIG Image Version. +options: + resource_group: + description: + - The name of the resource group. + type: str + required: true + gallery_name: + description: + - >- + The name of the Shared Image Gallery in which the Image Definition + resides. + type: str + required: true + gallery_image_name: + description: + - >- + The name of the gallery Image Definition in which the Image Version + resides. + type: str + required: true + name: + description: + - Resource name + type: str +extends_documentation_fragment: + - azure +author: + - Liu Qingyi (@smile37773) + +''' + +EXAMPLES = ''' +- name: List gallery image versions in a gallery image definition. + azure_rm_galleryimageversion_info: + resource_group: myResourceGroup + gallery_name: myGallery + gallery_image_name: myImage +- name: Get a gallery image version. + azure_rm_galleryimageversion_info: + resource_group: myResourceGroup + gallery_name: myGallery + gallery_image_name: myImage + name: myVersion + +''' + +RETURN = ''' +versions: + description: >- + A list of dict results where the key is the name of the version + and the values are the info for that version. + returned: always + type: complex + contains: + id: + description: + - Resource Id + returned: always + type: str + sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups + /myResourceGroup/providers/Microsoft.Compute/galleries/myGallery/ + images/myImage/versions/myVersion" + name: + description: + - Resource name + returned: always + type: str + sample: "myVersion" + location: + description: + - Resource location + returned: always + type: str + sample: "eastus" + tags: + description: + - Resource tags + returned: always + type: dict + sample: { "tag": "value" } + publishing_profile: + description: + - The publishing profile of a gallery image version. + type: dict + provisioning_state: + description: + - The current state of the gallery. + type: str + sample: "Succeeded" + +''' + +import time +import json +from ansible.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.azure_rm_common_rest import GenericRestClient +from copy import deepcopy +try: + from msrestazure.azure_exceptions import CloudError +except Exception: + # handled in azure_rm_common + pass + + +class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + gallery_name=dict( + type='str', + required=True + ), + gallery_image_name=dict( + type='str', + required=True + ), + name=dict( + type='str' + ) + ) + + self.resource_group = None + self.gallery_name = None + self.gallery_image_name = None + self.name = None + + self.results = dict(changed=False) + self.mgmt_client = None + self.state = None + self.url = None + self.status_code = [200] + + self.query_parameters = {} + self.query_parameters['api-version'] = '2019-03-01' + self.header_parameters = {} + self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' + + self.mgmt_client = None + super(AzureRMGalleryImageVersionsInfo, 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.resource_group is not None and + self.gallery_name is not None and + self.gallery_image_name is not None and + self.name is not None): + self.results['versions'] = self.get() + elif (self.resource_group is not None and + self.gallery_name is not None and + self.gallery_image_name is not None): + self.results['versions'] = self.listbygalleryimage() + return self.results + + def get(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries' + + '/{{ gallery_name }}' + + '/images' + + '/{{ image_name }}' + + '/versions' + + '/{{ version_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('{{ gallery_name }}', self.gallery_name) + self.url = self.url.replace('{{ image_name }}', self.gallery_image_name) + self.url = self.url.replace('{{ version_name }}', self.name) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return self.format_item(results) + + def listbygalleryimage(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.Compute' + + '/galleries' + + '/{{ gallery_name }}' + + '/images' + + '/{{ image_name }}' + + '/versions') + 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('{{ gallery_name }}', self.gallery_name) + self.url = self.url.replace('{{ image_name }}', self.gallery_image_name) + + try: + response = self.mgmt_client.query(self.url, + 'GET', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.text) + # self.log('Response : {0}'.format(response)) + except CloudError as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + + return [self.format_item(x) for x in results['value']] if results['value'] else [] + + def format_item(self, item): + d = { + 'id': item['id'], + 'name': item['name'], + 'location': item['location'], + 'tags': item.get('tags'), + 'publishing_profile': item['properties']['publishingProfile'], + 'provisioning_state': item['properties']['provisioningState'] + } + return d + + +def main(): + AzureRMGalleryImageVersionsInfo() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/azure_rm_gallery/tasks/main.yml b/test/integration/targets/azure_rm_gallery/tasks/main.yml index b0d477778e1..83fac210b0c 100644 --- a/test/integration/targets/azure_rm_gallery/tasks/main.yml +++ b/test/integration/targets/azure_rm_gallery/tasks/main.yml @@ -88,6 +88,21 @@ that: - output.changed +- name: Get a gallery info. + azure_rm_gallery_info: + resource_group: "{{ resource_group }}" + name: myGallery{{ rpfx }} + register: output + +- assert: + that: + - not output.changed + - output.galleries['id'] != None + - output.galleries['name'] != None + - output.galleries['location'] != None + - output.galleries['description'] != None + - output.galleries['provisioning_state'] != None + - name: Create or update gallery image azure_rm_galleryimage: resource_group: "{{ resource_group }}" @@ -145,6 +160,23 @@ that: - output.changed +- name: Get a gallery image info. + azure_rm_galleryimage_info: + resource_group: "{{ resource_group }}" + gallery_name: myGallery{{ rpfx }} + name: myImage + register: output + +- assert: + that: + - not output.changed + - output.images['id'] != None + - output.images['name'] != None + - output.images['location'] != None + - output.images['os_state'] != None + - output.images['os_type'] != None + - output.images['identifier'] != None + - name: Create or update a simple gallery Image Version. azure_rm_galleryimageversion: resource_group: "{{ resource_group }}" @@ -226,6 +258,23 @@ that: - output.changed +- name: Get a simple gallery Image Version info. + azure_rm_galleryimageversion_info: + resource_group: "{{ resource_group }}" + gallery_name: myGallery{{ rpfx }} + gallery_image_name: myImage + name: 10.1.3 + register: output + +- assert: + that: + - not output.changed + - output.versions['id'] != None + - output.versions['name'] != None + - output.versions['location'] != None + - output.versions['publishing_profile'] != None + - output.versions['provisioning_state'] != None + - name: Delete gallery image Version. azure_rm_galleryimageversion: resource_group: "{{ resource_group }}"