From 6d97943c82226e98cc09738167f616c5d08b556c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 19 Feb 2020 17:31:54 +0100 Subject: [PATCH] New module ec2_tag_info - fetch the tags from EC2 objects (#66839) * New module ec2_tag_info - fetch the tags from EC2 objects * Add ec2_tag_info to group/aws * Add basic test case --- lib/ansible/config/module_defaults.yml | 2 + .../modules/cloud/amazon/ec2_tag_info.py | 92 +++++++++++++++++++ test/integration/targets/ec2_tag/aliases | 1 + .../targets/ec2_tag/tasks/main.yml | 38 ++++---- 4 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 lib/ansible/modules/cloud/amazon/ec2_tag_info.py diff --git a/lib/ansible/config/module_defaults.yml b/lib/ansible/config/module_defaults.yml index ebb006e4d75..5e4ffc45f5b 100644 --- a/lib/ansible/config/module_defaults.yml +++ b/lib/ansible/config/module_defaults.yml @@ -297,6 +297,8 @@ groupings: - aws ec2_tag: - aws + ec2_tag_info: + - aws ec2_transit_gateway: - aws ec2_transit_gateway_info: diff --git a/lib/ansible/modules/cloud/amazon/ec2_tag_info.py b/lib/ansible/modules/cloud/amazon/ec2_tag_info.py new file mode 100644 index 00000000000..6e607763b8c --- /dev/null +++ b/lib/ansible/modules/cloud/amazon/ec2_tag_info.py @@ -0,0 +1,92 @@ +#!/usr/bin/python +# Copyright: Ansible Project +# 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': ['stableinterface'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: ec2_tag_info +short_description: list tags on ec2 resources +description: + - Lists tags for any EC2 resource. + - Resources are referenced by their resource id (e.g. an instance being i-XXXXXXX, a vpc being vpc-XXXXXX). + - Resource tags can be managed using the M(ec2_tag) module. +version_added: "2.10" +requirements: [ "boto3", "botocore" ] +options: + resource: + description: + - The EC2 resource id (for example i-XXXXXX or vpc-XXXXXX). + required: true + type: str + +author: + - Mark Chappell (@tremble) +extends_documentation_fragment: + - aws + - ec2 +''' + +EXAMPLES = ''' +- name: Retrieve all tags on an instance + ec2_tag_info: + region: eu-west-1 + resource: i-xxxxxxxxxxxxxxxxx + register: instance_tags + +- name: Retrieve all tags on a VPC + ec2_tag_info: + region: eu-west-1 + resource: vpc-xxxxxxxxxxxxxxxxx + register: vpc_tags +''' + +RETURN = ''' +tags: + description: A dict containing the tags on the resource + returned: always + type: dict +''' + +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.ec2 import boto3_tag_list_to_ansible_dict, AWSRetry + +try: + from botocore.exceptions import BotoCoreError, ClientError +except Exception: + pass # Handled by AnsibleAWSModule + + +@AWSRetry.jittered_backoff() +def get_tags(ec2, module, resource): + filters = [{'Name': 'resource-id', 'Values': [resource]}] + return boto3_tag_list_to_ansible_dict(ec2.describe_tags(Filters=filters)['Tags']) + + +def main(): + argument_spec = dict( + resource=dict(required=True), + ) + + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) + resource = module.params['resource'] + ec2 = module.client('ec2') + + try: + current_tags = get_tags(ec2, module, resource) + except (BotoCoreError, ClientError) as e: + module.fail_json_aws(e, msg='Failed to fetch tags for resource {0}'.format(resource)) + + module.exit_json(changed=False, tags=current_tags) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ec2_tag/aliases b/test/integration/targets/ec2_tag/aliases index 6e3860bee23..be56eee8941 100644 --- a/test/integration/targets/ec2_tag/aliases +++ b/test/integration/targets/ec2_tag/aliases @@ -1,2 +1,3 @@ cloud/aws shippable/aws/group2 +ec2_tag_info diff --git a/test/integration/targets/ec2_tag/tasks/main.yml b/test/integration/targets/ec2_tag/tasks/main.yml index 81a12b44a65..7e8cd8d128b 100644 --- a/test/integration/targets/ec2_tag/tasks/main.yml +++ b/test/integration/targets/ec2_tag/tasks/main.yml @@ -1,37 +1,39 @@ --- # tasks file for test_ec2_tag - name: Set up AWS connection info - set_fact: - aws_connection_info: &aws_connection_info + module_defaults: + group/aws: aws_access_key: "{{ aws_access_key }}" aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" + security_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" - no_log: true - -- block: + block: - name: Create an EC2 volume so we have something to tag ec2_vol: name: "{{ resource_prefix }} ec2_tag volume" volume_size: 1 state: present zone: "{{ aws_region }}a" - <<: *aws_connection_info register: volume - - name: List the tags + - name: List the tags on the volume (ec2_tag) ec2_tag: resource: "{{ volume.volume_id }}" state: list - <<: *aws_connection_info register: result + - name: List the tags on the volume (ec2_tag_info) + ec2_tag_info: + resource: "{{ volume.volume_id }}" + register: result_info - assert: that: - result.tags | length == 1 - result.tags.Name == '{{ resource_prefix }} ec2_tag volume' + - result_info.tags | length == 1 + - result_info.tags.Name == '{{ resource_prefix }} ec2_tag volume' - - name: Set some new tags + - name: Set some new tags on the volume ec2_tag: resource: "{{ volume.volume_id }}" state: present @@ -39,8 +41,11 @@ foo: foo bar: baz baz: also baz - <<: *aws_connection_info register: result + - name: List the new tags on the volume + ec2_tag_info: + resource: "{{ volume.volume_id }}" + register: result_info - assert: that: @@ -51,6 +56,11 @@ - result.tags.foo == 'foo' - result.tags.bar == 'baz' - result.tags.baz == 'also baz' + - result_info.tags | length == 4 + - result_info.tags.Name == '{{ resource_prefix }} ec2_tag volume' + - result_info.tags.foo == 'foo' + - result_info.tags.bar == 'baz' + - result_info.tags.baz == 'also baz' - name: Remove a tag by name ec2_tag: @@ -58,7 +68,6 @@ state: absent tags: baz: - <<: *aws_connection_info register: result - assert: @@ -73,7 +82,6 @@ state: absent tags: foo: baz - <<: *aws_connection_info register: result - assert: @@ -86,7 +94,6 @@ state: absent tags: foo: foo - <<: *aws_connection_info register: result - assert: @@ -104,7 +111,6 @@ purge_tags: true tags: baz: quux - <<: *aws_connection_info register: result - assert: @@ -120,7 +126,6 @@ resource: "{{ volume.volume_id }}" purge_tags: true tags: {} - <<: *aws_connection_info register: result - assert: @@ -133,7 +138,6 @@ ec2_vol: id: "{{ volume.volume_id }}" state: absent - <<: *aws_connection_info register: result until: result is not failed ignore_errors: yes