From fc6476bd72b5ecea52f6ccbd72aa87648ed04593 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Thu, 23 Jan 2020 10:15:57 +0530 Subject: [PATCH] VMware: Handle multiple tags with different category (#66465) vmware_tag_info used to return dict of tag information which caused data loss when there are multiple tags with same name and different category ids. This fix will add additional fact "tag_info" which will deprecated existing fact "tag_facts". The "tag_info" is a list which handles multiple tags with same name. Signed-off-by: Abhijeet Kasurde --- .../rst/porting_guides/porting_guide_2.10.rst | 2 +- .../modules/cloud/vmware/vmware_tag_info.py | 72 ++++++++++++++++--- .../vmware_tag/tasks/tag_manager_ops.yml | 2 +- .../targets/vmware_tag_info/aliases | 3 + .../targets/vmware_tag_info/tasks/main.yml | 5 ++ .../vmware_tag_info/tasks/tag_info.yml | 24 +++++++ 6 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 test/integration/targets/vmware_tag_info/aliases create mode 100644 test/integration/targets/vmware_tag_info/tasks/main.yml create mode 100644 test/integration/targets/vmware_tag_info/tasks/tag_info.yml diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst index 960d14b51c3..0cc111683e7 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst @@ -82,7 +82,7 @@ The following functionality will change in Ansible 2.14. Please update update yo * :ref:`iam_policy `: the default value for the ``skip_duplicates`` option will change from ``true`` to ``false``. To maintain the existing behavior explicitly set it to ``true``. * :ref:`iam_role `: the ``purge_policies`` option (also know as ``purge_policy``) default value will change from ``true`` to ``false`` * :ref:`elb_network_lb `: the default behaviour for the ``state`` option will change from ``absent`` to ``present``. To maintain the existing behavior explicitly set state to ``absent``. - +* :ref:`vmware_tag_info `: the module will not return ``tag_facts`` since it does not return multiple tags with the same name and different category id. To maintain the existing behavior use ``tag_info`` which is a list of tag metadata. The following modules will be removed in Ansible 2.14. Please update your playbooks accordingly. diff --git a/lib/ansible/modules/cloud/vmware/vmware_tag_info.py b/lib/ansible/modules/cloud/vmware/vmware_tag_info.py index f3f6b2c7ba4..d23cc61f26d 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_tag_info.py +++ b/lib/ansible/modules/cloud/vmware/vmware_tag_info.py @@ -24,6 +24,8 @@ description: - Tag feature is introduced in vSphere 6 version, so this module is not supported in the earlier versions of vSphere. - All variables and VMware object names are case sensitive. - This module was called C(vmware_tag_facts) before Ansible 2.9. The usage did not change. +- C(tag_facts) will be deprecated in Ansible 2.14, since it does not return multiple tags with same name and different category id. +- Please use C(tag_info) instead of C(tag_facts). version_added: '2.6' author: - Abhijeet Kasurde (@Akasurde) @@ -55,10 +57,24 @@ EXAMPLES = r''' - debug: msg: "{{ tag_details.tag_facts['fedora_machines']['tag_category_id'] }}" +- name: Gather tag id from the given tag + vmware_tag_info: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + delegate_to: localhost + register: tag_results +- set_fact: + tag_id: "{{ item.tag_id }}" + loop: "{{ tag_results.tag_info|json_query(query) }}" + vars: + query: "[?tag_name==`tag0001`]" +- debug: var=tag_id ''' RETURN = r''' -results: +tag_facts: description: dictionary of tag metadata returned: on success type: dict @@ -82,6 +98,31 @@ results: "tag_used_by": [] } } + +tag_info: + description: list of tag metadata + returned: on success + type: list + sample: [ + { "tag_name": "Sample_Tag_0002", + "tag_category_id": "urn:vmomi:InventoryServiceCategory:6de17f28-7694-43ec-a783-d09c141819ae:GLOBAL", + "tag_description": "Sample Description", + "tag_id": "urn:vmomi:InventoryServiceTag:a141f212-0f82-4f05-8eb3-c49647c904c5:GLOBAL", + "tag_used_by": [] + }, + { "tag_name": "Sample_Tag_0002", + "tag_category_id": "urn:vmomi:InventoryServiceCategory:6de17f28-7694-43ec-a783-d09c141819ae:GLOBAL", + "tag_description": "", + "tag_id": "urn:vmomi:InventoryServiceTag:7d27d182-3ecd-4200-9d72-410cc6398a8a:GLOBAL", + "tag_used_by": [] + }, + { "tag_name": "ubuntu_machines", + "tag_category_id": "urn:vmomi:InventoryServiceCategory:89573410-29b4-4cac-87a4-127c084f3d50:GLOBAL", + "tag_description": "", + "tag_id": "urn:vmomi:InventoryServiceTag:7f3516d5-a750-4cb9-8610-6747eb39965d:GLOBAL", + "tag_used_by": [] + } + ] ''' from ansible.module_utils.basic import AnsibleModule @@ -92,21 +133,36 @@ class VmTagInfoManager(VmwareRestClient): def __init__(self, module): """Constructor.""" super(VmTagInfoManager, self).__init__(module) - self.tag_service = self.api_client.tagging.Tag - self.global_tags = dict() def get_all_tags(self): - """Function to retrieve all tag information.""" - for tag in self.tag_service.list(): - tag_obj = self.tag_service.get(tag) - self.global_tags[tag_obj.name] = dict( + """ + Retrieve all tag information. + """ + global_tag_info = list() + # Backward compatability + global_tags = dict() + tag_service = self.api_client.tagging.Tag + for tag in tag_service.list(): + tag_obj = tag_service.get(tag) + global_tags[tag_obj.name] = dict( tag_description=tag_obj.description, tag_used_by=tag_obj.used_by, tag_category_id=tag_obj.category_id, tag_id=tag_obj.id ) + global_tag_info.append(dict( + tag_name=tag_obj.name, + tag_description=tag_obj.description, + tag_used_by=tag_obj.used_by, + tag_category_id=tag_obj.category_id, + tag_id=tag_obj.id + )) - self.module.exit_json(changed=False, tag_facts=self.global_tags) + self.module.exit_json( + changed=False, + tag_facts=global_tags, + tag_info=global_tag_info + ) def main(): diff --git a/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml b/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml index 1e949e0e117..14158cfca0b 100644 --- a/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml +++ b/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml @@ -29,7 +29,7 @@ name: Get info about tag in check mode check_mode: yes - - set_fact: Tag_Name={{ tag_info['tag_info'].keys() | list }} + - set_fact: Tag_Name={{ tag_info['tag_facts'].keys() | list }} - debug: var=Tag_Name diff --git a/test/integration/targets/vmware_tag_info/aliases b/test/integration/targets/vmware_tag_info/aliases new file mode 100644 index 00000000000..9cc67c4113a --- /dev/null +++ b/test/integration/targets/vmware_tag_info/aliases @@ -0,0 +1,3 @@ +cloud/vcenter +unsupported +zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_tag_info/tasks/main.yml b/test/integration/targets/vmware_tag_info/tasks/main.yml new file mode 100644 index 00000000000..c7b0209a928 --- /dev/null +++ b/test/integration/targets/vmware_tag_info/tasks/main.yml @@ -0,0 +1,5 @@ +# Test code for the vmware_tag_info. +# Copyright: (c) 2020, Abhijeet Kasurde +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- include: tag_info.yml \ No newline at end of file diff --git a/test/integration/targets/vmware_tag_info/tasks/tag_info.yml b/test/integration/targets/vmware_tag_info/tasks/tag_info.yml new file mode 100644 index 00000000000..819faaad342 --- /dev/null +++ b/test/integration/targets/vmware_tag_info/tasks/tag_info.yml @@ -0,0 +1,24 @@ +# Test code for the vmware_tag_info. +# Copyright: (c) 2020, Abhijeet Kasurde +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- when: vcsim is not defined + block: + - &tag_info + name: Get info about tag + vmware_tag_info: + hostname: '{{ vcenter_hostname }}' + username: '{{ vcenter_username }}' + password: '{{ vcenter_password }}' + validate_certs: False + register: tag_info + + - <<: *tag_info + name: Get info about tag in check mode + check_mode: yes + + - name: Check if facts exists + assert: + that: + - tag_info['tag_facts'] is defined + - tag_info['tag_info'] is defined