diff --git a/changelogs/fragments/523-ec2_vpc_igw-tagging.yml b/changelogs/fragments/523-ec2_vpc_igw-tagging.yml new file mode 100644 index 00000000000..7486cd26464 --- /dev/null +++ b/changelogs/fragments/523-ec2_vpc_igw-tagging.yml @@ -0,0 +1,2 @@ +minor_changes: + - ec2_vpc_igw - use module_util helper for tagging (https://github.com/ansible-collections/amazon.aws/pull/523). diff --git a/plugins/modules/ec2_vpc_igw.py b/plugins/modules/ec2_vpc_igw.py index b985ff5c767..47e3dc5a29c 100644 --- a/plugins/modules/ec2_vpc_igw.py +++ b/plugins/modules/ec2_vpc_igw.py @@ -103,22 +103,23 @@ except ImportError: pass # caught by AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.waiters import get_waiter -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_aws_tags +from ..module_utils.core import AnsibleAWSModule +from ..module_utils.waiters import get_waiter +from ..module_utils.ec2 import AWSRetry +from ..module_utils.ec2 import ansible_dict_to_boto3_filter_list +from ..module_utils.ec2 import boto3_tag_list_to_ansible_dict +from ..module_utils.ec2 import camel_dict_to_snake_dict +from ..module_utils.ec2 import ensure_ec2_tags -class AnsibleEc2Igw(object): +class AnsibleEc2Igw(): def __init__(self, module, results): self._module = module self._results = results - self._connection = self._module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) + self._connection = self._module.client( + 'ec2', retry_decorator=AWSRetry.jittered_backoff() + ) self._check_mode = self._module.check_mode def process(self): @@ -144,74 +145,19 @@ def get_matching_igw(self, vpc_id): igw = None if len(igws) > 1: self._module.fail_json( - msg='EC2 returned more than one Internet Gateway for VPC {0}, aborting'.format(vpc_id)) + msg='EC2 returned more than one Internet Gateway for VPC {0}, aborting' + .format(vpc_id)) elif igws: igw = camel_dict_to_snake_dict(igws[0]) return igw - def ensure_tags(self, igw_id, tags, purge_tags): - final_tags = [] - - filters = ansible_dict_to_boto3_filter_list({'resource-id': igw_id, 'resource-type': 'internet-gateway'}) - cur_tags = None - try: - cur_tags = self._connection.describe_tags(aws_retry=True, Filters=filters) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't describe tags") - - if tags is None: - return boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')) - - to_update, to_delete = compare_aws_tags(boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) - final_tags = boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')) - - if to_update: - try: - if self._check_mode: - final_tags.update(to_update) - else: - self._connection.create_tags( - aws_retry=True, - Resources=[igw_id], - Tags=ansible_dict_to_boto3_tag_list(to_update) - ) - - self._results['changed'] = True - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't create tags") - - if to_delete: - try: - if self._check_mode: - for key in to_delete: - del final_tags[key] - else: - tags_list = [] - for key in to_delete: - tags_list.append({'Key': key}) - - self._connection.delete_tags(aws_retry=True, Resources=[igw_id], Tags=tags_list) - - self._results['changed'] = True - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't delete tags") - - if not self._check_mode and (to_update or to_delete): - try: - response = self._connection.describe_tags(aws_retry=True, Filters=filters) - final_tags = boto3_tag_list_to_ansible_dict(response.get('Tags')) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't describe tags") - - return final_tags - @staticmethod - def get_igw_info(igw): + def get_igw_info(igw, vpc_id): return { 'gateway_id': igw['internet_gateway_id'], - 'tags': igw['tags'], - 'vpc_id': igw['vpc_id'] + 'tags': boto3_tag_list_to_ansible_dict(igw['tags']), + 'vpc_id': vpc_id } def ensure_igw_absent(self, vpc_id): @@ -225,8 +171,15 @@ def ensure_igw_absent(self, vpc_id): try: self._results['changed'] = True - self._connection.detach_internet_gateway(aws_retry=True, InternetGatewayId=igw['internet_gateway_id'], VpcId=vpc_id) - self._connection.delete_internet_gateway(aws_retry=True, InternetGatewayId=igw['internet_gateway_id']) + self._connection.detach_internet_gateway( + aws_retry=True, + InternetGatewayId=igw['internet_gateway_id'], + VpcId=vpc_id + ) + self._connection.delete_internet_gateway( + aws_retry=True, + InternetGatewayId=igw['internet_gateway_id'] + ) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg="Unable to delete Internet Gateway") @@ -249,18 +202,22 @@ def ensure_igw_present(self, vpc_id, tags, purge_tags): waiter.wait(InternetGatewayIds=[response['InternetGateway']['InternetGatewayId']]) igw = camel_dict_to_snake_dict(response['InternetGateway']) - self._connection.attach_internet_gateway(aws_retry=True, InternetGatewayId=igw['internet_gateway_id'], VpcId=vpc_id) + self._connection.attach_internet_gateway( + aws_retry=True, + InternetGatewayId=igw['internet_gateway_id'], + VpcId=vpc_id + ) self._results['changed'] = True except botocore.exceptions.WaiterError as e: self._module.fail_json_aws(e, msg="No Internet Gateway exists.") except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg='Unable to create Internet Gateway') - igw['vpc_id'] = vpc_id - - igw['tags'] = self.ensure_tags(igw_id=igw['internet_gateway_id'], tags=tags, purge_tags=purge_tags) - - igw_info = self.get_igw_info(igw) + self._results['changed'] |= ensure_ec2_tags( + self._connection, self._module, igw['internet_gateway_id'], + resource_type='internet-gateway', tags=tags, purge_tags=purge_tags + ) + igw_info = self.get_igw_info(self.get_matching_igw(vpc_id), vpc_id) self._results.update(igw_info) return self._results diff --git a/tests/integration/targets/ec2_vpc_igw/tasks/main.yml b/tests/integration/targets/ec2_vpc_igw/tasks/main.yml index ae49daefd52..daddd5a7edb 100644 --- a/tests/integration/targets/ec2_vpc_igw/tasks/main.yml +++ b/tests/integration/targets/ec2_vpc_igw/tasks/main.yml @@ -18,7 +18,7 @@ - '"internet_gateways" in igw_info' # ============================================================ - - name: create a VPC + - name: Create a VPC ec2_vpc_net: name: '{{ vpc_name }}' state: present @@ -45,6 +45,7 @@ filters: attachment.vpc-id: '{{ vpc_result.vpc.id }}' register: igw_info + - name: Assert success assert: that: @@ -53,7 +54,7 @@ - (igw_info.internet_gateways | length) == 0 # ============================================================ - - name: create internet gateway (expected changed=true) - CHECK_MODE + - name: Create internet gateway (expected changed=true) - CHECK_MODE ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' @@ -62,12 +63,13 @@ Tag Two: two {{ resource_prefix }} register: vpc_igw_create check_mode: yes - - name: assert creation would happen (expected changed=true) - CHECK_MODE + + - name: Assert creation would happen (expected changed=true) - CHECK_MODE assert: that: - vpc_igw_create is changed - - name: create internet gateway (expected changed=true) + - name: Create internet gateway (expected changed=true) ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' @@ -75,7 +77,8 @@ tag_one: '{{ resource_prefix }} One' Tag Two: two {{ resource_prefix }} register: vpc_igw_create - - name: assert creation happened (expected changed=true) + + - name: Assert creation happened (expected changed=true) assert: that: - vpc_igw_create is changed @@ -92,11 +95,13 @@ set_fact: igw_id: '{{ vpc_igw_create.gateway_id }}' vpc_id: '{{ vpc_result.vpc.id }}' + - name: Search for internet gateway by VPC ec2_vpc_igw_info: filters: attachment.vpc-id: '{{ vpc_id }}' register: igw_info + - name: Check standard IGW details assert: that: @@ -124,11 +129,13 @@ - current_igw.tags[1].value in [resource_prefix + " One", "two " + resource_prefix] vars: current_igw: '{{ igw_info.internet_gateways[0] }}' + - name: Fetch IGW by ID ec2_vpc_igw_info: internet_gateway_ids: '{{ igw_id }}' convert_tags: yes register: igw_info + - name: Check standard IGW details assert: that: @@ -150,11 +157,13 @@ - current_igw.tags["Tag Two"] == 'two {{ resource_prefix }}' vars: current_igw: '{{ igw_info.internet_gateways[0] }}' + - name: Fetch IGW by ID (list) ec2_vpc_igw_info: internet_gateway_ids: - '{{ igw_id }}' register: igw_info + - name: Check standard IGW details assert: that: @@ -171,13 +180,15 @@ - '"tags" in current_igw' vars: current_igw: '{{ igw_info.internet_gateways[0] }}' - - name: attempt to recreate internet gateway on VPC (expected changed=false) - CHECK_MODE + + - name: Attempt to recreate internet gateway on VPC (expected changed=false) - CHECK_MODE ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_recreate check_mode: yes - - name: assert recreation would do nothing (expected changed=false) - CHECK_MODE + + - name: Assert recreation would do nothing (expected changed=false) - CHECK_MODE assert: that: - vpc_igw_recreate is not changed @@ -188,12 +199,13 @@ - vpc_igw_create.tags["tag_one"] == '{{ resource_prefix }} One' - vpc_igw_create.tags["Tag Two"] == 'two {{ resource_prefix }}' - - name: attempt to recreate internet gateway on VPC (expected changed=false) + - name: Attempt to recreate internet gateway on VPC (expected changed=false) ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_recreate - - name: assert recreation did nothing (expected changed=false) + + - name: Assert recreation did nothing (expected changed=false) assert: that: - vpc_igw_recreate is not changed @@ -214,7 +226,8 @@ Tag Two: two {{ resource_prefix }} register: vpc_igw_recreate check_mode: yes - - name: assert tag update would do nothing (expected changed=false) - CHECK_MODE + + - name: Assert tag update would do nothing (expected changed=false) - CHECK_MODE assert: that: - vpc_igw_recreate is not changed @@ -233,7 +246,8 @@ tag_one: '{{ resource_prefix }} One' Tag Two: two {{ resource_prefix }} register: vpc_igw_recreate - - name: assert tag update did nothing (expected changed=false) + + - name: Assert tag update did nothing (expected changed=false) assert: that: - vpc_igw_recreate is not changed @@ -245,7 +259,7 @@ - vpc_igw_recreate.tags["Tag Two"] == 'two {{ resource_prefix }}' # ============================================================ - - name: Update the tags - remove and add - CHECK_MODE + - name: Update the tags (remove and add) - CHECK_MODE ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' @@ -254,7 +268,8 @@ Tag Two: two {{ resource_prefix }} register: vpc_igw_update check_mode: yes - - name: assert tag update would happen (expected changed=true) - CHECK_MODE + + - name: Assert tag update would happen (expected changed=true) - CHECK_MODE assert: that: - vpc_igw_update is changed @@ -262,11 +277,8 @@ - vpc_igw_update.vpc_id == vpc_id - '"tags" in vpc_igw_update' - vpc_igw_update.tags | length == 2 - - vpc_igw_update.tags["tag_three"] == '{{ resource_prefix }} Three' - - vpc_igw_update.tags["Tag Two"] == 'two {{ resource_prefix }}' - - - name: Update the tags - remove and add + - name: Update the tags (remove and add) ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' @@ -274,7 +286,8 @@ tag_three: '{{ resource_prefix }} Three' Tag Two: two {{ resource_prefix }} register: vpc_igw_update - - name: assert tags are updated (expected changed=true) + + - name: Assert tags are updated (expected changed=true) assert: that: - vpc_igw_update is changed @@ -295,17 +308,14 @@ tag_one: '{{ resource_prefix }} One' register: vpc_igw_update check_mode: yes - - name: assert tags would be added - CHECK_MODE + + - name: Assert tags would be added - CHECK_MODE assert: that: - vpc_igw_update is changed - vpc_igw_update.gateway_id == igw_id - vpc_igw_update.vpc_id == vpc_id - '"tags" in vpc_igw_update' - - vpc_igw_update.tags | length == 3 - - vpc_igw_update.tags["tag_one"] == '{{ resource_prefix }} One' - - vpc_igw_update.tags["tag_three"] == '{{ resource_prefix }} Three' - - vpc_igw_update.tags["Tag Two"] == 'two {{ resource_prefix }}' - name: Update the tags add without purge ec2_vpc_igw: @@ -315,7 +325,8 @@ tags: tag_one: '{{ resource_prefix }} One' register: vpc_igw_update - - name: assert tags added + + - name: Assert tags added assert: that: - vpc_igw_update is changed @@ -334,37 +345,32 @@ state: present vpc_id: '{{ vpc_result.vpc.id }}' tags: - lowercase spaced: "hello cruel world \u2764\uFE0F" - Title Case: "Hello Cruel World \u2764\uFE0F" - CamelCase: "SimpleCamelCase \u2764\uFE0F" - snake_case: "simple_snake_case \u2764\uFE0F" + lowercase spaced: "hello cruel world" + Title Case: "Hello Cruel World" + CamelCase: "SimpleCamelCase" + snake_case: "simple_snake_case" register: vpc_igw_update check_mode: yes - - name: assert tag update would happen (expected changed=true) - CHECK_MODE + + - name: Assert tag update would happen (expected changed=true) - CHECK_MODE assert: that: - vpc_igw_update is changed - vpc_igw_update.gateway_id == igw_id - vpc_igw_update.vpc_id == vpc_id - '"tags" in vpc_igw_update' - - vpc_igw_update.tags | length == 4 - - "vpc_igw_update.tags[\"lowercase spaced\"] == 'hello cruel world \u2764\uFE0F\ - '" - - "vpc_igw_update.tags[\"Title Case\"] == 'Hello Cruel World \u2764\uFE0F'" - - "vpc_igw_update.tags[\"CamelCase\"] == 'SimpleCamelCase \u2764\uFE0F'" - - "vpc_igw_update.tags[\"snake_case\"] == 'simple_snake_case \u2764\uFE0F'" - - name: Update the tags - remove and add ec2_vpc_igw: state: present vpc_id: '{{ vpc_result.vpc.id }}' tags: - lowercase spaced: "hello cruel world \u2764\uFE0F" - Title Case: "Hello Cruel World \u2764\uFE0F" - CamelCase: "SimpleCamelCase \u2764\uFE0F" - snake_case: "simple_snake_case \u2764\uFE0F" + lowercase spaced: "hello cruel world" + Title Case: "Hello Cruel World" + CamelCase: "SimpleCamelCase" + snake_case: "simple_snake_case" register: vpc_igw_update + - name: assert tags are updated (expected changed=true) assert: that: @@ -373,18 +379,18 @@ - vpc_igw_update.vpc_id == vpc_id - '"tags" in vpc_igw_update' - vpc_igw_update.tags | length == 4 - - "vpc_igw_update.tags[\"lowercase spaced\"] == 'hello cruel world \u2764\uFE0F\ - '" - - "vpc_igw_update.tags[\"Title Case\"] == 'Hello Cruel World \u2764\uFE0F'" - - "vpc_igw_update.tags[\"CamelCase\"] == 'SimpleCamelCase \u2764\uFE0F'" - - "vpc_igw_update.tags[\"snake_case\"] == 'simple_snake_case \u2764\uFE0F'" + - vpc_igw_update.tags["lowercase spaced"] == 'hello cruel world' + - vpc_igw_update.tags["Title Case"] == 'Hello Cruel World' + - vpc_igw_update.tags["CamelCase"] == 'SimpleCamelCase' + - vpc_igw_update.tags["snake_case"] == 'simple_snake_case' # ============================================================ - name: Gather information about a filtered list of Internet Gateways using tags ec2_vpc_igw_info: filters: - tag:Title Case: "Hello Cruel World \u2764\uFE0F" + tag:Title Case: "Hello Cruel World" register: igw_info + - name: Assert success assert: that: @@ -393,13 +399,13 @@ - igw_info.internet_gateways | selectattr("internet_gateway_id",'equalto',"{{ igw_id }}") - - name: Gather information about a filtered list of Internet Gateways using tags - - CHECK_MODE + - name: Gather information about a filtered list of Internet Gateways using tags - CHECK_MODE ec2_vpc_igw_info: filters: - tag:Title Case: "Hello Cruel World \u2764\uFE0F" + tag:Title Case: "Hello Cruel World" register: igw_info check_mode: yes + - name: Assert success - CHECK_MODE assert: that: @@ -409,12 +415,12 @@ igw_id }}") # ============================================================ - - name: Gather information about a filtered list of Internet Gateways using tags - (no match) + - name: Gather information about a filtered list of Internet Gateways using tags (no match) ec2_vpc_igw_info: filters: tag:tag_one: '{{ resource_prefix }} One' register: igw_info + - name: Assert success assert: that: @@ -422,13 +428,13 @@ - '"internet_gateways" in igw_info' - igw_info.internet_gateways | length == 0 - - name: Gather information about a filtered list of Internet Gateways using tags - (no match) - CHECK_MODE + - name: Gather information about a filtered list of Internet Gateways using tags (no match) - CHECK_MODE ec2_vpc_igw_info: filters: tag:tag_one: '{{ resource_prefix }} One' register: igw_info check_mode: yes + - name: Assert success - CHECK_MODE assert: that: @@ -444,7 +450,8 @@ tags: {} register: vpc_igw_update check_mode: yes - - name: assert tags would be removed - CHECK_MODE + + - name: Assert tags would be removed - CHECK_MODE assert: that: - vpc_igw_update is changed @@ -455,7 +462,8 @@ vpc_id: '{{ vpc_result.vpc.id }}' tags: {} register: vpc_igw_update - - name: assert tags removed + + - name: Assert tags removed assert: that: - vpc_igw_update is changed @@ -465,23 +473,25 @@ - vpc_igw_update.tags | length == 0 # ============================================================ - - name: test state=absent (expected changed=true) - CHECK_MODE + - name: Test state=absent (expected changed=true) - CHECK_MODE ec2_vpc_igw: state: absent vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_delete check_mode: yes - - name: assert state=absent (expected changed=true) - CHECK_MODE + + - name: Assert state=absent (expected changed=true) - CHECK_MODE assert: that: - vpc_igw_delete is changed - - name: test state=absent (expected changed=true) + - name: Test state=absent (expected changed=true) ec2_vpc_igw: state: absent vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_delete - - name: assert state=absent (expected changed=true) + + - name: Assert state=absent (expected changed=true) assert: that: - vpc_igw_delete is changed @@ -493,6 +503,7 @@ - '{{ igw_id }}' register: igw_info ignore_errors: true + - name: Check IGW does not exist assert: that: @@ -500,35 +511,38 @@ - igw_info is failed # ============================================================ - - name: test state=absent when already deleted (expected changed=false) - CHECK_MODE + - name: Test state=absent when already deleted (expected changed=false) - CHECK_MODE ec2_vpc_igw: state: absent vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_delete check_mode: yes - - name: assert state=absent (expected changed=false) - CHECK_MODE + + - name: Assert state=absent (expected changed=false) - CHECK_MODE assert: that: - vpc_igw_delete is not changed - - name: test state=absent when already deleted (expected changed=false) + - name: Test state=absent when already deleted (expected changed=false) ec2_vpc_igw: state: absent vpc_id: '{{ vpc_result.vpc.id }}' register: vpc_igw_delete - - name: assert state=absent (expected changed=false) + + - name: Assert state=absent (expected changed=false) assert: that: - vpc_igw_delete is not changed always: # ============================================================ - - name: tidy up IGW + - name: Tidy up IGW ec2_vpc_igw: state: absent vpc_id: '{{ vpc_result.vpc.id }}' ignore_errors: true - - name: tidy up VPC + + - name: Tidy up VPC ec2_vpc_net: name: '{{ vpc_name }}' state: absent