From 7ef4a6ccfdcd001f75413d82397b537595fdcf0e Mon Sep 17 00:00:00 2001 From: Marco Braga Date: Thu, 30 Mar 2023 10:05:34 -0300 Subject: [PATCH] feat(module/vpc-cagw): Add Carrier Gateway modules (#1353) feat(module/vpc-cagw): Add Carrier Gateway modules SUMMARY New modules to manage VPC Carrear Gateways. ISSUE TYPE New Module Pull Request COMPONENT NAME modules (new): ec2_carrier_gateway ec2_carrier_gateway_info ADDITIONAL INFORMATION $ ansible localhost -m ec2_vpc_cagw_info localhost | SUCCESS => { "carrier_gateways": [ { "carrier_gateway_id": "cagw-037df45cae5362d59", "tags": { "Name": "test1-54dsl-vpc-cagw" }, "vpc_id": "vpc-069cabb60c7e7fc6d" } ], "changed": false } $ ansible localhost -m ec2_carrier_gateway -a "state=absent vpc_id=vpc-069cabb60c7e7fc6d carrier_gateway_id=cagw-037df45cae5362d59" localhost | CHANGED => { "changed": true } $ ansible localhost -m ec2_carrier_gateway_info localhost | SUCCESS => { "carrier_gateways": [], "changed": false } $ ansible localhost -m ec2_carrier_gateway-a "vpc_id=vpc-069cabb60c7e7fc6d" localhost | CHANGED => { "carrier_gateway_id": "cagw-095f998ebdcb5ef86", "changed": true, "tags": {}, "vpc_id": "vpc-069cabb60c7e7fc6d" } $ ansible localhost -m ec2_carrier_gateway_info localhost | SUCCESS => { "carrier_gateways": [ { "carrier_gateway_id": "cagw-095f998ebdcb5ef86", "tags": {}, "vpc_id": "vpc-069cabb60c7e7fc6d" } ], "changed": false } Reviewed-by: Mark Chappell Reviewed-by: Marco Braga Reviewed-by: Markus Bergholz --- plugins/modules/ec2_carrier_gateway.py | 261 ++++++++++++++++++ plugins/modules/ec2_carrier_gateway_info.py | 159 +++++++++++ .../targets/ec2_carrier_gateway/aliases | 9 + .../ec2_carrier_gateway/defaults/main.yml | 3 + .../targets/ec2_carrier_gateway/meta/main.yml | 1 + .../ec2_carrier_gateway/tasks/main.yml | 167 +++++++++++ .../ec2_carrier_gateway/tasks/tags.yml | 224 +++++++++++++++ 7 files changed, 824 insertions(+) create mode 100644 plugins/modules/ec2_carrier_gateway.py create mode 100644 plugins/modules/ec2_carrier_gateway_info.py create mode 100644 tests/integration/targets/ec2_carrier_gateway/aliases create mode 100644 tests/integration/targets/ec2_carrier_gateway/defaults/main.yml create mode 100644 tests/integration/targets/ec2_carrier_gateway/meta/main.yml create mode 100644 tests/integration/targets/ec2_carrier_gateway/tasks/main.yml create mode 100644 tests/integration/targets/ec2_carrier_gateway/tasks/tags.yml diff --git a/plugins/modules/ec2_carrier_gateway.py b/plugins/modules/ec2_carrier_gateway.py new file mode 100644 index 00000000000..3458170e393 --- /dev/null +++ b/plugins/modules/ec2_carrier_gateway.py @@ -0,0 +1,261 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: ec2_carrier_gateway +version_added: 6.0.0 +short_description: Manage an AWS VPC Carrier gateway +description: + - Manage an AWS VPC Carrier gateway. +author: + - "Marco Braga (@mtulio)" +options: + vpc_id: + description: + - The VPC ID for the VPC in which to manage the Carrier Gateway. + required: true + type: str + carrier_gateway_id: + description: + - The Carrier Gateway ID to manage the Carrier Gateway. + required: false + type: str + state: + description: + - Create or terminate the Carrier Gateway. + default: present + choices: [ 'present', 'absent' ] + type: str +extends_documentation_fragment: + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.tags + - amazon.aws.boto3 +""" + +EXAMPLES = r""" +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# Ensure that the VPC has an Carrier Gateway. +# The Carrier Gateway ID can be accessed via {{cagw.carrier_gateway_id}} for use in setting up Route tables etc. +- name: Create Carrier gateway + community.aws.ec2_carrier_gateway: + vpc_id: vpc-abcdefgh + state: present + register: cagw + +- name: Create Carrier gateway with tags + community.aws.ec2_carrier_gateway: + vpc_id: vpc-abcdefgh + state: present + tags: + Tag1: tag1 + Tag2: tag2 + register: cagw + +- name: Delete Carrier gateway + community.aws.ec2_carrier_gateway: + vpc_id: vpc-abcdefgh + carrier_gateway_id: "cagw-123" + state: absent + register: vpc_cagw_delete +""" + +RETURN = r""" +changed: + description: If any changes have been made to the Carrier Gateway. + type: bool + returned: always + sample: + changed: false +carrier_gateway_id: + description: The unique identifier for the Carrier Gateway. + type: str + returned: I(state=present) + sample: + carrier_gateway_id: "cagw-XXXXXXXX" +tags: + description: The tags associated the Carrier Gateway. + type: dict + returned: I(state=present) + sample: + tags: + "Ansible": "Test" +vpc_id: + description: The VPC ID associated with the Carrier Gateway. + type: str + returned: I(state=present) + sample: + vpc_id: "vpc-XXXXXXXX" +""" + +try: + import botocore +except ImportError: + pass # caught by AnsibleAWSModule + +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_message +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ensure_ec2_tags +from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict +from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list + +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule + + +@AWSRetry.jittered_backoff(retries=10, delay=10) +def describe_cagws_with_backoff(connection, **params): + paginator = connection.get_paginator("describe_carrier_gateways") + return paginator.paginate(**params).build_full_result()["CarrierGateways"] + + +class AnsibleEc2Cagw: + def __init__(self, module, results): + self._module = module + self._results = results + self._connection = self._module.client("ec2", retry_decorator=AWSRetry.jittered_backoff()) + self._check_mode = self._module.check_mode + + def process(self): + vpc_id = self._module.params.get("vpc_id") + state = self._module.params.get("state", "present") + tags = self._module.params.get("tags") + purge_tags = self._module.params.get("purge_tags") + + if state == "present": + self.ensure_cagw_present(vpc_id, tags, purge_tags) + elif state == "absent": + self.ensure_cagw_absent(vpc_id) + + def get_matching_cagw(self, vpc_id, carrier_gateway_id=None): + """ + Returns the carrier gateway found. + Parameters: + vpc_id (str): VPC ID + carrier_gateway_id (str): Carrier Gateway ID, if specified + Returns: + cagw (dict): dict of cagw found, None if none found + """ + filters = ansible_dict_to_boto3_filter_list({"vpc-id": vpc_id}) + try: + if not carrier_gateway_id: + cagws = describe_cagws_with_backoff( + self._connection, + Filters=filters, + ) + else: + cagws = describe_cagws_with_backoff( + self._connection, + CarrierGatewayIds=[carrier_gateway_id], + ) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + self._module.fail_json_aws(e) + + cagw = None + if len(cagws) > 1: + self._module.fail_json( + msg=f"EC2 returned more than one Carrier Gateway for VPC {vpc_id}, aborting" + ) + elif cagws: + cagw = camel_dict_to_snake_dict(cagws[0]) + + return cagw + + @staticmethod + def get_cagw_info(cagw, vpc_id): + return { + "carrier_gateway_id": cagw["carrier_gateway_id"], + "tags": boto3_tag_list_to_ansible_dict(cagw["tags"]), + "vpc_id": vpc_id, + } + + def ensure_cagw_absent(self, vpc_id): + cagw = self.get_matching_cagw(vpc_id) + if cagw is None: + return self._results + + if self._check_mode: + self._results["changed"] = True + return self._results + + try: + self._results["changed"] = True + self._connection.delete_carrier_gateway( + aws_retry=True, + CarrierGatewayId=cagw["carrier_gateway_id"], + ) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + self._module.fail_json_aws(e, msg="Unable to delete Carrier Gateway") + + return self._results + + def ensure_cagw_present(self, vpc_id, tags, purge_tags): + cagw = self.get_matching_cagw(vpc_id) + + if cagw is None: + if self._check_mode: + self._results["changed"] = True + self._results["carrier_gateway_id"] = None + return self._results + + try: + response = self._connection.create_carrier_gateway(VpcId=vpc_id, aws_retry=True) + cagw = camel_dict_to_snake_dict(response["CarrierGateway"]) + self._results["changed"] = True + except is_boto3_error_message("You must be opted into a wavelength zone to create a carrier gateway.") as e: + self._module.fail_json(msg="You must be opted into a wavelength zone to create a carrier gateway") + except botocore.exceptions.WaiterError as e: + self._module.fail_json_aws(e, msg="No Carrier Gateway exists.") + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + self._module.fail_json_aws(e, msg="Unable to create Carrier Gateway") + + # Modify tags + self._results["changed"] |= ensure_ec2_tags( + self._connection, + self._module, + cagw["carrier_gateway_id"], + resource_type="carrier-gateway", + tags=tags, + purge_tags=purge_tags, + retry_codes="InvalidCarrierGatewayID.NotFound", + ) + + # Update cagw + cagw = self.get_matching_cagw(vpc_id, carrier_gateway_id=cagw["carrier_gateway_id"]) + cagw_info = self.get_cagw_info(cagw, vpc_id) + self._results.update(cagw_info) + + return self._results + + +def main(): + argument_spec = dict( + carrier_gateway_id=dict(required=False), + vpc_id=dict(required=True), + state=dict(default="present", choices=["present", "absent"]), + tags=dict(required=False, type="dict", aliases=["resource_tags"]), + purge_tags=dict(default=True, type="bool"), + ) + + module = AnsibleAWSModule( + argument_spec=argument_spec, + required_one_of=[["vpc_id", "carrier_gateway_id"]], + supports_check_mode=True, + ) + results = dict( + changed=False, + ) + cagw_manager = AnsibleEc2Cagw(module=module, results=results) + cagw_manager.process() + + module.exit_json(**results) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/ec2_carrier_gateway_info.py b/plugins/modules/ec2_carrier_gateway_info.py new file mode 100644 index 00000000000..43d77d59aa6 --- /dev/null +++ b/plugins/modules/ec2_carrier_gateway_info.py @@ -0,0 +1,159 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: ec2_carrier_gateway_info +version_added: 6.0.0 +short_description: Gather information about carrier gateways in AWS +description: + - Gather information about carrier gateways in AWS. +author: + - "Marco Braga (@mtulio)" +options: + filters: + description: + - A dict of filters to apply. Each dict item consists of a filter key and a filter value. + See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeCarrierGateways.html) for possible filters. + required: false + default: {} + type: dict + carrier_gateway_ids: + description: + - Get details of specific Carrier Gateway ID. + required: false + type: list + elements: str +extends_documentation_fragment: + - amazon.aws.common.modules + - amazon.aws.region.modules + - amazon.aws.boto3 +""" + +EXAMPLES = r""" +# # Note: These examples do not set authentication details, see the AWS Guide for details. + +- name: Gather information about all Carrier Gateways for an account or profile + community.aws.ec2_carrier_gateway_info: + region: ap-southeast-2 + register: cagw_info + +- name: Gather information about a filtered list of Carrier Gateways + community.aws.ec2_carrier_gateway_info: + region: ap-southeast-2 + filters: + "tag:Name": "cagw-123" + register: cagw_info + +- name: Gather information about a specific carrier gateway by CarrierGatewayId + community.aws.ec2_carrier_gateway_info: + region: ap-southeast-2 + carrier_gateway_ids: cagw-c1231234 + register: cagw_info +""" + +RETURN = r""" +changed: + description: True if listing the carrier gateways succeeds. + type: bool + returned: always + sample: "false" +carrier_gateways: + description: The carrier gateways for the account. + returned: always + type: complex + contains: + vpc_id: + description: The ID of the VPC. + returned: I(state=present) + type: str + sample: vpc-02123b67 + carrier_gateway_id: + description: The ID of the carrier gateway. + returned: I(state=present) + type: str + sample: cagw-2123634d + tags: + description: Any tags assigned to the carrier gateway. + returned: I(state=present) + type: dict + sample: + tags: + "Ansible": "Test" +""" + +try: + import botocore +except ImportError: + pass # Handled by AnsibleAWSModule + +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code +from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict +from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list + +from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule + + +def get_carrier_gateway_info(carrier_gateway): + tags = boto3_tag_list_to_ansible_dict(carrier_gateway["Tags"]) + ignore_list = [] + carrier_gateway_info = { + "CarrierGatewayId": carrier_gateway["CarrierGatewayId"], + "VpcId": carrier_gateway["VpcId"], + "Tags": tags, + } + + carrier_gateway_info = camel_dict_to_snake_dict(carrier_gateway_info, ignore_list=ignore_list) + return carrier_gateway_info + + +def list_carrier_gateways(connection, module): + params = dict() + + params["Filters"] = ansible_dict_to_boto3_filter_list(module.params.get("filters")) + if module.params.get("carrier_gateway_ids"): + params["CarrierGatewayIds"] = module.params.get("carrier_gateway_ids") + + try: + all_carrier_gateways = connection.describe_carrier_gateways(aws_retry=True, **params) + except is_boto3_error_code("InvalidCarrierGatewayID.NotFound"): + module.fail_json("CarrierGateway not found") + except ( + botocore.exceptions.ClientError, + botocore.exceptions.BotoCoreError, + ) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, "Unable to describe carrier gateways") + + return [get_carrier_gateway_info(cagw) for cagw in all_carrier_gateways["CarrierGateways"]] + + +def main(): + argument_spec = dict( + carrier_gateway_ids=dict(default=None, elements="str", type="list"), + filters=dict(default={}, type="dict"), + ) + + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + # Validate Requirements + try: + connection = module.client("ec2", retry_decorator=AWSRetry.jittered_backoff()) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Failed to connect to AWS") + + results = list_carrier_gateways(connection, module) + + module.exit_json(carrier_gateways=results) + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/ec2_carrier_gateway/aliases b/tests/integration/targets/ec2_carrier_gateway/aliases new file mode 100644 index 00000000000..913237649c9 --- /dev/null +++ b/tests/integration/targets/ec2_carrier_gateway/aliases @@ -0,0 +1,9 @@ +# reason: missing-policy +# To test Carrier Gateway in the VPC, the Wavelength subnet +# group should be enabled on the AWS Account. +unsupported + +cloud/aws + +ec2_carrier_gateway +ec2_carrier_gateway_info diff --git a/tests/integration/targets/ec2_carrier_gateway/defaults/main.yml b/tests/integration/targets/ec2_carrier_gateway/defaults/main.yml new file mode 100644 index 00000000000..2e8c38f8847 --- /dev/null +++ b/tests/integration/targets/ec2_carrier_gateway/defaults/main.yml @@ -0,0 +1,3 @@ +--- +vpc_name: '{{ resource_prefix }}-ec2-vpc-cagw' +cagw_name: '{{ resource_prefix }}-ec2-vpc-cagw' diff --git a/tests/integration/targets/ec2_carrier_gateway/meta/main.yml b/tests/integration/targets/ec2_carrier_gateway/meta/main.yml new file mode 100644 index 00000000000..32cf5dda7ed --- /dev/null +++ b/tests/integration/targets/ec2_carrier_gateway/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] diff --git a/tests/integration/targets/ec2_carrier_gateway/tasks/main.yml b/tests/integration/targets/ec2_carrier_gateway/tasks/main.yml new file mode 100644 index 00000000000..1ec10c5c18c --- /dev/null +++ b/tests/integration/targets/ec2_carrier_gateway/tasks/main.yml @@ -0,0 +1,167 @@ +--- +- name: 'ec2_carrier_gateway integration tests' + collections: + - community.aws + module_defaults: + group/aws: + aws_access_key: '{{ aws_access_key }}' + aws_secret_key: '{{ aws_secret_key }}' + security_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region }}' + block: + + # ============================================================ + - debug: msg="Setting up test dependencies" + + - name: create a VPC + ec2_vpc_net: + name: "{{ vpc_name }}-{{ item }}" + state: present + cidr_block: "{{ vpc_cidr }}" + tags: + Description: "Created by ansible-test for CAGW tests" + register: vpc_result + loop: [1] + + - name: use set fact for vpc ids + set_fact: + vpc_id_1: '{{ vpc_result.results.0.vpc.id }}' + + # ============================================================ + - debug: msg="Running tests" + + - name: create carrier gateway and attach it to vpc + ec2_carrier_gateway: + state: present + vpc_id: '{{ vpc_id_1 }}' + name: "{{ cagw_name }}" + register: cagw + check_mode: true + + - name: use set fact for cagw ids + set_fact: + cagw_id: '{{ cagw.carrier_gateway_id }}' + + - assert: + that: + - cagw.changed + - cagw.vpc_id == vpc_id_1 + - cagw.tags.Name == cagw_name + + - name: test idempotence + ec2_carrier_gateway: + state: present + vpc_id: '{{ vpc_id_1 }}' + name: "{{ cagw_name }}" + register: cagw + check_mode: true + + - assert: + that: + - not cagw.changed + - cagw.carrier_gateway_id == cagw_id + + # ============================================================ + + - name: get VPC CAGW facts by ID (CHECK) + ec2_carrier_gateway_info: + carrier_gateway_id: ['{{ cagw_id }}'] + register: cagw_info + check_mode: True + + - name: verify expected facts + vars: + cagw_details: '{{ cagw_info.carrier_gateways[0] }}' + assert: + that: + - cagw_info.carrier_gateways | length == 1 + - '"carrier_gateway_id" in cagw_details' + - '"tags" in cagw_details' + - '"vpc_id" in cagw_details' + - cagw_details.carrier_gateway_id == cagw_id + - '"Name" in cagw_details.tags' + - cagw_details.tags.Name == cagw_name + + - name: get VPC CAGW facts by Tag + ec2_carrier_gateway_info: + filters: + "tag:Name": "{{ cagw_name }}" + register: cagw_info + + - name: verify expected facts + vars: + cagw_details: '{{ cagw_info.virtual_gateways[0] }}' + assert: + that: + - cagw_info.virtual_gateways | length == 1 + - '"carrier_gateway_id" in cagw_details' + - '"state" in cagw_details' + - '"tags" in cagw_details' + - cagw_details.carrier_gateway_id == cagw_id + - '"Name" in cagw_details.tags' + - cagw_details.tags.Name == cagw_name + + + # ============================================================ + + - name: get all CAGWs + ec2_carrier_gateway_info: + register: cagw_info + + - name: verify test CAGW is in the results + vars: + cagw_id_list: '{{ cagw_info.carrier_gateways | map(attribute="carrier_gateway_id") | list }}' + assert: + that: + - cagw_id in cagw_id_list + + # ============================================================ + + - include_tasks: 'tags.yml' + + # ============================================================ + + - name: delete carrier gateway + ec2_carrier_gateway: + state: absent + name: "{{ cagw_name }}" + register: cagw + check_mode: true + + - assert: + that: + - cagw.changed + + - name: test idempotence + ec2_carrier_gateway: + state: absent + name: "{{ cagw_name }}" + register: cagw + check_mode: true + + - assert: + that: + - not cagw.changed + + always: + + - debug: msg="Removing test dependencies" + + - name: delete carrier gateway + ec2_carrier_gateway: + state: absent + carrier_gateway_id: '{{ cagw.carrier_gateway_id }}' + ignore_errors: true + check_mode: true + + - name: delete vpc + ec2_vpc_net: + name: "{{ vpc_name }}-{{ item }}" + state: absent + cidr_block: "{{ vpc_cidr }}" + loop: [1, 2] + register: result + retries: 10 + delay: 5 + until: result is not failed + ignore_errors: true diff --git a/tests/integration/targets/ec2_carrier_gateway/tasks/tags.yml b/tests/integration/targets/ec2_carrier_gateway/tasks/tags.yml new file mode 100644 index 00000000000..07104daa712 --- /dev/null +++ b/tests/integration/targets/ec2_carrier_gateway/tasks/tags.yml @@ -0,0 +1,224 @@ +- vars: + first_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + second_tags: + 'New Key with Spaces': Value with spaces + NewCamelCaseKey: CamelCaseValue + newPascalCaseKey: pascalCaseValue + new_snake_case_key: snake_case_value + third_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + 'New Key with Spaces': Updated Value with spaces + final_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + 'New Key with Spaces': Updated Value with spaces + NewCamelCaseKey: CamelCaseValue + newPascalCaseKey: pascalCaseValue + new_snake_case_key: snake_case_value + name_tags: + Name: '{{ cagw_name }}' + module_defaults: + ec2_carrier_gateway: + name: '{{ cagw_name }}' + ec2_carrier_gateway_info: + vpn_gateway_ids: ['{{ cagw_id }}'] + block: + + # ============================================================ + + - name: add tags + ec2_carrier_gateway: + tags: '{{ first_tags }}' + state: 'present' + register: tag_cagw + check_mode: true + + - name: get VPC CAGW facts + ec2_carrier_gateway_info: {} + register: tag_cagw_info + + - name: verify the tags were added + assert: + that: + - tag_cagw is changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( first_tags | combine(name_tags) ) + + - name: add tags - IDEMPOTENCY + ec2_carrier_gateway: + tags: '{{ first_tags }}' + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: {} + register: tag_carrier_gateway_info + + - name: verify no change + assert: + that: + - tag_cagw is not changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( first_tags | combine(name_tags) ) + + # ============================================================ + + - name: get VPC CAGW facts by filter + ec2_carrier_gateway_info: + filters: + 'tag:Name': '{{ cagw_name }}' + vpn_gateway_ids: '{{ omit }}' + register: tag_cagw_info + + - name: assert the facts are the same as before + assert: + that: + - tag_cagw_info.carrier_gateways | length == 1 + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + + # ============================================================ + + - name: modify tags with purge + ec2_carrier_gateway: + tags: '{{ second_tags }}' + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify the tags were added + assert: + that: + - tag_cagw is changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( second_tags | combine(name_tags) ) + + - name: modify tags with purge - IDEMPOTENCY + ec2_carrier_gateway: + tags: '{{ second_tags }}' + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify no change + assert: + that: + - tag_cagw is not changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( second_tags | combine(name_tags) ) + + # ============================================================ + + - name: modify tags without purge + ec2_carrier_gateway: + tags: '{{ third_tags }}' + state: 'present' + purge_tags: False + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify the tags were added + assert: + that: + - tag_cagw is changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( final_tags | combine(name_tags) ) + + - name: modify tags without purge - IDEMPOTENCY + ec2_carrier_gateway: + tags: '{{ third_tags }}' + state: 'present' + purge_tags: False + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify no change + assert: + that: + - tag_cagw is not changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( final_tags | combine(name_tags) ) + + # ============================================================ + + - name: No change to tags without setting tags + ec2_carrier_gateway: + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify the tags were added + assert: + that: + - tag_cagw is not changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == ( final_tags | combine(name_tags) ) + + # ============================================================ + + - name: remove non name tags + ec2_carrier_gateway: + tags: {} + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify the tags were added + assert: + that: + - tag_cagw is changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == name_tags + + - name: remove non name tags - IDEMPOTENCY + ec2_carrier_gateway: + tags: {} + state: 'present' + register: tag_cagw + check_mode: true + - name: get VPC CAGW facts + ec2_carrier_gateway_info: + register: tag_cagw_info + + - name: verify no change + assert: + that: + - tag_cagw is not changed + - tag_cagw.carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].carrier_gateway_id == cagw_id + - tag_cagw_info.carrier_gateways[0].tags == name_tags