Add support for EC2 transit gateway associations (#4089)
Co-authored-by: Nevil Macwan <macnev2013@gmail.com> Co-authored-by: monty16597 <alonjamohit77@gmail.com>
This commit is contained in:
		
							parent
							
								
									6803a473dc
								
							
						
					
					
						commit
						6eeb4b4b32
					
				| @ -33,7 +33,7 @@ from moto.core.utils import ( | |||||||
| ) | ) | ||||||
| from moto.core import ACCOUNT_ID | from moto.core import ACCOUNT_ID | ||||||
| from moto.kms import kms_backends | from moto.kms import kms_backends | ||||||
| from moto.utilities.utils import load_resource, merge_multiple_dicts | from moto.utilities.utils import load_resource, merge_multiple_dicts, filter_resources | ||||||
| from os import listdir | from os import listdir | ||||||
| 
 | 
 | ||||||
| from .exceptions import ( | from .exceptions import ( | ||||||
| @ -6016,29 +6016,18 @@ class TransitGatewayBackend(object): | |||||||
|         return transit_gateway |         return transit_gateway | ||||||
| 
 | 
 | ||||||
|     def get_all_transit_gateways(self, filters): |     def get_all_transit_gateways(self, filters): | ||||||
|         transit_gateways = self.transit_gateways.values() |         transit_gateways = list(self.transit_gateways.values()) | ||||||
| 
 | 
 | ||||||
|         if filters is not None: |         attr_pairs = ( | ||||||
|             if filters.get("transit-gateway-id") is not None: |             ("transit-gateway-id", "id"), | ||||||
|                 transit_gateways = [ |             ("state", "state"), | ||||||
|                     transit_gateway |             ("owner-id", "owner_id"), | ||||||
|                     for transit_gateway in transit_gateways |         ) | ||||||
|                     if transit_gateway.id in filters["transit-gateway-id"] |  | ||||||
|                 ] |  | ||||||
|             if filters.get("state") is not None: |  | ||||||
|                 transit_gateways = [ |  | ||||||
|                     transit_gateway |  | ||||||
|                     for transit_gateway in transit_gateways |  | ||||||
|                     if transit_gateway.state in filters["state"] |  | ||||||
|                 ] |  | ||||||
|             if filters.get("owner-id") is not None: |  | ||||||
|                 transit_gateways = [ |  | ||||||
|                     transit_gateway |  | ||||||
|                     for transit_gateway in transit_gateways |  | ||||||
|                     if transit_gateway.owner_id in filters["owner-id"] |  | ||||||
|                 ] |  | ||||||
| 
 | 
 | ||||||
|         return transit_gateways |         result = transit_gateways | ||||||
|  |         if filters: | ||||||
|  |             result = filter_resources(transit_gateways, filters, attr_pairs) | ||||||
|  |         return result | ||||||
| 
 | 
 | ||||||
|     def delete_transit_gateway(self, transit_gateway_id): |     def delete_transit_gateway(self, transit_gateway_id): | ||||||
|         return self.transit_gateways.pop(transit_gateway_id) |         return self.transit_gateways.pop(transit_gateway_id) | ||||||
| @ -6074,6 +6063,8 @@ class TransitGatewayRouteTable(TaggedEC2Resource): | |||||||
|         self.state = "available" |         self.state = "available" | ||||||
|         self.routes = {} |         self.routes = {} | ||||||
|         self.add_tags(tags or {}) |         self.add_tags(tags or {}) | ||||||
|  |         self.route_table_association = {} | ||||||
|  |         self.route_table_propagation = {} | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def physical_resource_id(self): |     def physical_resource_id(self): | ||||||
| @ -6109,9 +6100,9 @@ class TransitGatewayRouteTableBackend(object): | |||||||
|         return transit_gateways_route_table |         return transit_gateways_route_table | ||||||
| 
 | 
 | ||||||
|     def get_all_transit_gateway_route_tables( |     def get_all_transit_gateway_route_tables( | ||||||
|         self, transit_gateway_ids=None, filters=None |         self, transit_gateway_route_table_ids=None, filters=None | ||||||
|     ): |     ): | ||||||
|         transit_gateway_route_tables = self.transit_gateways_route_tables.values() |         transit_gateway_route_tables = list(self.transit_gateways_route_tables.values()) | ||||||
| 
 | 
 | ||||||
|         attr_pairs = ( |         attr_pairs = ( | ||||||
|             ("default-association-route-table", "default_association_route_table"), |             ("default-association-route-table", "default_association_route_table"), | ||||||
| @ -6121,28 +6112,24 @@ class TransitGatewayRouteTableBackend(object): | |||||||
|             ("transit-gateway-route-table-id", "id"), |             ("transit-gateway-route-table-id", "id"), | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         if transit_gateway_ids: |         if transit_gateway_route_table_ids: | ||||||
|             transit_gateway_route_tables = [ |             transit_gateway_route_tables = [ | ||||||
|                 transit_gateway_route_table |                 transit_gateway_route_table | ||||||
|                 for transit_gateway_route_table in transit_gateway_route_tables |                 for transit_gateway_route_table in transit_gateway_route_tables | ||||||
|                 if transit_gateway_route_table.id in transit_gateway_ids |                 if transit_gateway_route_table.id in transit_gateway_route_table_ids | ||||||
|             ] |             ] | ||||||
| 
 | 
 | ||||||
|  |         result = transit_gateway_route_tables | ||||||
|         if filters: |         if filters: | ||||||
|             for attrs in attr_pairs: |             result = filter_resources(transit_gateway_route_tables, filters, attr_pairs) | ||||||
|                 values = filters.get(attrs[0]) or None |         return result | ||||||
|                 if values is not None: |  | ||||||
|                     transit_gateway_route_tables = [ |  | ||||||
|                         transit_gateway_route_table |  | ||||||
|                         for transit_gateway_route_table in transit_gateway_route_tables |  | ||||||
|                         if not values |  | ||||||
|                         or getattr(transit_gateway_route_table, attrs[1]) in values |  | ||||||
|                     ] |  | ||||||
| 
 |  | ||||||
|         return transit_gateway_route_tables |  | ||||||
| 
 | 
 | ||||||
|     def delete_transit_gateway_route_table(self, transit_gateway_route_table_id): |     def delete_transit_gateway_route_table(self, transit_gateway_route_table_id): | ||||||
|         return self.transit_gateways_route_tables.pop(transit_gateway_route_table_id) |         transit_gateways_route_table = self.transit_gateways_route_tables[ | ||||||
|  |             transit_gateway_route_table_id | ||||||
|  |         ] | ||||||
|  |         transit_gateways_route_table.state = "deleted" | ||||||
|  |         return transit_gateways_route_table | ||||||
| 
 | 
 | ||||||
|     def create_transit_gateway_route( |     def create_transit_gateway_route( | ||||||
|         self, |         self, | ||||||
| @ -6151,22 +6138,31 @@ class TransitGatewayRouteTableBackend(object): | |||||||
|         transit_gateway_attachment_id=None, |         transit_gateway_attachment_id=None, | ||||||
|         blackhole=False, |         blackhole=False, | ||||||
|     ): |     ): | ||||||
|         transit_gateways_route_table = self.transit_gateways_route_tables[ |         transit_gateways_route_table = self.transit_gateways_route_tables.get( | ||||||
|             transit_gateway_route_table_id |             transit_gateway_route_table_id | ||||||
|         ] |         ) | ||||||
|  |         transit_gateway_attachment = self.transit_gateway_attachments.get( | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ) | ||||||
|         transit_gateways_route_table.routes[destination_cidr_block] = { |         transit_gateways_route_table.routes[destination_cidr_block] = { | ||||||
|             "destinationCidrBlock": destination_cidr_block, |             "destinationCidrBlock": destination_cidr_block, | ||||||
|             "prefixListId": "", |             "prefixListId": "", | ||||||
|             "state": "blackhole" if blackhole else "active", |             "state": "blackhole" if blackhole else "active", | ||||||
|             # TODO: needs to be fixed once we have support for transit gateway attachments |             "type": "static", | ||||||
|             "transitGatewayAttachments": { |  | ||||||
|                 "resourceId": "TODO", |  | ||||||
|                 "resourceType": "TODO", |  | ||||||
|                 "transitGatewayAttachmentId": transit_gateway_attachment_id, |  | ||||||
|             }, |  | ||||||
|             "type": "TODO", |  | ||||||
|         } |         } | ||||||
|         return transit_gateways_route_table | 
 | ||||||
|  |         if transit_gateway_attachment: | ||||||
|  |             transit_gateway_attachment_dict = { | ||||||
|  |                 "transitGatewayAttachments": { | ||||||
|  |                     "resourceId": transit_gateway_attachment.resource_id, | ||||||
|  |                     "resourceType": transit_gateway_attachment.resource_type, | ||||||
|  |                     "transitGatewayAttachmentId": transit_gateway_attachment_id, | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             transit_gateways_route_table.routes[destination_cidr_block].update( | ||||||
|  |                 transit_gateway_attachment_dict | ||||||
|  |             ) | ||||||
|  |         return transit_gateways_route_table.routes[destination_cidr_block] | ||||||
| 
 | 
 | ||||||
|     def delete_transit_gateway_route( |     def delete_transit_gateway_route( | ||||||
|         self, transit_gateway_route_table_id, destination_cidr_block, |         self, transit_gateway_route_table_id, destination_cidr_block, | ||||||
| @ -6180,27 +6176,120 @@ class TransitGatewayRouteTableBackend(object): | |||||||
|     def search_transit_gateway_routes( |     def search_transit_gateway_routes( | ||||||
|         self, transit_gateway_route_table_id, filters, max_results=None |         self, transit_gateway_route_table_id, filters, max_results=None | ||||||
|     ): |     ): | ||||||
|         transit_gateway_route_table = self.transit_gateways_route_tables[ |         transit_gateway_route_table = self.transit_gateways_route_tables.get( | ||||||
|             transit_gateway_route_table_id |             transit_gateway_route_table_id | ||||||
|         ] |         ) | ||||||
|  |         if not transit_gateway_route_table: | ||||||
|  |             return [] | ||||||
| 
 | 
 | ||||||
|         attr_pairs = ( |         attr_pairs = ( | ||||||
|             ("type", "type"), |             ("type", "type"), | ||||||
|             ("state", "state"), |             ("state", "state"), | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         for attrs in attr_pairs: |         routes = transit_gateway_route_table.routes.copy() | ||||||
|             values = filters.get(attrs[0]) or None |         for key in transit_gateway_route_table.routes: | ||||||
|             if values: |             for attrs in attr_pairs: | ||||||
|                 routes = [ |                 values = filters.get(attrs[0]) or None | ||||||
|                     transit_gateway_route_table.routes[key] |                 if values: | ||||||
|                     for key in transit_gateway_route_table.routes |                     if routes.get(key).get(attrs[1]) not in values: | ||||||
|                     if transit_gateway_route_table.routes[key][attrs[1]] in values |                         routes.pop(key) | ||||||
|                 ] |                         break | ||||||
|         if max_results: |         if max_results: | ||||||
|             routes = routes[: int(max_results)] |             routes = routes[: int(max_results)] | ||||||
|         return routes |         return routes | ||||||
| 
 | 
 | ||||||
|  |     def set_route_table_association( | ||||||
|  |         self, transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |     ): | ||||||
|  |         self.transit_gateways_route_tables[ | ||||||
|  |             transit_gateway_route_table_id | ||||||
|  |         ].route_table_association = { | ||||||
|  |             "resourceId": self.transit_gateway_attachments[ | ||||||
|  |                 transit_gateway_attachment_id | ||||||
|  |             ].resource_id, | ||||||
|  |             "resourceType": self.transit_gateway_attachments[ | ||||||
|  |                 transit_gateway_attachment_id | ||||||
|  |             ].resource_type, | ||||||
|  |             "state": "associated", | ||||||
|  |             "transitGatewayAttachmentId": transit_gateway_attachment_id, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     def set_route_table_propagation( | ||||||
|  |         self, transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |     ): | ||||||
|  |         self.transit_gateways_route_tables[ | ||||||
|  |             transit_gateway_route_table_id | ||||||
|  |         ].route_table_propagation = { | ||||||
|  |             "resourceId": self.transit_gateway_attachments[ | ||||||
|  |                 transit_gateway_attachment_id | ||||||
|  |             ].resource_id, | ||||||
|  |             "resourceType": self.transit_gateway_attachments[ | ||||||
|  |                 transit_gateway_attachment_id | ||||||
|  |             ].resource_type, | ||||||
|  |             "state": "enabled", | ||||||
|  |             "transitGatewayAttachmentId": transit_gateway_attachment_id, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     def disable_route_table_propagation(self, transit_gateway_route_table_id): | ||||||
|  |         self.transit_gateways_route_tables[ | ||||||
|  |             transit_gateway_route_table_id | ||||||
|  |         ].route_table_propagation = {} | ||||||
|  | 
 | ||||||
|  |     def get_all_transit_gateway_route_table_associations( | ||||||
|  |         self, transit_gateway_route_table_id=None, filters=None | ||||||
|  |     ): | ||||||
|  |         transit_gateway_route_tables = list(self.transit_gateways_route_tables.values()) | ||||||
|  | 
 | ||||||
|  |         if transit_gateway_route_tables: | ||||||
|  |             transit_gateway_route_tables = [ | ||||||
|  |                 transit_gateway_route_table | ||||||
|  |                 for transit_gateway_route_table in transit_gateway_route_tables | ||||||
|  |                 if transit_gateway_route_table.id in transit_gateway_route_table_id | ||||||
|  |             ] | ||||||
|  | 
 | ||||||
|  |         attr_pairs = ( | ||||||
|  |             ("resource-id", "route_table_association", "resourceId"), | ||||||
|  |             ("resource-type", "route_table_association", "resourceType"), | ||||||
|  |             ( | ||||||
|  |                 "transit-gateway-attachment-id", | ||||||
|  |                 "route_table_association", | ||||||
|  |                 "transitGatewayAttachmentId", | ||||||
|  |             ), | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         result = transit_gateway_route_tables | ||||||
|  |         if filters: | ||||||
|  |             result = filter_resources(transit_gateway_route_tables, filters, attr_pairs) | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  |     def get_all_transit_gateway_route_table_propagations( | ||||||
|  |         self, transit_gateway_route_table_id=None, filters=None | ||||||
|  |     ): | ||||||
|  |         transit_gateway_route_tables = list(self.transit_gateways_route_tables.values()) | ||||||
|  | 
 | ||||||
|  |         if transit_gateway_route_tables: | ||||||
|  |             transit_gateway_route_tables = [ | ||||||
|  |                 transit_gateway_route_table | ||||||
|  |                 for transit_gateway_route_table in transit_gateway_route_tables | ||||||
|  |                 if transit_gateway_route_table.id in transit_gateway_route_table_id | ||||||
|  |             ] | ||||||
|  | 
 | ||||||
|  |         attr_pairs = ( | ||||||
|  |             ("resource-id", "route_table_propagation", "resourceId"), | ||||||
|  |             ("resource-type", "route_table_propagation", "resourceType"), | ||||||
|  |             ( | ||||||
|  |                 "transit-gateway-attachment-id", | ||||||
|  |                 "route_table_propagation", | ||||||
|  |                 "transitGatewayAttachmentId", | ||||||
|  |             ), | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         result = transit_gateway_route_tables | ||||||
|  |         if filters: | ||||||
|  |             result = filter_resources(transit_gateway_route_tables, filters, attr_pairs) | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class TransitGatewayAttachment(TaggedEC2Resource): | class TransitGatewayAttachment(TaggedEC2Resource): | ||||||
|     def __init__( |     def __init__( | ||||||
| @ -6209,6 +6298,7 @@ class TransitGatewayAttachment(TaggedEC2Resource): | |||||||
| 
 | 
 | ||||||
|         self.ec2_backend = backend |         self.ec2_backend = backend | ||||||
|         self.association = {} |         self.association = {} | ||||||
|  |         self.propagation = {} | ||||||
|         self.resource_id = resource_id |         self.resource_id = resource_id | ||||||
|         self.resource_type = resource_type |         self.resource_type = resource_type | ||||||
| 
 | 
 | ||||||
| @ -6261,7 +6351,7 @@ class TransitGatewayVpcAttachment(TransitGatewayAttachment): | |||||||
| 
 | 
 | ||||||
| class TransitGatewayAttachmentBackend(object): | class TransitGatewayAttachmentBackend(object): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.transit_gateways_attachments = {} |         self.transit_gateway_attachments = {} | ||||||
|         super(TransitGatewayAttachmentBackend, self).__init__() |         super(TransitGatewayAttachmentBackend, self).__init__() | ||||||
| 
 | 
 | ||||||
|     def create_transit_gateway_vpn_attachment( |     def create_transit_gateway_vpn_attachment( | ||||||
| @ -6274,7 +6364,7 @@ class TransitGatewayAttachmentBackend(object): | |||||||
|             transit_gateway_id=transit_gateway_id, |             transit_gateway_id=transit_gateway_id, | ||||||
|             tags=tags, |             tags=tags, | ||||||
|         ) |         ) | ||||||
|         self.transit_gateways_attachments[ |         self.transit_gateway_attachments[ | ||||||
|             transit_gateway_vpn_attachment.id |             transit_gateway_vpn_attachment.id | ||||||
|         ] = transit_gateway_vpn_attachment |         ] = transit_gateway_vpn_attachment | ||||||
|         return transit_gateway_vpn_attachment |         return transit_gateway_vpn_attachment | ||||||
| @ -6290,7 +6380,7 @@ class TransitGatewayAttachmentBackend(object): | |||||||
|             subnet_ids=subnet_ids, |             subnet_ids=subnet_ids, | ||||||
|             options=options, |             options=options, | ||||||
|         ) |         ) | ||||||
|         self.transit_gateways_attachments[ |         self.transit_gateway_attachments[ | ||||||
|             transit_gateway_vpc_attachment.id |             transit_gateway_vpc_attachment.id | ||||||
|         ] = transit_gateway_vpc_attachment |         ] = transit_gateway_vpc_attachment | ||||||
|         return transit_gateway_vpc_attachment |         return transit_gateway_vpc_attachment | ||||||
| @ -6298,7 +6388,7 @@ class TransitGatewayAttachmentBackend(object): | |||||||
|     def describe_transit_gateway_attachments( |     def describe_transit_gateway_attachments( | ||||||
|         self, transit_gateways_attachment_ids=None, filters=None, max_results=0 |         self, transit_gateways_attachment_ids=None, filters=None, max_results=0 | ||||||
|     ): |     ): | ||||||
|         transit_gateways_attachments = self.transit_gateways_attachments.values() |         transit_gateway_attachments = list(self.transit_gateway_attachments.values()) | ||||||
| 
 | 
 | ||||||
|         attr_pairs = ( |         attr_pairs = ( | ||||||
|             ("resource-id", "resource_id"), |             ("resource-id", "resource_id"), | ||||||
| @ -6306,28 +6396,25 @@ class TransitGatewayAttachmentBackend(object): | |||||||
|             ("transit-gateway-id", "transit_gateway_id"), |             ("transit-gateway-id", "transit_gateway_id"), | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         if transit_gateways_attachment_ids: |         if ( | ||||||
|             transit_gateways_attachments = [ |             not transit_gateways_attachment_ids == [] | ||||||
|  |             and transit_gateways_attachment_ids is not None | ||||||
|  |         ): | ||||||
|  |             transit_gateway_attachments = [ | ||||||
|                 transit_gateways_attachment |                 transit_gateways_attachment | ||||||
|                 for transit_gateways_attachment in transit_gateways_attachments |                 for transit_gateways_attachment in transit_gateway_attachments | ||||||
|                 if transit_gateways_attachment.id in transit_gateways_attachment_ids |                 if transit_gateways_attachment.id in transit_gateways_attachment_ids | ||||||
|             ] |             ] | ||||||
| 
 | 
 | ||||||
|  |         result = transit_gateway_attachments | ||||||
|         if filters: |         if filters: | ||||||
|             for attrs in attr_pairs: |             result = filter_resources(transit_gateway_attachments, filters, attr_pairs) | ||||||
|                 values = filters.get(attrs[0]) or None |         return result | ||||||
|                 if values is not None: |  | ||||||
|                     transit_gateways_attachments = [ |  | ||||||
|                         transit_gateways_attachment |  | ||||||
|                         for transit_gateways_attachment in transit_gateways_attachments |  | ||||||
|                         if getattr(transit_gateways_attachment, attrs[1]) in values |  | ||||||
|                     ] |  | ||||||
|         return transit_gateways_attachments |  | ||||||
| 
 | 
 | ||||||
|     def describe_transit_gateway_vpc_attachments( |     def describe_transit_gateway_vpc_attachments( | ||||||
|         self, transit_gateways_attachment_ids=None, filters=None, max_results=0 |         self, transit_gateways_attachment_ids=None, filters=None, max_results=0 | ||||||
|     ): |     ): | ||||||
|         transit_gateways_attachments = self.transit_gateways_attachments.values() |         transit_gateway_attachments = list(self.transit_gateway_attachments.values()) | ||||||
| 
 | 
 | ||||||
|         attr_pairs = ( |         attr_pairs = ( | ||||||
|             ("state", "state"), |             ("state", "state"), | ||||||
| @ -6340,23 +6427,155 @@ class TransitGatewayAttachmentBackend(object): | |||||||
|             not transit_gateways_attachment_ids == [] |             not transit_gateways_attachment_ids == [] | ||||||
|             and transit_gateways_attachment_ids is not None |             and transit_gateways_attachment_ids is not None | ||||||
|         ): |         ): | ||||||
|             transit_gateways_attachments = [ |             transit_gateway_attachments = [ | ||||||
|                 transit_gateways_attachment |                 transit_gateways_attachment | ||||||
|                 for transit_gateways_attachment in transit_gateways_attachments |                 for transit_gateways_attachment in transit_gateway_attachments | ||||||
|                 if transit_gateways_attachment.id in transit_gateways_attachment_ids |                 if transit_gateways_attachment.id in transit_gateways_attachment_ids | ||||||
|             ] |             ] | ||||||
| 
 | 
 | ||||||
|  |         result = transit_gateway_attachments | ||||||
|         if filters: |         if filters: | ||||||
|             for attrs in attr_pairs: |             result = filter_resources(transit_gateway_attachments, filters, attr_pairs) | ||||||
|                 values = filters.get(attrs[0]) or None |         return result | ||||||
|                 if values is not None: |  | ||||||
|                     transit_gateways_attachments = [ |  | ||||||
|                         transit_gateways_attachment |  | ||||||
|                         for transit_gateways_attachment in transit_gateways_attachments |  | ||||||
|                         if getattr(transit_gateways_attachment, attrs[1]) in values |  | ||||||
|                     ] |  | ||||||
| 
 | 
 | ||||||
|         return transit_gateways_attachments |     def delete_transit_gateway_vpc_attachment(self, transit_gateway_attachment_id=None): | ||||||
|  |         transit_gateway_attachment = self.transit_gateway_attachments.pop( | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ) | ||||||
|  |         transit_gateway_attachment.state = "deleted" | ||||||
|  |         return transit_gateway_attachment | ||||||
|  | 
 | ||||||
|  |     def modify_transit_gateway_vpc_attachment( | ||||||
|  |         self, | ||||||
|  |         add_subnet_ids=None, | ||||||
|  |         options=None, | ||||||
|  |         remove_subnet_ids=None, | ||||||
|  |         transit_gateway_attachment_id=None, | ||||||
|  |     ): | ||||||
|  | 
 | ||||||
|  |         tgw_attachment = self.transit_gateway_attachments[transit_gateway_attachment_id] | ||||||
|  |         if remove_subnet_ids: | ||||||
|  |             tgw_attachment.subnet_ids = [ | ||||||
|  |                 id for id in tgw_attachment.subnet_ids if id not in remove_subnet_ids | ||||||
|  |             ] | ||||||
|  | 
 | ||||||
|  |         if options: | ||||||
|  |             tgw_attachment.options.update(options) | ||||||
|  | 
 | ||||||
|  |         if add_subnet_ids: | ||||||
|  |             for id in add_subnet_ids: | ||||||
|  |                 tgw_attachment.subnet_ids.append(id) | ||||||
|  | 
 | ||||||
|  |         return tgw_attachment | ||||||
|  | 
 | ||||||
|  |     def set_attachment_association( | ||||||
|  |         self, transit_gateway_attachment_id=None, transit_gateway_route_table_id=None | ||||||
|  |     ): | ||||||
|  |         self.transit_gateway_attachments[transit_gateway_attachment_id].association = { | ||||||
|  |             "state": "associated", | ||||||
|  |             "transitGatewayRouteTableId": transit_gateway_route_table_id, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     def set_attachment_propagation( | ||||||
|  |         self, transit_gateway_attachment_id=None, transit_gateway_route_table_id=None | ||||||
|  |     ): | ||||||
|  |         self.transit_gateway_attachments[transit_gateway_attachment_id].propagation = { | ||||||
|  |             "state": "enabled", | ||||||
|  |             "transitGatewayRouteTableId": transit_gateway_route_table_id, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     def disable_attachment_propagation(self, transit_gateway_attachment_id=None): | ||||||
|  |         self.transit_gateway_attachments[transit_gateway_attachment_id].propagation[ | ||||||
|  |             "state" | ||||||
|  |         ] = "disabled" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TransitGatewayRelations(object): | ||||||
|  |     # this class is for TransitGatewayAssociation and TransitGatewayPropagation | ||||||
|  |     def __init__( | ||||||
|  |         self, | ||||||
|  |         backend, | ||||||
|  |         transit_gateway_attachment_id=None, | ||||||
|  |         transit_gateway_route_table_id=None, | ||||||
|  |         state=None, | ||||||
|  |     ): | ||||||
|  |         self.ec2_backend = backend | ||||||
|  |         self.transit_gateway_attachment_id = transit_gateway_attachment_id | ||||||
|  |         self.transit_gateway_route_table_id = transit_gateway_route_table_id | ||||||
|  |         self.resource_id = backend.transit_gateway_attachments[ | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ].resource_id | ||||||
|  |         self.resource_type = backend.transit_gateway_attachments[ | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ].resource_type | ||||||
|  |         self.state = state | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TransitGatewayRelationsBackend(object): | ||||||
|  |     def __init__(self): | ||||||
|  |         self.transit_gateway_associations = {} | ||||||
|  |         self.transit_gateway_propagations = {} | ||||||
|  |         super(TransitGatewayRelationsBackend, self).__init__() | ||||||
|  | 
 | ||||||
|  |     def associate_transit_gateway_route_table( | ||||||
|  |         self, transit_gateway_attachment_id=None, transit_gateway_route_table_id=None | ||||||
|  |     ): | ||||||
|  |         transit_gateway_association = TransitGatewayRelations( | ||||||
|  |             self, | ||||||
|  |             transit_gateway_attachment_id, | ||||||
|  |             transit_gateway_route_table_id, | ||||||
|  |             state="associated", | ||||||
|  |         ) | ||||||
|  |         self.set_route_table_association( | ||||||
|  |             transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |         ) | ||||||
|  |         self.set_attachment_association( | ||||||
|  |             transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |         ) | ||||||
|  |         self.transit_gateway_associations[ | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ] = transit_gateway_association | ||||||
|  | 
 | ||||||
|  |         return transit_gateway_association | ||||||
|  | 
 | ||||||
|  |     def enable_transit_gateway_route_table_propagation( | ||||||
|  |         self, transit_gateway_attachment_id=None, transit_gateway_route_table_id=None | ||||||
|  |     ): | ||||||
|  |         transit_gateway_propagation = TransitGatewayRelations( | ||||||
|  |             self, | ||||||
|  |             transit_gateway_attachment_id, | ||||||
|  |             transit_gateway_route_table_id, | ||||||
|  |             state="enabled", | ||||||
|  |         ) | ||||||
|  |         self.set_route_table_propagation( | ||||||
|  |             transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |         ) | ||||||
|  |         self.set_attachment_propagation( | ||||||
|  |             transit_gateway_attachment_id, transit_gateway_route_table_id | ||||||
|  |         ) | ||||||
|  |         self.transit_gateway_propagations[ | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ] = transit_gateway_propagation | ||||||
|  | 
 | ||||||
|  |         return transit_gateway_propagation | ||||||
|  | 
 | ||||||
|  |     def disable_transit_gateway_route_table_propagation( | ||||||
|  |         self, transit_gateway_attachment_id=None, transit_gateway_route_table_id=None | ||||||
|  |     ): | ||||||
|  |         self.disable_route_table_propagation( | ||||||
|  |             transit_gateway_route_table_id=transit_gateway_route_table_id | ||||||
|  |         ) | ||||||
|  |         self.disable_attachment_propagation( | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id | ||||||
|  |         ) | ||||||
|  |         self.transit_gateway_propagations[ | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ].state = "disabled" | ||||||
|  |         transit_gateway_propagation = self.transit_gateway_propagations.pop( | ||||||
|  |             transit_gateway_attachment_id | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         return transit_gateway_propagation | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NatGateway(CloudFormationModel): | class NatGateway(CloudFormationModel): | ||||||
| @ -6721,6 +6940,7 @@ class EC2Backend( | |||||||
|     TransitGatewayBackend, |     TransitGatewayBackend, | ||||||
|     TransitGatewayRouteTableBackend, |     TransitGatewayRouteTableBackend, | ||||||
|     TransitGatewayAttachmentBackend, |     TransitGatewayAttachmentBackend, | ||||||
|  |     TransitGatewayRelationsBackend, | ||||||
|     LaunchTemplateBackend, |     LaunchTemplateBackend, | ||||||
|     IamInstanceProfileAssociationBackend, |     IamInstanceProfileAssociationBackend, | ||||||
| ): | ): | ||||||
|  | |||||||
| @ -41,6 +41,21 @@ class TransitGatewayAttachment(BaseResponse): | |||||||
|             transit_gateway_vpc_attachments=transit_gateway_vpc_attachments |             transit_gateway_vpc_attachments=transit_gateway_vpc_attachments | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |     def modify_transit_gateway_vpc_attachment(self): | ||||||
|  |         add_subnet_ids = self._get_multi_param("AddSubnetIds") | ||||||
|  |         options = self._get_multi_param_dict("Options") | ||||||
|  |         remove_subnet_ids = self._get_multi_param("RemoveSubnetIds") | ||||||
|  |         transit_gateway_attachment_id = self._get_param("TransitGatewayAttachmentId") | ||||||
|  | 
 | ||||||
|  |         transit_gateway_attachment = self.ec2_backend.modify_transit_gateway_vpc_attachment( | ||||||
|  |             add_subnet_ids=add_subnet_ids, | ||||||
|  |             options=options, | ||||||
|  |             remove_subnet_ids=remove_subnet_ids, | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id, | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(MODIFY_TRANSIT_GATEWAY_VPC_ATTACHMENTS) | ||||||
|  |         return template.render(transit_gateway_attachment=transit_gateway_attachment) | ||||||
|  | 
 | ||||||
|     def describe_transit_gateway_attachments(self): |     def describe_transit_gateway_attachments(self): | ||||||
|         transit_gateways_attachment_ids = self._get_multi_param( |         transit_gateways_attachment_ids = self._get_multi_param( | ||||||
|             "TransitGatewayAttachmentIds" |             "TransitGatewayAttachmentIds" | ||||||
| @ -55,6 +70,44 @@ class TransitGatewayAttachment(BaseResponse): | |||||||
|         template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_ATTACHMENTS) |         template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_ATTACHMENTS) | ||||||
|         return template.render(transit_gateway_attachments=transit_gateway_attachments) |         return template.render(transit_gateway_attachments=transit_gateway_attachments) | ||||||
| 
 | 
 | ||||||
|  |     def delete_transit_gateway_vpc_attachment(self): | ||||||
|  |         transit_gateway_attachment_id = self._get_param("TransitGatewayAttachmentId") | ||||||
|  |         transit_gateway_attachment = self.ec2_backend.delete_transit_gateway_vpc_attachment( | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(DELETE_TRANSIT_GATEWAY_VPC_ATTACHMENTS) | ||||||
|  |         return template.render(transit_gateway_attachment=transit_gateway_attachment) | ||||||
|  | 
 | ||||||
|  |     def associate_transit_gateway_route_table(self): | ||||||
|  |         transit_gateway_attachment_id = self._get_param("TransitGatewayAttachmentId") | ||||||
|  |         transit_gateway_route_table_id = self._get_param("TransitGatewayRouteTableId") | ||||||
|  |         transit_gateway_association = self.ec2_backend.associate_transit_gateway_route_table( | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id, | ||||||
|  |             transit_gateway_route_table_id=transit_gateway_route_table_id, | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(TRANSIT_GATEWAY_ASSOCIATION) | ||||||
|  |         return template.render(transit_gateway_association=transit_gateway_association) | ||||||
|  | 
 | ||||||
|  |     def enable_transit_gateway_route_table_propagation(self): | ||||||
|  |         transit_gateway_attachment_id = self._get_param("TransitGatewayAttachmentId") | ||||||
|  |         transit_gateway_route_table_id = self._get_param("TransitGatewayRouteTableId") | ||||||
|  |         transit_gateway_propagation = self.ec2_backend.enable_transit_gateway_route_table_propagation( | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id, | ||||||
|  |             transit_gateway_route_table_id=transit_gateway_route_table_id, | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(TRANSIT_GATEWAY_PROPAGATION) | ||||||
|  |         return template.render(transit_gateway_propagation=transit_gateway_propagation) | ||||||
|  | 
 | ||||||
|  |     def disable_transit_gateway_route_table_propagation(self): | ||||||
|  |         transit_gateway_attachment_id = self._get_param("TransitGatewayAttachmentId") | ||||||
|  |         transit_gateway_route_table_id = self._get_param("TransitGatewayRouteTableId") | ||||||
|  |         transit_gateway_propagation = self.ec2_backend.disable_transit_gateway_route_table_propagation( | ||||||
|  |             transit_gateway_attachment_id=transit_gateway_attachment_id, | ||||||
|  |             transit_gateway_route_table_id=transit_gateway_route_table_id, | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(TRANSIT_GATEWAY_PROPAGATION) | ||||||
|  |         return template.render(transit_gateway_propagation=transit_gateway_propagation) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| CREATE_TRANSIT_GATEWAY_VPC_ATTACHMENT = """<CreateTransitGatewayVpcAttachmentResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | CREATE_TRANSIT_GATEWAY_VPC_ATTACHMENT = """<CreateTransitGatewayVpcAttachmentResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|         <requestId>9b5766ac-2af6-4b92-9a8a-4d74ae46ae79</requestId> |         <requestId>9b5766ac-2af6-4b92-9a8a-4d74ae46ae79</requestId> | ||||||
| @ -153,3 +206,91 @@ DESCRIBE_TRANSIT_GATEWAY_VPC_ATTACHMENTS = """<DescribeTransitGatewayVpcAttachme | |||||||
|     </transitGatewayVpcAttachments> |     </transitGatewayVpcAttachments> | ||||||
| </DescribeTransitGatewayVpcAttachmentsResponse> | </DescribeTransitGatewayVpcAttachmentsResponse> | ||||||
| """ | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | MODIFY_TRANSIT_GATEWAY_VPC_ATTACHMENTS = """<ModifyTransitGatewayVpcAttachmentResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |         <requestId>9b5766ac-2af6-4b92-9a8a-4d74ae46ae79</requestId> | ||||||
|  |         <transitGatewayVpcAttachment> | ||||||
|  |             <createTime>{{ transit_gateway_attachment.create_time }}</createTime> | ||||||
|  |             <options> | ||||||
|  |                 <applianceModeSupport>{{ transit_gateway_attachment.options.ApplianceModeSupport }}</applianceModeSupport> | ||||||
|  |                 <dnsSupport>{{ transit_gateway_attachment.options.DnsSupport }}</dnsSupport> | ||||||
|  |                 <ipv6Support>{{ transit_gateway_attachment.options.Ipv6Support }}</ipv6Support> | ||||||
|  |             </options> | ||||||
|  |             <state>{{ transit_gateway_attachment.state }}</state> | ||||||
|  |             <subnetIds> | ||||||
|  |             {% for subnet_id in transit_gateway_attachment.subnet_ids %} | ||||||
|  |                 <item>{{ subnet_id }}</item> | ||||||
|  |             {% endfor %} | ||||||
|  |             </subnetIds> | ||||||
|  |             <tagSet> | ||||||
|  |             {% for tag in transit_gateway_attachment.get_tags() %} | ||||||
|  |                 <item> | ||||||
|  |                     <key>{{ tag.key }}</key> | ||||||
|  |                     <value>{{ tag.value }}</value> | ||||||
|  |                 </item> | ||||||
|  |             {% endfor %} | ||||||
|  |             </tagSet> | ||||||
|  |             <transitGatewayAttachmentId>{{ transit_gateway_attachment.id }}</transitGatewayAttachmentId> | ||||||
|  |             <transitGatewayId>{{ transit_gateway_attachment.transit_gateway_id }}</transitGatewayId> | ||||||
|  |             <vpcId>{{ transit_gateway_attachment.vpc_id }}</vpcId> | ||||||
|  |             <vpcOwnerId>{{ transit_gateway_attachment.resource_owner_id }}</vpcOwnerId> | ||||||
|  |     </transitGatewayVpcAttachment> | ||||||
|  | </ModifyTransitGatewayVpcAttachmentResponse>""" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DELETE_TRANSIT_GATEWAY_VPC_ATTACHMENTS = """<DeleteTransitGatewayVpcAttachmentResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |         <requestId>9b5766ac-2af6-4b92-9a8a-4d74ae46ae79</requestId> | ||||||
|  |         <transitGatewayVpcAttachment> | ||||||
|  |             <createTime>{{ transit_gateway_attachment.create_time }}</createTime> | ||||||
|  |             <options> | ||||||
|  |                 <applianceModeSupport>{{ transit_gateway_attachment.options.ApplianceModeSupport }}</applianceModeSupport> | ||||||
|  |                 <dnsSupport>{{ transit_gateway_attachment.options.DnsSupport }}</dnsSupport> | ||||||
|  |                 <ipv6Support>{{ transit_gateway_attachment.options.Ipv6Support }}</ipv6Support> | ||||||
|  |             </options> | ||||||
|  |             <state>{{ transit_gateway_attachment.state }}</state> | ||||||
|  |             <subnetIds> | ||||||
|  |             {% for subnet_id in transit_gateway_attachment.subnet_ids %} | ||||||
|  |                 <item>{{ subnet_id }}</item> | ||||||
|  |             {% endfor %} | ||||||
|  |             </subnetIds> | ||||||
|  |             <tagSet> | ||||||
|  |             {% for tag in transit_gateway_attachment.get_tags() %} | ||||||
|  |                 <item> | ||||||
|  |                     <key>{{ tag.key }}</key> | ||||||
|  |                     <value>{{ tag.value }}</value> | ||||||
|  |                 </item> | ||||||
|  |             {% endfor %} | ||||||
|  |             </tagSet> | ||||||
|  |             <transitGatewayAttachmentId>{{ transit_gateway_attachment.id }}</transitGatewayAttachmentId> | ||||||
|  |             <transitGatewayId>{{ transit_gateway_attachment.transit_gateway_id }}</transitGatewayId> | ||||||
|  |             <vpcId>{{ transit_gateway_attachment.vpc_id }}</vpcId> | ||||||
|  |             <vpcOwnerId>{{ transit_gateway_attachment.resource_owner_id }}</vpcOwnerId> | ||||||
|  |     </transitGatewayVpcAttachment> | ||||||
|  | </DeleteTransitGatewayVpcAttachmentResponse>""" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | TRANSIT_GATEWAY_ASSOCIATION = """<AssociateTransitGatewayRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |     <requestId>86a597cf-93ec-44a3-9559-4641863642a5</requestId> | ||||||
|  |     <association> | ||||||
|  |         <resourceId>{{ transit_gateway_association.resource_id }}</resourceId> | ||||||
|  |         <resourceType>{{ transit_gateway_association.resource_type }}</resourceType> | ||||||
|  |         <state>{{ transit_gateway_association.state }}</state> | ||||||
|  |         <transitGatewayAttachmentId>{{ transit_gateway_association.transit_gateway_attachment_id }}</transitGatewayAttachmentId> | ||||||
|  |         <transitGatewayRouteTableId>{{ transit_gateway_association.transit_gateway_route_table_id }}</transitGatewayRouteTableId> | ||||||
|  |     </association> | ||||||
|  | </AssociateTransitGatewayRouteTableResponse> | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | TRANSIT_GATEWAY_PROPAGATION = """<EnableTransitGatewayRouteTablePropagationResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |     <requestId>c78427d4-e498-46ae-bc14-32841b16bff4</requestId> | ||||||
|  |     <propagation> | ||||||
|  |         <resourceId>{{ transit_gateway_propagation.resource_id }}</resourceId> | ||||||
|  |         <resourceType>{{ transit_gateway_propagation.resource_type }}</resourceType> | ||||||
|  |         <state>{{ transit_gateway_propagation.state }}</state> | ||||||
|  |         <transitGatewayAttachmentId>{{ transit_gateway_propagation.transit_gateway_attachment_id }}</transitGatewayAttachmentId> | ||||||
|  |         <transitGatewayRouteTableId>{{ transit_gateway_propagation.transit_gateway_route_table_id }}</transitGatewayRouteTableId> | ||||||
|  |     </propagation> | ||||||
|  | </EnableTransitGatewayRouteTablePropagationResponse> | ||||||
|  | """ | ||||||
|  | |||||||
| @ -20,11 +20,11 @@ class TransitGatewayRouteTable(BaseResponse): | |||||||
| 
 | 
 | ||||||
|     def describe_transit_gateway_route_tables(self): |     def describe_transit_gateway_route_tables(self): | ||||||
|         filters = filters_from_querystring(self.querystring) |         filters = filters_from_querystring(self.querystring) | ||||||
|         transit_gateway_ids = ( |         transit_gateway_route_table_ids = ( | ||||||
|             self._get_multi_param("TransitGatewayRouteTableIds") or None |             self._get_multi_param("TransitGatewayRouteTableIds") or None | ||||||
|         ) |         ) | ||||||
|         transit_gateway_route_tables = self.ec2_backend.get_all_transit_gateway_route_tables( |         transit_gateway_route_tables = self.ec2_backend.get_all_transit_gateway_route_tables( | ||||||
|             transit_gateway_ids, filters |             transit_gateway_route_table_ids, filters | ||||||
|         ) |         ) | ||||||
|         template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE) |         template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE) | ||||||
|         return template.render( |         return template.render( | ||||||
| @ -83,6 +83,32 @@ class TransitGatewayRouteTable(BaseResponse): | |||||||
|         template = self.response_template(SEARCH_TRANSIT_GATEWAY_ROUTES_RESPONSE) |         template = self.response_template(SEARCH_TRANSIT_GATEWAY_ROUTES_RESPONSE) | ||||||
|         return template.render(transit_gateway_routes=transit_gateway_routes) |         return template.render(transit_gateway_routes=transit_gateway_routes) | ||||||
| 
 | 
 | ||||||
|  |     def get_transit_gateway_route_table_associations(self): | ||||||
|  |         transit_gateway_route_table_id = self._get_param("TransitGatewayRouteTableId") | ||||||
|  |         filters = filters_from_querystring(self.querystring) | ||||||
|  |         transit_gateway_route_table_associations = self.ec2_backend.get_all_transit_gateway_route_table_associations( | ||||||
|  |             transit_gateway_route_table_id, filters | ||||||
|  |         ) | ||||||
|  |         template = self.response_template( | ||||||
|  |             GET_TRANSIT_GATEWAY_ROUTE_TABLE_ASSOCIATIONS_RESPONSE | ||||||
|  |         ) | ||||||
|  |         return template.render( | ||||||
|  |             transit_gateway_route_table_associations=transit_gateway_route_table_associations | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def get_transit_gateway_route_table_propagations(self): | ||||||
|  |         transit_gateway_route_table_id = self._get_param("TransitGatewayRouteTableId") | ||||||
|  |         filters = filters_from_querystring(self.querystring) | ||||||
|  |         transit_gateway_route_table_propagations = self.ec2_backend.get_all_transit_gateway_route_table_propagations( | ||||||
|  |             transit_gateway_route_table_id, filters | ||||||
|  |         ) | ||||||
|  |         template = self.response_template( | ||||||
|  |             GET_TRANSIT_GATEWAY_ROUTE_TABLE_PROPAGATIONS_RESPONSE | ||||||
|  |         ) | ||||||
|  |         return template.render( | ||||||
|  |             transit_gateway_route_table_propagations=transit_gateway_route_table_propagations | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| CREATE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE = """<CreateTransitGatewayRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | CREATE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE = """<CreateTransitGatewayRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|     <requestId>3a495d25-08d4-466d-822e-477c9b1fc606</requestId> |     <requestId>3a495d25-08d4-466d-822e-477c9b1fc606</requestId> | ||||||
| @ -133,16 +159,12 @@ DESCRIBE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE = """<DescribeTransitGatewayRouteT | |||||||
| DELETE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE = """<DeleteTransitGatewayRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | DELETE_TRANSIT_GATEWAY_ROUTE_TABLE_RESPONSE = """<DeleteTransitGatewayRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|     <requestId>a9a07226-c7b1-4305-9934-0bcfc3ef1c5e</requestId> |     <requestId>a9a07226-c7b1-4305-9934-0bcfc3ef1c5e</requestId> | ||||||
|     <transitGatewayRouteTable> |     <transitGatewayRouteTable> | ||||||
|         {% for transit_gateway_route_table in transit_gateway_route_tables %} |         <creationTime>{{ transit_gateway_route_table.create_time }}</creationTime> | ||||||
|         <item> |         <defaultAssociationRouteTable>{{ transit_gateway_route_table.default_association_route_table }}</defaultAssociationRouteTable> | ||||||
|             <creationTime>{{ transit_gateway_route_table.create_time }}</creationTime> |         <defaultPropagationRouteTable>{{ transit_gateway_route_table.default_propagation_route_table }}</defaultPropagationRouteTable> | ||||||
|             <defaultAssociationRouteTable>{{ transit_gateway_route_table.default_association_route_table }}</defaultAssociationRouteTable> |         <state>{{ transit_gateway_route_table.state }}</state> | ||||||
|             <defaultPropagationRouteTable>{{ transit_gateway_route_table.default_propagation_route_table }}</defaultPropagationRouteTable> |         <transitGatewayId>{{ transit_gateway_route_table.transit_gateway_id }}</transitGatewayId> | ||||||
|             <state>{{ transit_gateway_route_table.state }}</state> |         <transitGatewayRouteTableId>{{ transit_gateway_route_table.id }}</transitGatewayRouteTableId> | ||||||
|             <transitGatewayId>{{ transit_gateway_route_table.transit_gateway_id }}</transitGatewayId> |  | ||||||
|             <transitGatewayRouteTableId>{{ transit_gateway_route_table.id }}</transitGatewayRouteTableId> |  | ||||||
|         </item> |  | ||||||
|         {% endfor %} |  | ||||||
|     </transitGatewayRouteTable> |     </transitGatewayRouteTable> | ||||||
| </DeleteTransitGatewayRouteTableResponse> | </DeleteTransitGatewayRouteTableResponse> | ||||||
| """ | """ | ||||||
| @ -152,9 +174,18 @@ CREATE_TRANSIT_GATEWAY_ROUTE_RESPONSE = """<?xml version="1.0" encoding="UTF-8"? | |||||||
| <CreateTransitGatewayRouteResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | <CreateTransitGatewayRouteResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|     <requestId>072b02ce-df3a-4de6-a20b-6653ae4b91a4</requestId> |     <requestId>072b02ce-df3a-4de6-a20b-6653ae4b91a4</requestId> | ||||||
|     <route> |     <route> | ||||||
|         <destinationCidrBlock>{{ transit_gateway_route_table.routes[destination_cidr_block]['destinationCidrBlock'] }}</destinationCidrBlock> |         <destinationCidrBlock>{{ transit_gateway_route_table.destinationCidrBlock }}</destinationCidrBlock> | ||||||
|         <state>{{ transit_gateway_route_table.routes[destination_cidr_block]['state'] }}</state> |         <state>{{ transit_gateway_route_table.state }}</state> | ||||||
|         <type>{{ transit_gateway_route_table.routes[destination_cidr_block]['type'] }}</type> |         <type>{{ transit_gateway_route_table.type }}</type> | ||||||
|  |         <transitGatewayAttachments> | ||||||
|  |         {% if transit_gateway_route_table.state != 'blackhole' and transit_gateway_route_table.transitGatewayAttachments %} | ||||||
|  |             <item> | ||||||
|  |                 <resourceId>{{ transit_gateway_route_table.transitGatewayAttachments.resourceId }}</resourceId> | ||||||
|  |                 <resourceType>{{ transit_gateway_route_table.transitGatewayAttachments.resourceType }}</resourceType> | ||||||
|  |                 <transitGatewayAttachmentId>{{ transit_gateway_route_table.transitGatewayAttachments.transitGatewayAttachmentId }}</transitGatewayAttachmentId> | ||||||
|  |             </item> | ||||||
|  |         {% endif %} | ||||||
|  |         </transitGatewayAttachments> | ||||||
|     </route> |     </route> | ||||||
| </CreateTransitGatewayRouteResponse> | </CreateTransitGatewayRouteResponse> | ||||||
| """ | """ | ||||||
| @ -163,9 +194,9 @@ DELETE_TRANSIT_GATEWAY_ROUTE_RESPONSE = """<?xml version="1.0" encoding="UTF-8"? | |||||||
| <DeleteTransitGatewayRouteResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | <DeleteTransitGatewayRouteResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|     <requestId>2109d5bb-f874-4f35-b419-4723792a638f</requestId> |     <requestId>2109d5bb-f874-4f35-b419-4723792a638f</requestId> | ||||||
|     <route> |     <route> | ||||||
|         <destinationCidrBlock>{{ transit_gateway_route_table.routes[destination_cidr_block]['destinationCidrBlock'] }}</destinationCidrBlock> |         <destinationCidrBlock>{{ transit_gateway_route_table.routes[destination_cidr_block].destinationCidrBlock }}</destinationCidrBlock> | ||||||
|         <state>{{ transit_gateway_route_table.routes[destination_cidr_block]['state'] }}</state> |         <state>{{ transit_gateway_route_table.routes[destination_cidr_block].state }}</state> | ||||||
|         <type>{{ transit_gateway_route_table.routes[destination_cidr_block]['type'] }}</type> |         <type>{{ transit_gateway_route_table.routes[destination_cidr_block].type }}</type> | ||||||
|     </route> |     </route> | ||||||
| </DeleteTransitGatewayRouteResponse> | </DeleteTransitGatewayRouteResponse> | ||||||
| """ | """ | ||||||
| @ -176,12 +207,49 @@ SEARCH_TRANSIT_GATEWAY_ROUTES_RESPONSE = """<?xml version="1.0" encoding="UTF-8" | |||||||
|     <routeSet> |     <routeSet> | ||||||
|         {% for route in transit_gateway_routes %} |         {% for route in transit_gateway_routes %} | ||||||
|         <item> |         <item> | ||||||
|             <destinationCidrBlock>{{ route['destinationCidrBlock'] }}</destinationCidrBlock> |             <destinationCidrBlock>{{ transit_gateway_routes[route].destinationCidrBlock }}</destinationCidrBlock> | ||||||
|             <state>{{ route['state'] }}</state> |             <state>{{ transit_gateway_routes[route].state }}</state> | ||||||
|             <type>{{ route['type'] }}</type> |             <type>{{ transit_gateway_routes[route].type }}</type> | ||||||
|  |             {% if transit_gateway_routes[route].get('transitGatewayAttachments') %} | ||||||
|  |             <transitGatewayAttachments> | ||||||
|  |                 <item> | ||||||
|  |                     <resourceId>{{ transit_gateway_routes[route].transitGatewayAttachments.resourceId }}</resourceId> | ||||||
|  |                     <resourceType>{{ transit_gateway_routes[route].transitGatewayAttachments.resourceType }}</resourceType> | ||||||
|  |                     <transitGatewayAttachmentId>{{ transit_gateway_routes[route].transitGatewayAttachments.transitGatewayAttachmentId }}</transitGatewayAttachmentId> | ||||||
|  |                 </item> | ||||||
|  |             </transitGatewayAttachments> | ||||||
|  |             {% endif %} | ||||||
|         </item> |         </item> | ||||||
|         {% endfor %} |         {% endfor %} | ||||||
|     </routeSet> |     </routeSet> | ||||||
|     <additionalRoutesAvailable>false</additionalRoutesAvailable> |     <additionalRoutesAvailable>false</additionalRoutesAvailable> | ||||||
| </SearchTransitGatewayRoutesResponse> | </SearchTransitGatewayRoutesResponse> | ||||||
| """ | """ | ||||||
|  | 
 | ||||||
|  | GET_TRANSIT_GATEWAY_ROUTE_TABLE_ASSOCIATIONS_RESPONSE = """<GetTransitGatewayRouteTableAssociationsResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |     <requestId>92fdc91d-c374-4217-b2b4-33f2fb0a2be7</requestId> | ||||||
|  |     <associations> | ||||||
|  |         {% for route_table in transit_gateway_route_table_associations %} | ||||||
|  |         <item> | ||||||
|  |             <resourceId>{{ route_table.route_table_association.resourceId }}</resourceId> | ||||||
|  |             <resourceType>{{ route_table.route_table_association.resourceType }}</resourceType> | ||||||
|  |             <state>{{ route_table.route_table_association.state }}</state> | ||||||
|  |             <transitGatewayAttachmentId>{{ route_table.route_table_association.transitGatewayAttachmentId }}</transitGatewayAttachmentId> | ||||||
|  |         </item> | ||||||
|  |         {% endfor %} | ||||||
|  |     </associations> | ||||||
|  | </GetTransitGatewayRouteTableAssociationsResponse>""" | ||||||
|  | 
 | ||||||
|  | GET_TRANSIT_GATEWAY_ROUTE_TABLE_PROPAGATIONS_RESPONSE = """<GetTransitGatewayRouteTablePropagationsResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/"> | ||||||
|  |     <requestId>541bc42d-9ed9-4aef-a5f7-2ea32fbdec16</requestId> | ||||||
|  |     <transitGatewayRouteTablePropagations> | ||||||
|  |         {% for route_table in transit_gateway_route_table_propagations %} | ||||||
|  |         <item> | ||||||
|  |             <resourceId>{{ route_table.route_table_propagation.resourceId }}</resourceId> | ||||||
|  |             <resourceType>{{ route_table.route_table_propagation.resourceType }}</resourceType> | ||||||
|  |             <state>{{ route_table.route_table_propagation.state }}</state> | ||||||
|  |             <transitGatewayAttachmentId>{{ route_table.route_table_propagation.transitGatewayAttachmentId }}</transitGatewayAttachmentId> | ||||||
|  |         </item> | ||||||
|  |         {% endfor %} | ||||||
|  |     </transitGatewayRouteTablePropagations> | ||||||
|  | </GetTransitGatewayRouteTablePropagationsResponse>""" | ||||||
|  | |||||||
| @ -14,6 +14,21 @@ class TransitGateways(BaseResponse): | |||||||
|         transit_gateway = self.ec2_backend.create_transit_gateway( |         transit_gateway = self.ec2_backend.create_transit_gateway( | ||||||
|             description=description, options=options, tags=tags |             description=description, options=options, tags=tags | ||||||
|         ) |         ) | ||||||
|  | 
 | ||||||
|  |         # creating default route table | ||||||
|  |         transit_gateway_route_table = self.ec2_backend.create_transit_gateway_route_table( | ||||||
|  |             transit_gateway_id=transit_gateway.id, | ||||||
|  |             tags={}, | ||||||
|  |             default_association_route_table=True, | ||||||
|  |             default_propagation_route_table=True, | ||||||
|  |         ) | ||||||
|  |         transit_gateway.options[ | ||||||
|  |             "AssociationDefaultRouteTableId" | ||||||
|  |         ] = transit_gateway_route_table.id | ||||||
|  |         transit_gateway.options[ | ||||||
|  |             "PropagationDefaultRouteTableId" | ||||||
|  |         ] = transit_gateway_route_table.id | ||||||
|  | 
 | ||||||
|         template = self.response_template(CREATE_TRANSIT_GATEWAY_RESPONSE) |         template = self.response_template(CREATE_TRANSIT_GATEWAY_RESPONSE) | ||||||
|         return template.render(transit_gateway=transit_gateway) |         return template.render(transit_gateway=transit_gateway) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -34,3 +34,21 @@ def merge_multiple_dicts(*args): | |||||||
|     for d in args: |     for d in args: | ||||||
|         result.update(d) |         result.update(d) | ||||||
|     return result |     return result | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def filter_resources(resources, filters, attr_pairs): | ||||||
|  |     """ | ||||||
|  |     Used to filter resources. Usually in get and describe apis. | ||||||
|  |     """ | ||||||
|  |     result = resources.copy() | ||||||
|  |     for resource in resources: | ||||||
|  |         for attrs in attr_pairs: | ||||||
|  |             values = filters.get(attrs[0]) or None | ||||||
|  |             if values: | ||||||
|  |                 instance = getattr(resource, attrs[1]) | ||||||
|  |                 if (len(attrs) <= 2 and instance not in values) or ( | ||||||
|  |                     len(attrs) == 3 and instance.get(attrs[2]) not in values | ||||||
|  |                 ): | ||||||
|  |                     result.remove(resource) | ||||||
|  |                     break | ||||||
|  |     return result | ||||||
|  | |||||||
| @ -2,10 +2,7 @@ TestAccAWSEc2TransitGatewayDxGatewayAttachmentDataSource | |||||||
| TestAccAWSEc2TransitGatewayPeeringAttachment | TestAccAWSEc2TransitGatewayPeeringAttachment | ||||||
| TestAccAWSEc2TransitGatewayPeeringAttachmentAccepter | TestAccAWSEc2TransitGatewayPeeringAttachmentAccepter | ||||||
| TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource | TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource | ||||||
| TestAccAWSEc2TransitGatewayRoute |  | ||||||
| TestAccAWSEc2TransitGatewayRouteTableAssociation | TestAccAWSEc2TransitGatewayRouteTableAssociation | ||||||
| TestAccAWSEc2TransitGatewayRouteTablePropagation |  | ||||||
| TestAccAWSEc2TransitGatewayVpcAttachment | TestAccAWSEc2TransitGatewayVpcAttachment | ||||||
| TestAccAWSEc2TransitGatewayVpcAttachmentDataSource |  | ||||||
| TestAccAWSFms | TestAccAWSFms | ||||||
| TestAccAWSIAMRolePolicy | TestAccAWSIAMRolePolicy | ||||||
| @ -26,10 +26,18 @@ TestAccAWSEc2InstanceTypeOfferingDataSource | |||||||
| TestAccAWSEc2InstanceTypeOfferingsDataSource | TestAccAWSEc2InstanceTypeOfferingsDataSource | ||||||
| TestAccAWSEc2Tag | TestAccAWSEc2Tag | ||||||
| TestAccAWSEc2TransitGateway | TestAccAWSEc2TransitGateway | ||||||
|  | TestAccAWSEc2TransitGatewayRoute | ||||||
| TestAccAWSEc2TransitGatewayDataSource | TestAccAWSEc2TransitGatewayDataSource | ||||||
| TestAccAWSEc2TransitGatewayRouteTable | TestAccAWSEc2TransitGatewayRouteTable | ||||||
| TestAccAWSEc2TransitGatewayRouteTableDataSource | TestAccAWSEc2TransitGatewayRouteTableDataSource | ||||||
|  | TestAccAWSEc2TransitGatewayRouteTablePropagation | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachment_basic | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachment_disappears | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachment_ApplianceModeSupport | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachment_DnsSupport | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachment_SharedTransitGateway | ||||||
| TestAccAWSEc2TransitGatewayVpcAttachmentAccepter | TestAccAWSEc2TransitGatewayVpcAttachmentAccepter | ||||||
|  | TestAccAWSEc2TransitGatewayVpcAttachmentDataSource | ||||||
| TestAccAWSEc2TransitGatewayVpnAttachmentDataSource | TestAccAWSEc2TransitGatewayVpnAttachmentDataSource | ||||||
| TestAccAWSElasticBeanstalkSolutionStackDataSource | TestAccAWSElasticBeanstalkSolutionStackDataSource | ||||||
| TestAccAWSElbHostedZoneId | TestAccAWSElbHostedZoneId | ||||||
|  | |||||||
| @ -194,8 +194,7 @@ def test_create_transit_gateway_route_table(): | |||||||
|     table.should.have.key("Tags").equals([]) |     table.should.have.key("Tags").equals([]) | ||||||
| 
 | 
 | ||||||
|     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] |     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] | ||||||
|     tables.should.have.length_of(1) |     tables.should.have.length_of(2) | ||||||
|     tables[0].should.equal(table) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| @ -235,14 +234,16 @@ def test_delete_transit_gateway_route_table(): | |||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] |     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] | ||||||
|     tables.should.have.length_of(1) |     tables.should.have.length_of(2) | ||||||
| 
 | 
 | ||||||
|     ec2.delete_transit_gateway_route_table( |     table = ec2.delete_transit_gateway_route_table( | ||||||
|         TransitGatewayRouteTableId=table["TransitGatewayRouteTableId"] |         TransitGatewayRouteTableId=table["TransitGatewayRouteTableId"] | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  |     table["TransitGatewayRouteTable"].should.have.key("State").equals("deleted") | ||||||
|  | 
 | ||||||
|     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] |     tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] | ||||||
|     tables.should.have.length_of(0) |     tables.should.have.length_of(2) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| @ -278,7 +279,7 @@ def test_create_transit_gateway_route(): | |||||||
|     )["Route"] |     )["Route"] | ||||||
| 
 | 
 | ||||||
|     route.should.have.key("DestinationCidrBlock").equal("0.0.0.0") |     route.should.have.key("DestinationCidrBlock").equal("0.0.0.0") | ||||||
|     route.should.have.key("Type").equal("TODO") |     route.should.have.key("Type").equal("static") | ||||||
|     route.should.have.key("State").equal("active") |     route.should.have.key("State").equal("active") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -299,7 +300,7 @@ def test_create_transit_gateway_route_as_blackhole(): | |||||||
|     )["Route"] |     )["Route"] | ||||||
| 
 | 
 | ||||||
|     route.should.have.key("DestinationCidrBlock").equal("192.168.0.1") |     route.should.have.key("DestinationCidrBlock").equal("192.168.0.1") | ||||||
|     route.should.have.key("Type").equal("TODO") |     route.should.have.key("Type").equal("static") | ||||||
|     route.should.have.key("State").equal("blackhole") |     route.should.have.key("State").equal("blackhole") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -329,7 +330,7 @@ def test_search_transit_gateway_routes_by_state(): | |||||||
|     )["Routes"] |     )["Routes"] | ||||||
| 
 | 
 | ||||||
|     routes.should.equal( |     routes.should.equal( | ||||||
|         [{"DestinationCidrBlock": "192.168.0.0", "Type": "TODO", "State": "active"}] |         [{"DestinationCidrBlock": "192.168.0.0", "Type": "static", "State": "active"}] | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     routes = ec2.search_transit_gateway_routes( |     routes = ec2.search_transit_gateway_routes( | ||||||
| @ -338,7 +339,13 @@ def test_search_transit_gateway_routes_by_state(): | |||||||
|     )["Routes"] |     )["Routes"] | ||||||
| 
 | 
 | ||||||
|     routes.should.equal( |     routes.should.equal( | ||||||
|         [{"DestinationCidrBlock": "192.168.0.1", "Type": "TODO", "State": "blackhole"}] |         [ | ||||||
|  |             { | ||||||
|  |                 "DestinationCidrBlock": "192.168.0.1", | ||||||
|  |                 "Type": "static", | ||||||
|  |                 "State": "blackhole", | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     routes = ec2.search_transit_gateway_routes( |     routes = ec2.search_transit_gateway_routes( | ||||||
| @ -371,7 +378,7 @@ def test_delete_transit_gateway_route(): | |||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     response["Route"].should.equal( |     response["Route"].should.equal( | ||||||
|         {"DestinationCidrBlock": "192.168.0.0", "Type": "TODO", "State": "deleted"} |         {"DestinationCidrBlock": "192.168.0.0", "Type": "static", "State": "deleted"} | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     routes = ec2.search_transit_gateway_routes( |     routes = ec2.search_transit_gateway_routes( | ||||||
| @ -380,7 +387,7 @@ def test_delete_transit_gateway_route(): | |||||||
|     )["Routes"] |     )["Routes"] | ||||||
| 
 | 
 | ||||||
|     routes.should.equal( |     routes.should.equal( | ||||||
|         [{"DestinationCidrBlock": "192.168.0.1", "Type": "TODO", "State": "active"}] |         [{"DestinationCidrBlock": "192.168.0.1", "Type": "static", "State": "active"}] | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user