From d1f5339d18c4b1006104c82f6049e6352f55bd4f Mon Sep 17 00:00:00 2001 From: Joseph Torcasso <87090265+jatorcasso@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:32:51 -0400 Subject: [PATCH] ec2_vpc_route_table - support associating internet gateways (#690) ec2_vpc_route_table - support associating internet gateways Depends-On: ansible/ansible-zuul-jobs#1362 Depends-On: ansible/ansible-zuul-jobs#1364 SUMMARY Update ec2_vpc_route_table to support associating internet gateways per feature request #476 Add integration tests Fix idempotency issue when associating a subnet with a route table ISSUE TYPE Feature Pull Request COMPONENT NAME ec2_vpc_route_table Reviewed-by: Mandar Kulkarni Reviewed-by: Joseph Torcasso Reviewed-by: Abhijeet Kasurde Reviewed-by: Alina Buzachis Reviewed-by: None Reviewed-by: Mike Graves Reviewed-by: Mark Chappell Reviewed-by: Mark Woolley (cherry picked from commit d9d5d0d71ec4280602694c3b5f1510087cc63876) --- .../690-ec2_vpc_route_table-associate-igw.yml | 2 + plugins/modules/ec2_vpc_route_table.py | 261 ++++-- plugins/modules/ec2_vpc_route_table_info.py | 44 +- .../ec2_vpc_route_table/defaults/main.yml | 1 + .../ec2_vpc_route_table/tasks/main.yml | 834 ++++++++++++++++-- 5 files changed, 981 insertions(+), 161 deletions(-) create mode 100644 changelogs/fragments/690-ec2_vpc_route_table-associate-igw.yml diff --git a/changelogs/fragments/690-ec2_vpc_route_table-associate-igw.yml b/changelogs/fragments/690-ec2_vpc_route_table-associate-igw.yml new file mode 100644 index 00000000000..cade07afa56 --- /dev/null +++ b/changelogs/fragments/690-ec2_vpc_route_table-associate-igw.yml @@ -0,0 +1,2 @@ +minor_changes: + - ec2_vpc_route_table - support associating internet gateways (https://github.com/ansible-collections/amazon.aws/pull/690). \ No newline at end of file diff --git a/plugins/modules/ec2_vpc_route_table.py b/plugins/modules/ec2_vpc_route_table.py index 81fb40ce6a1..0e4664ddb71 100644 --- a/plugins/modules/ec2_vpc_route_table.py +++ b/plugins/modules/ec2_vpc_route_table.py @@ -18,6 +18,12 @@ - Rob White (@wimnat) - Will Thames (@willthames) options: + gateway_id: + description: + - The ID of the gateway to associate with the route table. + - If I(gateway_id) is C('None') or C(''), gateway will be disassociated with the route table. + type: str + version_added: 3.2.0 lookup: description: Look up route table by either tags or by route table ID. Non-unique tag lookup will fail. If no tags are specified then no lookup for an existing route table is performed and a new @@ -32,15 +38,15 @@ purge_routes: description: Purge existing routes that are not found in routes. type: bool - default: 'yes' + default: True purge_subnets: description: Purge existing subnets that are not found in subnets. Ignored unless the subnets option is supplied. - default: 'true' + default: True type: bool purge_tags: description: Purge existing tags that are not found in route table. type: bool - default: 'no' + default: False route_table_id: description: - The ID of the route table to update or delete. @@ -105,6 +111,27 @@ gateway_id: "{{ igw.gateway_id }}" register: public_route_table +- name: Create vpc gateway + amazon.aws.ec2_vpc_igw: + vpc_id: vpc-1245678 + register: vpc_igw + +- name: Create gateway route table + amazon.aws.ec2_vpc_route_table: + vpc_id: vpc-1245678 + tags: + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + register: gateway_route_table + +- name: Disassociate gateway from route table + amazon.aws.ec2_vpc_route_table: + vpc_id: vpc-1245678 + tags: + Name: Gateway route table + gateway_id: None + register: gateway_route_table + - name: Set up NAT-protected route table amazon.aws.ec2_vpc_route_table: vpc_id: vpc-1245678 @@ -131,52 +158,72 @@ RETURN = r''' route_table: - description: Route Table result + description: Route Table result. returned: always type: complex contains: associations: - description: List of subnets associated with the route table + description: List of associations between the route table and one or more subnets or a gateway. returned: always type: complex contains: + association_state: + description: The state of the association. + returned: always + type: complex + contains: + state: + description: The state of the association. + returned: always + type: str + sample: associated + state_message: + description: Additional information about the state of the association. + returned: when available + type: str + sample: 'Creating association' + gateway_id: + description: ID of the internet gateway or virtual private gateway. + returned: when route table is a gateway route table + type: str + sample: igw-03312309 main: - description: Whether this is the main route table + description: Whether this is the main route table. returned: always type: bool sample: false route_table_association_id: - description: ID of association between route table and subnet + description: ID of association between route table and subnet. returned: always type: str sample: rtbassoc-ab47cfc3 route_table_id: - description: ID of the route table + description: ID of the route table. returned: always type: str sample: rtb-bf779ed7 subnet_id: - description: ID of the subnet - returned: always + description: ID of the subnet. + returned: when route table is a subnet route table type: str sample: subnet-82055af9 id: - description: ID of the route table (same as route_table_id for backwards compatibility) + description: ID of the route table (same as route_table_id for backwards compatibility). returned: always type: str sample: rtb-bf779ed7 propagating_vgws: - description: List of Virtual Private Gateways propagating routes + description: List of Virtual Private Gateways propagating routes. returned: always type: list sample: [] route_table_id: - description: ID of the route table + description: ID of the route table. returned: always type: str sample: rtb-bf779ed7 routes: - description: List of routes in the route table + description: List of routes in the route table. returned: always type: complex contains: @@ -191,44 +238,44 @@ type: str sample: 2600:1f1c:1b3:8f00:8000::/65 gateway_id: - description: ID of the gateway + description: ID of the gateway. returned: when gateway is local or internet gateway type: str sample: local instance_id: - description: ID of a NAT instance + description: ID of a NAT instance. returned: when the route is via an EC2 instance type: str sample: i-abcd123456789 instance_owner_id: - description: AWS account owning the NAT instance + description: AWS account owning the NAT instance. returned: when the route is via an EC2 instance type: str sample: 123456789012 nat_gateway_id: - description: ID of the NAT gateway + description: ID of the NAT gateway. returned: when the route is via a NAT gateway type: str sample: local origin: - description: mechanism through which the route is in the table + description: mechanism through which the route is in the table. returned: always type: str sample: CreateRouteTable state: - description: state of the route + description: state of the route. returned: always type: str sample: active tags: - description: Tags applied to the route table + description: Tags applied to the route table. returned: always type: dict sample: Name: Public route table Public: 'true' vpc_id: - description: ID for the VPC in which the route lives + description: ID for the VPC in which the route lives. returned: always type: str sample: vpc-6e2d2407 @@ -395,7 +442,11 @@ def route_spec_matches_route(route_spec, route): def route_spec_matches_route_cidr(route_spec, route): - return route_spec['DestinationCidrBlock'] == route.get('DestinationCidrBlock') + if route_spec.get('DestinationCidrBlock') and route.get('DestinationCidrBlock'): + return route_spec.get('DestinationCidrBlock') == route.get('DestinationCidrBlock') + if route_spec.get('DestinationIpv6CidrBlock') and route.get('DestinationIpv6CidrBlock'): + return route_spec.get('DestinationIpv6CidrBlock') == route.get('DestinationIpv6CidrBlock') + return False def rename_key(d, old_key, new_key): @@ -406,13 +457,12 @@ def index_of_matching_route(route_spec, routes_to_match): for i, route in enumerate(routes_to_match): if route_spec_matches_route(route_spec, route): return "exact", i - elif 'Origin' in route_spec and route_spec['Origin'] != 'EnableVgwRoutePropagation': + elif 'Origin' in route and route['Origin'] != 'EnableVgwRoutePropagation': # only replace created routes if route_spec_matches_route_cidr(route_spec, route): return "replace", i -def ensure_routes(connection=None, module=None, route_table=None, route_specs=None, - propagating_vgw_ids=None, check_mode=None, purge_routes=None): +def ensure_routes(connection, module, route_table, route_specs, purge_routes): routes_to_match = list(route_table['Routes']) route_specs_to_create = [] route_specs_to_recreate = [] @@ -434,16 +484,16 @@ def ensure_routes(connection=None, module=None, route_table=None, route_specs=No routes_to_delete = [] if purge_routes: - for r in routes_to_match: - if not r.get('DestinationCidrBlock'): + for route in routes_to_match: + if not route.get('DestinationCidrBlock'): module.warn("Skipping purging route {0} because it has no destination cidr block. " - "To remove VPC endpoints from route tables use the ec2_vpc_endpoint module.".format(r)) + "To remove VPC endpoints from route tables use the ec2_vpc_endpoint module.".format(route)) continue - if r['Origin'] == 'CreateRoute': - routes_to_delete.append(r) + if route['Origin'] == 'CreateRoute': + routes_to_delete.append(route) changed = bool(routes_to_delete or route_specs_to_create or route_specs_to_recreate) - if changed and not check_mode: + if changed and not module.check_mode: for route in routes_to_delete: try: connection.delete_route( @@ -467,34 +517,33 @@ def ensure_routes(connection=None, module=None, route_table=None, route_specs=No except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Couldn't create route") - return {'changed': bool(changed)} + return changed -def ensure_subnet_association(connection=None, module=None, vpc_id=None, route_table_id=None, subnet_id=None, - check_mode=None): +def ensure_subnet_association(connection, module, vpc_id, route_table_id, subnet_id): filters = ansible_dict_to_boto3_filter_list({'association.subnet-id': subnet_id, 'vpc-id': vpc_id}) try: route_tables = describe_route_tables_with_backoff(connection, Filters=filters) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't get route tables") for route_table in route_tables: - if route_table['RouteTableId'] is None: - continue - for a in route_table['Associations']: - if a['Main']: - continue - if a['SubnetId'] == subnet_id: - if route_table['RouteTableId'] == route_table_id: - return {'changed': False, 'association_id': a['RouteTableAssociationId']} - else: - if check_mode: + if route_table.get('RouteTableId'): + for association in route_table['Associations']: + if association['Main']: + continue + if association['SubnetId'] == subnet_id: + if route_table['RouteTableId'] == route_table_id: + return {'changed': False, 'association_id': association['RouteTableAssociationId']} + if module.check_mode: return {'changed': True} try: connection.disassociate_route_table( - aws_retry=True, AssociationId=a['RouteTableAssociationId']) + aws_retry=True, AssociationId=association['RouteTableAssociationId']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't disassociate subnet from route table") + if module.check_mode: + return {'changed': True} try: association_id = connection.associate_route_table(aws_retry=True, RouteTableId=route_table_id, @@ -504,45 +553,92 @@ def ensure_subnet_association(connection=None, module=None, vpc_id=None, route_t return {'changed': True, 'association_id': association_id} -def ensure_subnet_associations(connection=None, module=None, route_table=None, subnets=None, - check_mode=None, purge_subnets=None): - current_association_ids = [a['RouteTableAssociationId'] for a in route_table['Associations'] if not a['Main']] +def ensure_subnet_associations(connection, module, route_table, subnets, purge_subnets): + current_association_ids = [association['RouteTableAssociationId'] for association in route_table['Associations'] + if not association['Main'] and association.get('SubnetId')] new_association_ids = [] changed = False for subnet in subnets: result = ensure_subnet_association( connection=connection, module=module, vpc_id=route_table['VpcId'], - route_table_id=route_table['RouteTableId'], subnet_id=subnet['SubnetId'], - check_mode=check_mode) + route_table_id=route_table['RouteTableId'], subnet_id=subnet['SubnetId']) changed = changed or result['changed'] - if changed and check_mode: - return {'changed': True} + if changed and module.check_mode: + return True new_association_ids.append(result['association_id']) if purge_subnets: - to_delete = [a_id for a_id in current_association_ids - if a_id not in new_association_ids] - - for a_id in to_delete: + to_delete = [association_id for association_id in current_association_ids + if association_id not in new_association_ids] + for association_id in to_delete: changed = True - if not check_mode: + if not module.check_mode: try: - connection.disassociate_route_table(aws_retry=True, AssociationId=a_id) + connection.disassociate_route_table(aws_retry=True, AssociationId=association_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't disassociate subnet from route table") - return {'changed': changed} + return changed + + +def disassociate_gateway(connection, module, route_table): + # Delete all gateway associations that have state = associated + # Subnet associations are handled in its method + changed = False + associations_to_delete = [association['RouteTableAssociationId'] for association in route_table['Associations'] if not association['Main'] + and association.get('GatewayId') and association['AssociationState']['State'] in ['associated', 'associating']] + for association_id in associations_to_delete: + changed = True + if not module.check_mode: + try: + connection.disassociate_route_table(aws_retry=True, AssociationId=association_id) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Couldn't disassociate gateway from route table") + + return changed + +def associate_gateway(connection, module, route_table, gateway_id): + filters = ansible_dict_to_boto3_filter_list({'association.gateway-id': gateway_id, 'vpc-id': route_table['VpcId']}) + try: + route_tables = describe_route_tables_with_backoff(connection, Filters=filters) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Couldn't get route tables") + for table in route_tables: + if table.get('RouteTableId'): + for association in table.get('Associations'): + if association['Main']: + continue + if association.get('GatewayId', '') == gateway_id and (association['AssociationState']['State'] in ['associated', 'associating']): + if table['RouteTableId'] == route_table['RouteTableId']: + return False + elif module.check_mode: + return True + else: + try: + connection.disassociate_route_table( + aws_retry=True, AssociationId=association['RouteTableAssociationId']) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Couldn't disassociate gateway from route table") -def ensure_propagation(connection=None, module=None, route_table=None, propagating_vgw_ids=None, - check_mode=None): + if not module.check_mode: + try: + connection.associate_route_table(aws_retry=True, + RouteTableId=route_table['RouteTableId'], + GatewayId=gateway_id) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg="Couldn't associate gateway with route table") + return True + + +def ensure_propagation(connection, module, route_table, propagating_vgw_ids): changed = False gateways = [gateway['GatewayId'] for gateway in route_table['PropagatingVgws']] - to_add = set(propagating_vgw_ids) - set(gateways) - if to_add: + vgws_to_add = set(propagating_vgw_ids) - set(gateways) + if vgws_to_add: changed = True - if not check_mode: - for vgw_id in to_add: + if not module.check_mode: + for vgw_id in vgws_to_add: try: connection.enable_vgw_route_propagation( aws_retry=True, @@ -551,7 +647,7 @@ def ensure_propagation(connection=None, module=None, route_table=None, propagati except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't enable route propagation") - return {'changed': changed} + return changed def ensure_route_table_absent(connection, module): @@ -573,10 +669,11 @@ def ensure_route_table_absent(connection, module): if route_table is None: return {'changed': False} - # disassociate subnets before deleting route table + # disassociate subnets and gateway before deleting route table if not module.check_mode: ensure_subnet_associations(connection=connection, module=module, route_table=route_table, - subnets=[], check_mode=False, purge_subnets=purge_subnets) + subnets=[], purge_subnets=purge_subnets) + disassociate_gateway(connection=connection, module=module, route_table=route_table) try: connection.delete_route_table(aws_retry=True, RouteTableId=route_table['RouteTableId']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: @@ -618,6 +715,7 @@ def create_route_spec(connection, module, vpc_id): def ensure_route_table_present(connection, module): + gateway_id = module.params.get('gateway_id') lookup = module.params.get('lookup') propagating_vgw_ids = module.params.get('propagating_vgw_ids') purge_routes = module.params.get('purge_routes') @@ -668,14 +766,13 @@ def ensure_route_table_present(connection, module): if routes is not None: result = ensure_routes(connection=connection, module=module, route_table=route_table, - route_specs=routes, propagating_vgw_ids=propagating_vgw_ids, - check_mode=module.check_mode, purge_routes=purge_routes) - changed = changed or result['changed'] + route_specs=routes, purge_routes=purge_routes) + changed = changed or result if propagating_vgw_ids is not None: result = ensure_propagation(connection=connection, module=module, route_table=route_table, - propagating_vgw_ids=propagating_vgw_ids, check_mode=module.check_mode) - changed = changed or result['changed'] + propagating_vgw_ids=propagating_vgw_ids) + changed = changed or result if not tags_valid and tags is not None: changed |= ensure_ec2_tags(connection, module, route_table['RouteTableId'], @@ -685,11 +782,18 @@ def ensure_route_table_present(connection, module): if subnets is not None: associated_subnets = find_subnets(connection, module, vpc_id, subnets) - result = ensure_subnet_associations(connection=connection, module=module, route_table=route_table, - subnets=associated_subnets, check_mode=module.check_mode, - purge_subnets=purge_subnets) - changed = changed or result['changed'] + subnets=associated_subnets, purge_subnets=purge_subnets) + changed = changed or result + + if gateway_id == 'None' or gateway_id == '': + gateway_changed = disassociate_gateway(connection=connection, module=module, route_table=route_table) + elif gateway_id is not None: + gateway_changed = associate_gateway(connection=connection, module=module, route_table=route_table, gateway_id=gateway_id) + else: + gateway_changed = False + + changed = changed or gateway_changed if changed: # pause to allow route table routes/subnets/associations to be updated before exiting with final state @@ -699,6 +803,7 @@ def ensure_route_table_present(connection, module): def main(): argument_spec = dict( + gateway_id=dict(type='str'), lookup=dict(default='tag', choices=['tag', 'id']), propagating_vgw_ids=dict(type='list', elements='str'), purge_routes=dict(default=True, type='bool'), diff --git a/plugins/modules/ec2_vpc_route_table_info.py b/plugins/modules/ec2_vpc_route_table_info.py index 8ebf076a0b8..0579e1641db 100644 --- a/plugins/modules/ec2_vpc_route_table_info.py +++ b/plugins/modules/ec2_vpc_route_table_info.py @@ -59,20 +59,35 @@ type: complex contains: associations: - description: List of subnets associated with the route table + description: List of associations between the route table and one or more subnets or a gateway returned: always type: complex contains: + association_state: + description: The state of the association + returned: always + type: complex + contains: + state: + description: The state of the association + returned: always + type: str + sample: associated + state_message: + description: Additional information about the state of the association + returned: when available + type: str + sample: 'Creating association' + gateway_id: + description: ID of the internet gateway or virtual private gateway + returned: when route table is a gateway route table + type: str + sample: igw-03312309 main: description: Whether this is the main route table returned: always type: bool sample: false - id: - description: ID of association between route table and subnet - returned: always - type: str - sample: rtbassoc-ab47cfc3 route_table_association_id: description: ID of association between route table and subnet returned: always @@ -85,24 +100,9 @@ sample: rtb-bf779ed7 subnet_id: description: ID of the subnet - returned: always + returned: when route table is a subnet route table type: str sample: subnet-82055af9 - association_state: - description: The state of the association - returned: always - type: complex - contains: - state: - description: The state of the association - returned: always - type: str - sample: associated - state_message: - description: Additional information about the state of the association - returned: when available - type: str - sample: 'Creating association' id: description: ID of the route table (same as route_table_id for backwards compatibility) returned: always diff --git a/tests/integration/targets/ec2_vpc_route_table/defaults/main.yml b/tests/integration/targets/ec2_vpc_route_table/defaults/main.yml index 81bbd5d7ea7..111510850d3 100644 --- a/tests/integration/targets/ec2_vpc_route_table/defaults/main.yml +++ b/tests/integration/targets/ec2_vpc_route_table/defaults/main.yml @@ -1,3 +1,4 @@ --- availability_zone_a: '{{ ec2_availability_zone_names[0] }}' availability_zone_b: '{{ ec2_availability_zone_names[1] }}' +vpc_cidr: 10.228.224.0/21 diff --git a/tests/integration/targets/ec2_vpc_route_table/tasks/main.yml b/tests/integration/targets/ec2_vpc_route_table/tasks/main.yml index cf78b5b00b5..69c47858f89 100644 --- a/tests/integration/targets/ec2_vpc_route_table/tasks/main.yml +++ b/tests/integration/targets/ec2_vpc_route_table/tasks/main.yml @@ -9,7 +9,7 @@ - name: create VPC ec2_vpc_net: - cidr_block: 10.228.224.0/21 + cidr_block: '{{ vpc_cidr }}' name: '{{ resource_prefix }}_vpc' state: present register: vpc @@ -20,7 +20,7 @@ - vpc.changed - name: Assign IPv6 CIDR block to existing VPC, check mode ec2_vpc_net: - cidr_block: 10.228.224.0/21 + cidr_block: '{{ vpc_cidr }}' name: '{{ resource_prefix }}_vpc' ipv6_cidr: true check_mode: true @@ -31,7 +31,7 @@ - vpc_update.changed - name: Assign Amazon-provided IPv6 CIDR block to existing VPC ec2_vpc_net: - cidr_block: 10.228.224.0/21 + cidr_block: '{{ vpc_cidr }}' name: '{{ resource_prefix }}_vpc' ipv6_cidr: true register: vpc_update @@ -66,8 +66,8 @@ vpc_id: '{{ vpc.vpc.id }}' state: present tags: - Public: '{{ item.public|string }}' - Name: "{{ (item.public|bool)|ternary('public', 'private') }}-{{ item.zone }}" + Public: '{{ item.public | string }}' + Name: "{{ (item.public | bool) | ternary('public', 'private') }}-{{ item.zone }}" with_items: - cidr: 10.228.224.0/24 zone: '{{ availability_zone_a }}' @@ -111,15 +111,16 @@ vpc-id: '{{ vpc.vpc.id }}' register: vpc_subnets - set_fact: - public_subnets: "{{ (vpc_subnets.subnets| selectattr('tags.Public', 'equalto',\ - \ 'True')| map(attribute='id')| list) }}" - public_cidrs: "{{ (vpc_subnets.subnets| selectattr('tags.Public', 'equalto',\ - \ 'True')| map(attribute='cidr_block')| list) }}" - private_subnets: "{{ (vpc_subnets.subnets| selectattr('tags.Public', 'equalto',\ - \ 'False')| map(attribute='id')| list) }}" + public_subnets: "{{ (vpc_subnets.subnets | selectattr('tags.Public', 'equalto',\ + \ 'True') | map(attribute='id') | list) }}" + public_cidrs: "{{ (vpc_subnets.subnets | selectattr('tags.Public', 'equalto',\ + \ 'True') | map(attribute='cidr_block') | list) }}" + private_subnets: "{{ (vpc_subnets.subnets | selectattr('tags.Public', 'equalto',\ + \ 'False') | map(attribute='id') | list) }}" - name: create IGW ec2_vpc_igw: vpc_id: '{{ vpc.vpc.id }}' + register: vpc_igw - name: create NAT GW ec2_vpc_nat_gateway: if_exist_do_not_create: yes @@ -151,13 +152,13 @@ that: - create_public_table.changed - create_public_table.route_table.id.startswith('rtb-') - - "'Public' in create_public_table.route_table.tags and create_public_table.route_table.tags['Public']\ - \ == 'true'" - # One route for IPv4, one route for IPv6 - - create_public_table.route_table.routes|length == 2 - - create_public_table.route_table.associations|length == 0 + - "'Public' in create_public_table.route_table.tags" + - create_public_table.route_table.tags['Public'] == 'true' + - create_public_table.route_table.associations | length == 0 - create_public_table.route_table.vpc_id == "{{ vpc.vpc.id }}" - - create_public_table.route_table.propagating_vgws|length == 0 + - create_public_table.route_table.propagating_vgws | length == 0 + # One route for IPv4, one route for IPv6 + - create_public_table.route_table.routes | length == 2 - name: CHECK MODE - route table should already exist ec2_vpc_route_table: @@ -184,12 +185,12 @@ that: - not recreate_public_route_table.changed - create_public_table.route_table.id.startswith('rtb-') - - "'Public' in create_public_table.route_table.tags and create_public_table.route_table.tags['Public']\ - \ == 'true'" - - create_public_table.route_table.routes|length == 2 - - create_public_table.route_table.associations|length == 0 + - "'Public' in create_public_table.route_table.tags" + - create_public_table.route_table.tags['Public'] == 'true' + - create_public_table.route_table.associations | length == 0 - create_public_table.route_table.vpc_id == "{{ vpc.vpc.id }}" - - create_public_table.route_table.propagating_vgws|length == 0 + - create_public_table.route_table.propagating_vgws | length == 0 + - create_public_table.route_table.routes | length == 2 - name: CHECK MODE - add route to public route table ec2_vpc_route_table: @@ -225,17 +226,17 @@ assert: that: - add_routes.changed + - add_routes.route_table.id.startswith('rtb-') + - "'Public' in add_routes.route_table.tags" + - add_routes.route_table.tags['Public'] == 'true' # 10.228.224.0/21 # 0.0.0.0/0 # ::/0 # Amazon-provide IPv6 block - - add_routes.route_table.routes|length == 4 - - add_routes.route_table.id.startswith('rtb-') - - "'Public' in add_routes.route_table.tags and add_routes.route_table.tags['Public']\ - \ == 'true'" - - add_routes.route_table.associations|length == 0 + - add_routes.route_table.routes | length == 4 + - add_routes.route_table.associations | length == 0 - add_routes.route_table.vpc_id == "{{ vpc.vpc.id }}" - - add_routes.route_table.propagating_vgws|length == 0 + - add_routes.route_table.propagating_vgws | length == 0 - name: CHECK MODE - re-add route to public route table ec2_vpc_route_table: @@ -267,7 +268,7 @@ assert: that: - add_routes is not changed - - add_routes.route_table.routes|length == 4 + - add_routes.route_table.routes | length == 4 - name: CHECK MODE - add subnets to public route table ec2_vpc_route_table: @@ -301,18 +302,8 @@ assert: that: - add_subnets.changed - - add_subnets.route_table.associations|length == 3 + - add_subnets.route_table.associations | length == 3 - - name: add a route to public route table - ec2_vpc_route_table: - vpc_id: '{{ vpc.vpc.id }}' - tags: - Public: 'true' - Name: Public route table - routes: - - dest: 0.0.0.0/0 - gateway_id: igw - register: add_routes - name: CHECK MODE - no routes but purge_routes set to false ec2_vpc_route_table: vpc_id: '{{ vpc.vpc.id }}' @@ -341,8 +332,8 @@ assert: that: - not no_purge_routes.changed - - no_purge_routes.route_table.routes|length == 4 - - no_purge_routes.route_table.associations|length == 3 + - no_purge_routes.route_table.routes | length == 4 + - no_purge_routes.route_table.associations | length == 3 - name: rerun with purge_subnets set to false ec2_vpc_route_table: @@ -359,8 +350,8 @@ assert: that: - not no_purge_subnets.changed - - no_purge_subnets.route_table.routes|length == 4 - - no_purge_subnets.route_table.associations|length == 3 + - no_purge_subnets.route_table.routes | length == 4 + - no_purge_subnets.route_table.associations | length == 3 - name: rerun with purge_tags not set (implicitly false) ec2_vpc_route_table: @@ -376,8 +367,8 @@ assert: that: - not no_purge_tags.changed - - "'Public' in no_purge_tags.route_table.tags and no_purge_tags.route_table.tags['Public']\ - \ == 'true'" + - "'Public' in no_purge_tags.route_table.tags" + - no_purge_tags.route_table.tags['Public'] == 'true' - name: CHECK MODE - purge subnets ec2_vpc_route_table: @@ -411,7 +402,7 @@ assert: that: - purge_subnets.changed - - purge_subnets.route_table.associations|length == 0 + - purge_subnets.route_table.associations | length == 0 - purge_subnets.route_table.id == create_public_table.route_table.id - name: CHECK MODE - purge routes @@ -442,7 +433,7 @@ assert: that: - add_subnets_cidr.changed - - add_subnets_cidr.route_table.associations|length == 3 + - add_subnets_cidr.route_table.associations | length == 3 - name: purge subnets added by cidr ec2_vpc_route_table: @@ -458,7 +449,7 @@ assert: that: - purge_subnets_cidr.changed - - purge_subnets_cidr.route_table.associations|length == 0 + - purge_subnets_cidr.route_table.associations | length == 0 - name: add subnets by name to public route table ec2_vpc_route_table: @@ -474,7 +465,7 @@ assert: that: - add_subnets_name.changed - - add_subnets_name.route_table.associations|length == 3 + - add_subnets_name.route_table.associations | length == 3 - name: purge subnets added by name ec2_vpc_route_table: @@ -490,7 +481,7 @@ assert: that: - purge_subnets_name.changed - - purge_subnets_name.route_table.associations|length == 0 + - purge_subnets_name.route_table.associations | length == 0 - name: purge routes ec2_vpc_route_table: @@ -504,7 +495,7 @@ assert: that: - purge_routes.changed - - purge_routes.route_table.routes|length == 3 + - purge_routes.route_table.routes | length == 3 - purge_routes.route_table.id == create_public_table.route_table.id - name: CHECK MODE - update tags @@ -537,8 +528,8 @@ assert: that: - update_tags.changed - - "'Updated' in update_tags.route_table.tags and update_tags.route_table.tags['Updated']\ - \ == 'new_tag'" + - "'Updated' in update_tags.route_table.tags" + - update_tags.route_table.tags['Updated'] == 'new_tag' - "'Public' not in update_tags.route_table.tags" - name: create NAT GW @@ -668,10 +659,10 @@ that: - route_table_info.route_tables | length == 1 - '"tags" in route_table_info.route_tables[0]' - - '"Public" in route_table_info.route_tables[0].tags and route_table_info.route_tables[0].tags["Public"] - == "false"' - - '"Name" in route_table_info.route_tables[0].tags and route_table_info.route_tables[0].tags["Name"] - == "Private route table"' + - '"Public" in route_table_info.route_tables[0].tags' + - route_table_info.route_tables[0].tags["Public"] == "false" + - '"Name" in route_table_info.route_tables[0].tags' + - route_table_info.route_tables[0].tags["Name"] == "Private route table" - name: create NAT GW ec2_vpc_nat_gateway: @@ -731,6 +722,714 @@ that: - endpoint_details.vpc_endpoints[0].route_table_ids[0] == recreate_private_table.route_table.route_table_id + # ------------------------------------------------------------------------------------------ + + - name: Create gateway route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Create gateway route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 2 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Create gateway route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Create gateway route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 2 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Create ENI for gateway route table + ec2_eni: + subnet_id: '{{ public_subnets[0] }}' + register: eni + + - name: Replace route to gateway route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "{{ vpc_cidr }}" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Replace route to gateway route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "{{ vpc_cidr }}" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 2 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + - create_gateway_table.route_table.routes[0].destination_cidr_block == vpc_cidr + - create_gateway_table.route_table.routes[0].network_interface_id == eni.interface.id + + - name: Replace route to gateway route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "{{ vpc_cidr }}" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Replace route to gateway route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "{{ vpc_cidr }}" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 2 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + - create_gateway_table.route_table.routes[0].destination_cidr_block == vpc_cidr + - create_gateway_table.route_table.routes[0].network_interface_id == eni.interface.id + + # ------------------------------------------------------------------------------------------ + + - name: Add route to gateway route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Add route to gateway route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Add route to gateway route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Add route to gateway route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 1 + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Ensure gateway doesn't disassociate when not passed in - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Ensure gateway doesn't disassociate when not passed in + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 1 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Disassociate gateway when gateway_id is 'None' - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: None + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Disassociate gateway when gateway_id is 'None' + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: None + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 0 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Disassociate gateway when gateway_id is 'None' (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: None + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Disassociate gateway when gateway_id is 'None' (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: None + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 0 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Associate gateway with route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Associate gateway with route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 1 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 1 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Associate gateway with route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Associate gateway with route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vpc_igw.gateway_id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 1 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 1 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Disassociate gateway when gateway_id is '' - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: '' + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Disassociate gateway when gateway_id is '' + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: '' + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 0 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Disassociate gateway when gateway_id is '' (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: '' + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Disassociate gateway when gateway_id is '' (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: '' + routes: + - dest: "10.228.228.0/24" + network_interface_id: "{{ eni.interface.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 0 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Create vgw for gateway route table + ec2_vpc_vgw: + state: present + vpc_id: "{{ vpc.vpc.id }}" + type: ipsec.1 + name: '{{ resource_prefix }}_vpc' + register: vgw + + - name: Associate vgw with route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vgw.vgw.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is changed + + - name: Associate vgw with route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vgw.vgw.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 2 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 1 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + - name: Associate vgw with route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vgw.vgw.id }}" + purge_routes: no + register: create_gateway_table + check_mode: yes + + - assert: + that: + - create_gateway_table is not changed + + - name: Associate vgw with route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + gateway_id: "{{ vgw.vgw.id }}" + purge_routes: no + register: create_gateway_table + + - assert: + that: + - create_gateway_table is not changed + - create_gateway_table.route_table.id.startswith('rtb-') + - "'Public' in create_gateway_table.route_table.tags" + - create_gateway_table.route_table.tags['Public'] == 'true' + - create_gateway_table.route_table.routes | length == 3 + - create_gateway_table.route_table.associations | length == 2 + - "{{ create_gateway_table.route_table.associations | map(attribute='association_state') | selectattr('state', '==', 'associated') | length == 1 }}" + - create_gateway_table.route_table.vpc_id == vpc.vpc.id + - create_gateway_table.route_table.propagating_vgws | length == 0 + + # ------------------------------------------------------------------------------------------ + + - name: Get route table info + ec2_vpc_route_table_info: + filters: + route-table-id: "{{ create_gateway_table.route_table.id }}" + register: rt_info + + - name: Assert route table exists prior to deletion + assert: + that: + - rt_info.route_tables | length == 1 + + - name: Delete gateway route table - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + state: absent + register: delete_gateway_table + check_mode: yes + + - assert: + that: + - delete_gateway_table is changed + + - name: Delete gateway route table + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + state: absent + register: delete_gateway_table + + - name: Get route table info + ec2_vpc_route_table_info: + filters: + route-table-id: "{{ create_gateway_table.route_table.id }}" + register: rt_info + + - name: Assert route table was deleted + assert: + that: + - delete_gateway_table is changed + - rt_info.route_tables | length == 0 + + - name: Delete gateway route table (idempotence) - check_mode + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + state: absent + register: delete_gateway_table + check_mode: yes + + - assert: + that: + - delete_gateway_table is not changed + + - name: Delete gateway route table (idempotence) + ec2_vpc_route_table: + vpc_id: "{{ vpc.vpc.id }}" + tags: + Public: 'true' + Name: Gateway route table + state: absent + register: delete_gateway_table + + - name: Get route table info + ec2_vpc_route_table_info: + filters: + route-table-id: "{{ create_gateway_table.route_table.id }}" + register: rt_info + + - name: Assert route table was deleted + assert: + that: + - delete_gateway_table is not changed + - rt_info.route_tables | length == 0 + always: ############################################################################# # TEAR DOWN STARTS HERE @@ -747,8 +1446,9 @@ lookup: id state: absent with_items: - - '{{ create_public_table|default() }}' - - '{{ create_private_table|default() }}' + - '{{ create_public_table | default() }}' + - '{{ create_private_table | default() }}' + - '{{ create_gateway_table | default() }}' when: item and not item.failed ignore_errors: yes - name: destroy NAT GW @@ -764,6 +1464,18 @@ vpc_id: '{{ vpc.vpc.id }}' state: absent ignore_errors: yes + - name: destroy VGW + ec2_vpc_vgw: + state: absent + type: ipsec.1 + name: '{{ resource_prefix }}_vpc' + vpc_id: "{{ vpc.vpc.id }}" + ignore_errors: yes + - name: destroy ENI + ec2_eni: + state: absent + eni_id: '{{ eni.interface.id }}' + ignore_errors: yes - name: destroy subnets ec2_vpc_subnet: cidr: '{{ item.cidr }}' @@ -783,4 +1495,4 @@ cidr_block: 10.228.224.0/21 name: '{{ resource_prefix }}_vpc' state: absent - ignore_errors: yes + ignore_errors: yes \ No newline at end of file