added support for egress-only-internet-gateway (#4196)

This commit is contained in:
Macwan Nevil 2021-08-19 11:09:06 +05:30 committed by GitHub
parent b4f02f3436
commit a93756c69a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 151 additions and 1 deletions

View File

@ -398,6 +398,14 @@ class InvalidParameterValueErrorUnknownAttribute(EC2ClientError):
)
class InvalidGatewayIDError(EC2ClientError):
def __init__(self, gateway_id):
super(InvalidGatewayIDError, self).__init__(
"InvalidGatewayID.NotFound",
"The eigw ID '{0}' does not exist".format(gateway_id),
)
class InvalidInternetGatewayIdError(EC2ClientError):
def __init__(self, internet_gateway_id):
super(InvalidInternetGatewayIdError, self).__init__(

View File

@ -111,6 +111,7 @@ from .exceptions import (
InvalidAssociationIDIamProfileAssociationError,
InvalidVpcEndPointIdError,
InvalidTaggableResourceType,
InvalidGatewayIDError,
)
from .utils import (
EC2_RESOURCE_TO_PREFIX,
@ -123,6 +124,7 @@ from .utils import (
random_eni_id,
random_instance_id,
random_internet_gateway_id,
random_egress_only_internet_gateway_id,
random_ip,
random_ipv6_cidr,
random_transit_gateway_attachment_id,
@ -4792,6 +4794,52 @@ class InternetGatewayBackend(object):
return self.describe_internet_gateways(internet_gateway_ids=igw_ids)[0]
class EgressOnlyInternetGateway(TaggedEC2Resource):
def __init__(self, ec2_backend, vpc_id, tags=None):
self.id = random_egress_only_internet_gateway_id()
self.ec2_backend = ec2_backend
self.vpc_id = vpc_id
self.state = "attached"
self.add_tags(tags or {})
@property
def physical_resource_id(self):
return self.id
class EgressOnlyInternetGatewayBackend(object):
def __init__(self):
self.egress_only_internet_gateway_backend = {}
super(EgressOnlyInternetGatewayBackend, self).__init__()
def create_egress_only_internet_gateway(self, vpc_id, tags=None):
vpc = self.get_vpc(vpc_id)
if not vpc:
raise InvalidVPCIdError(vpc_id)
egress_only_igw = EgressOnlyInternetGateway(self, vpc_id, tags)
self.egress_only_internet_gateway_backend[egress_only_igw.id] = egress_only_igw
return egress_only_igw
def describe_egress_only_internet_gateways(self, ids=None, filters=None):
# TODO: support filtering based on tag
egress_only_igws = list(self.egress_only_internet_gateway_backend.values())
if ids:
egress_only_igws = [
egress_only_igw
for egress_only_igw in egress_only_igws
if egress_only_igw.id in ids
]
return egress_only_igws
def delete_egress_only_internet_gateway(self, id):
egress_only_igw = self.egress_only_internet_gateway_backend.get(id)
if not egress_only_igw:
raise InvalidGatewayIDError(id)
if egress_only_igw:
self.egress_only_internet_gateway_backend.pop(id)
class VPCGatewayAttachment(CloudFormationModel):
def __init__(self, gateway_id, vpc_id):
self.gateway_id = gateway_id
@ -7308,6 +7356,7 @@ class EC2Backend(
RouteTableBackend,
RouteBackend,
InternetGatewayBackend,
EgressOnlyInternetGatewayBackend,
VPCGatewayAttachmentBackend,
SpotFleetBackend,
SpotRequestBackend,

View File

@ -12,6 +12,7 @@ from .elastic_network_interfaces import ElasticNetworkInterfaces
from .general import General
from .instances import InstanceResponse
from .internet_gateways import InternetGateways
from .egress_only_internet_gateways import EgressOnlyInternetGateway
from .ip_addresses import IPAddresses
from .key_pairs import KeyPairs
from .launch_templates import LaunchTemplates
@ -53,6 +54,7 @@ class EC2Response(
General,
InstanceResponse,
InternetGateways,
EgressOnlyInternetGateway,
IPAddresses,
KeyPairs,
LaunchTemplates,

View File

@ -0,0 +1,83 @@
from moto.core.responses import BaseResponse
from moto.ec2.utils import filters_from_querystring, add_tag_specification
class EgressOnlyInternetGateway(BaseResponse):
def create_egress_only_internet_gateway(self):
vpc_id = self._get_param("VpcId")
tags = self._get_multi_param("TagSpecification")
tags = add_tag_specification(tags)
egress_only_igw = self.ec2_backend.create_egress_only_internet_gateway(
vpc_id=vpc_id, tags=tags
)
template = self.response_template(CREATE_EGRESS_ONLY_IGW_RESPONSE)
return template.render(egress_only_igw=egress_only_igw)
def describe_egress_only_internet_gateways(self):
egress_only_igw_ids = self._get_multi_param("EgressOnlyInternetGatewayId")
filters = filters_from_querystring(self.querystring)
egress_only_igws = self.ec2_backend.describe_egress_only_internet_gateways(
egress_only_igw_ids, filters,
)
template = self.response_template(DESCRIBE_EGRESS_ONLY_IGW_RESPONSE)
return template.render(egress_only_igws=egress_only_igws)
def delete_egress_only_internet_gateway(self):
egress_only_igw_id = self._get_param("EgressOnlyInternetGatewayId")
self.ec2_backend.delete_egress_only_internet_gateway(id=egress_only_igw_id)
template = self.response_template(DELETE_EGRESS_ONLY_IGW_RESPONSE)
return template.render()
CREATE_EGRESS_ONLY_IGW_RESPONSE = """<CreateEgressOnlyInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>c617595f-6c29-4a00-a941-example</requestId>
<egressOnlyInternetGateway>
<attachmentSet>
<item>
<state>{{ egress_only_igw.state }}</state>
<vpcId>{{ egress_only_igw.vpc_id }}</vpcId>
</item>
</attachmentSet>
<egressOnlyInternetGatewayId>{{ egress_only_igw.id }}</egressOnlyInternetGatewayId>
<tagSet>
{% for tag in egress_only_igw.get_tags() %}
<item>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</egressOnlyInternetGateway>
</CreateEgressOnlyInternetGatewayResponse>
"""
DESCRIBE_EGRESS_ONLY_IGW_RESPONSE = """<DescribeEgressOnlyInternetGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>ec441b4c-357f-4483-b4a7-example</requestId>
<egressOnlyInternetGatewaySet>
{% for egress_only_igw in egress_only_igws %}
<item>
<attachmentSet>
<item>
<state>{{ egress_only_igw.state }}</state>
<vpcId>{{ egress_only_igw.vpc_id }}</vpcId>
</item>
</attachmentSet>
<egressOnlyInternetGatewayId>{{ egress_only_igw.id }}</egressOnlyInternetGatewayId>
<tagSet>
{% for tag in egress_only_igw.get_tags() %}
<item>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</item>
{% endfor %}
</egressOnlyInternetGatewaySet>
</DescribeEgressOnlyInternetGatewaysResponse>"""
DELETE_EGRESS_ONLY_IGW_RESPONSE = """<DeleteEgressOnlyInternetGateway xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<returnCode>true</returnCode>
</DeleteEgressOnlyInternetGateway>"""

View File

@ -23,6 +23,7 @@ EC2_RESOURCE_TO_PREFIX = {
"image": "ami",
"instance": "i",
"internet-gateway": "igw",
"egress-only-internet-gateway": "eigw",
"launch-template": "lt",
"nat-gateway": "nat",
"network-acl": "acl",
@ -153,6 +154,12 @@ def random_internet_gateway_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["internet-gateway"])
def random_egress_only_internet_gateway_id():
return random_id(
prefix=EC2_RESOURCE_TO_PREFIX["egress-only-internet-gateway"], size=17
)
def random_route_table_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table"])

View File

@ -86,4 +86,5 @@ TestAccAWSRouteTable_IPv4_To_NatGateway
TestAccAWSRouteTable_IPv4_To_TransitGateway
TestAccAWSRouteTable_disappears
TestAccAWSRouteTable_basic
TestAccAwsEc2ManagedPrefixList
TestAccAwsEc2ManagedPrefixList
TestAccAWSEgressOnlyInternetGateway