From 39314906bc4750cfb45edf79c53536bcf691898d Mon Sep 17 00:00:00 2001 From: Macwan Nevil Date: Sun, 12 Sep 2021 02:00:15 +0530 Subject: [PATCH] added support for carrier gateway (#4280) --- moto/ec2/exceptions.py | 8 +++ moto/ec2/models.py | 63 +++++++++++++++++ moto/ec2/responses/__init__.py | 2 + moto/ec2/responses/carrier_gateways.py | 94 ++++++++++++++++++++++++++ moto/ec2/utils.py | 5 ++ tests/terraform-tests.success.txt | 1 + 6 files changed, 173 insertions(+) create mode 100644 moto/ec2/responses/carrier_gateways.py diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py index 4811a9f8b..bec3ffc41 100644 --- a/moto/ec2/exceptions.py +++ b/moto/ec2/exceptions.py @@ -703,3 +703,11 @@ class InvalidSubnetCidrBlockAssociationID(EC2ClientError): association_id ), ) + + +class InvalidCarrierGatewayID(EC2ClientError): + def __init__(self, carrier_gateway_id): + super(InvalidCarrierGatewayID, self).__init__( + "InvalidCarrierGatewayID.NotFound", + "The CarrierGateway ID '{0}' does not exist".format(carrier_gateway_id), + ) diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 56514ed6f..65d89a2bd 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -116,6 +116,7 @@ from .exceptions import ( InvalidVpcEndPointIdError, InvalidTaggableResourceType, InvalidGatewayIDError, + InvalidCarrierGatewayID, ) from .utils import ( EC2_RESOURCE_TO_PREFIX, @@ -160,6 +161,7 @@ from .utils import ( random_vpc_cidr_association_id, random_vpc_peering_connection_id, random_iam_instance_profile_association_id, + random_carrier_gateway_id, generic_filter, is_valid_resource_id, get_prefix, @@ -5344,6 +5346,66 @@ class InternetGatewayBackend(object): return self.describe_internet_gateways(internet_gateway_ids=igw_ids)[0] +class CarrierGateway(TaggedEC2Resource): + def __init__(self, ec2_backend, vpc_id, tags=None): + self.id = random_carrier_gateway_id() + self.ec2_backend = ec2_backend + self.vpc_id = vpc_id + self.state = "available" + self.add_tags(tags or {}) + + @property + def physical_resource_id(self): + return self.id + + @property + def owner_id(self): + return ACCOUNT_ID + + +class CarrierGatewayBackend(object): + def __init__(self): + self.carrier_gateways = {} + super(CarrierGatewayBackend, self).__init__() + + def create_carrier_gateway(self, vpc_id, tags=None): + vpc = self.get_vpc(vpc_id) + if not vpc: + raise InvalidVPCIdError(vpc_id) + carrier_gateway = CarrierGateway(self, vpc_id, tags) + self.carrier_gateways[carrier_gateway.id] = carrier_gateway + return carrier_gateway + + def delete_carrier_gateway(self, id): + if not self.carrier_gateways.get(id): + raise InvalidCarrierGatewayID(id) + carrier_gateway = self.carrier_gateways.pop(id) + carrier_gateway.state = "deleted" + return carrier_gateway + + def describe_carrier_gateways(self, ids=None, filters=None): + carrier_gateways = list(self.carrier_gateways.values()) + + if ids: + carrier_gateways = [ + carrier_gateway + for carrier_gateway in carrier_gateways + if carrier_gateway.id in ids + ] + + attr_pairs = ( + ("carrier-gateway-id", "id"), + ("state", "state"), + ("vpc-id", "vpc_id"), + ("owner-id", "owner_id"), + ) + + result = carrier_gateways + if filters: + result = filter_resources(carrier_gateways, filters, attr_pairs) + return result + + class EgressOnlyInternetGateway(TaggedEC2Resource): def __init__(self, ec2_backend, vpc_id, tags=None): self.id = random_egress_only_internet_gateway_id() @@ -7962,6 +8024,7 @@ class EC2Backend( TransitGatewayRelationsBackend, LaunchTemplateBackend, IamInstanceProfileAssociationBackend, + CarrierGatewayBackend, ): def __init__(self, region_name): self.region_name = region_name diff --git a/moto/ec2/responses/__init__.py b/moto/ec2/responses/__init__.py index 5368062b8..008b81f2a 100644 --- a/moto/ec2/responses/__init__.py +++ b/moto/ec2/responses/__init__.py @@ -39,6 +39,7 @@ from .transit_gateways import TransitGateways from .transit_gateway_route_tables import TransitGatewayRouteTable from .transit_gateway_attachments import TransitGatewayAttachment from .iam_instance_profiles import IamInstanceProfiles +from .carrier_gateways import CarrierGateway class EC2Response( @@ -81,6 +82,7 @@ class EC2Response( TransitGatewayRouteTable, TransitGatewayAttachment, IamInstanceProfiles, + CarrierGateway, ): @property def ec2_backend(self): diff --git a/moto/ec2/responses/carrier_gateways.py b/moto/ec2/responses/carrier_gateways.py new file mode 100644 index 000000000..f55467825 --- /dev/null +++ b/moto/ec2/responses/carrier_gateways.py @@ -0,0 +1,94 @@ +from moto.core.responses import BaseResponse +from moto.ec2.utils import filters_from_querystring, add_tag_specification + + +class CarrierGateway(BaseResponse): + def create_carrier_gateway(self): + vpc_id = self._get_param("VpcId") + tags = self._get_multi_param("TagSpecification") + tags = add_tag_specification(tags) + + carrier_gateway = self.ec2_backend.create_carrier_gateway( + vpc_id=vpc_id, tags=tags + ) + template = self.response_template(CREATE_CARRIER_GATEWAY_RESPONSE) + return template.render(carrier_gateway=carrier_gateway) + + def delete_carrier_gateway(self): + carrier_gateway_id = self._get_param("CarrierGatewayId") + + carrier_gateway = self.ec2_backend.delete_carrier_gateway(carrier_gateway_id) + template = self.response_template(DELETE_CARRIER_GATEWAY_RESPONSE) + return template.render(carrier_gateway=carrier_gateway) + + def describe_carrier_gateways(self): + carrier_gateway_ids = self._get_multi_param("CarrierGatewayId") + filters = filters_from_querystring(self.querystring) + + carrier_gateways = self.ec2_backend.describe_carrier_gateways( + carrier_gateway_ids, filters + ) + template = self.response_template(DESCRIBE_CARRIER_GATEWAYS_RESPONSE) + return template.render(carrier_gateways=carrier_gateways) + + +CREATE_CARRIER_GATEWAY_RESPONSE = """ + c617595f-6c29-4a00-a941-example + + {{ carrier_gateway.state }} + {{ carrier_gateway.vpc_id }} + {{ carrier_gateway.id }} + {{ carrier_gateway.owner_id }} + + {% for tag in carrier_gateway.get_tags() %} + + {{ tag.key }} + {{ tag.value }} + + {% endfor %} + + + +""" + +DELETE_CARRIER_GATEWAY_RESPONSE = """ + c617595f-6c29-4a00-a941-example + + {{ carrier_gateway.state }} + {{ carrier_gateway.vpc_id }} + {{ carrier_gateway.id }} + {{ carrier_gateway.owner_id }} + + {% for tag in carrier_gateway.get_tags() %} + + {{ tag.key }} + {{ tag.value }} + + {% endfor %} + + + +""" + +DESCRIBE_CARRIER_GATEWAYS_RESPONSE = """ + 151283df-f7dc-4317-89b4-01c9888b1d45 + + {% for carrier_gateway in carrier_gateways %} + + {{ carrier_gateway.state }} + {{ carrier_gateway.vpc_id }} + {{ carrier_gateway.id }} + {{ carrier_gateway.owner_id }} + + {% for tag in carrier_gateway.get_tags() %} + + {{ tag.key }} + {{ tag.value }} + + {% endfor %} + + + {% endfor %} + + +""" diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index 89c28ce29..d230af37b 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -52,6 +52,7 @@ EC2_RESOURCE_TO_PREFIX = { "vpn-connection": "vpn", "vpn-gateway": "vgw", "iam-instance-profile-association": "iip-assoc", + "carrier-gateway": "cagw", } @@ -220,6 +221,10 @@ def random_iam_instance_profile_association_id(): return random_id(prefix=EC2_RESOURCE_TO_PREFIX["iam-instance-profile-association"]) +def random_carrier_gateway_id(): + return random_id(prefix=EC2_RESOURCE_TO_PREFIX["carrier-gateway"], size=17) + + def random_public_ip(): return "54.214.{0}.{1}".format(random.choice(range(255)), random.choice(range(255))) diff --git a/tests/terraform-tests.success.txt b/tests/terraform-tests.success.txt index 4a8aa6bdd..18080f276 100644 --- a/tests/terraform-tests.success.txt +++ b/tests/terraform-tests.success.txt @@ -123,3 +123,4 @@ TestAccAWSInternetGateway TestAccAWSSecurityGroupRule_ TestAccAWSVpnGateway TestAccAWSVpnGatewayAttachment +TestAccAWSEc2CarrierGateway \ No newline at end of file