Merge pull request #553 from spulec/feature/nat-gateway
Implement NAT Gateways
This commit is contained in:
commit
9c3b0fb5cf
@ -26,6 +26,7 @@ MODEL_MAP = {
|
|||||||
"AWS::EC2::EIP": ec2_models.ElasticAddress,
|
"AWS::EC2::EIP": ec2_models.ElasticAddress,
|
||||||
"AWS::EC2::Instance": ec2_models.Instance,
|
"AWS::EC2::Instance": ec2_models.Instance,
|
||||||
"AWS::EC2::InternetGateway": ec2_models.InternetGateway,
|
"AWS::EC2::InternetGateway": ec2_models.InternetGateway,
|
||||||
|
"AWS::EC2::NatGateway": ec2_models.NatGateway,
|
||||||
"AWS::EC2::NetworkInterface": ec2_models.NetworkInterface,
|
"AWS::EC2::NetworkInterface": ec2_models.NetworkInterface,
|
||||||
"AWS::EC2::Route": ec2_models.Route,
|
"AWS::EC2::Route": ec2_models.Route,
|
||||||
"AWS::EC2::RouteTable": ec2_models.RouteTable,
|
"AWS::EC2::RouteTable": ec2_models.RouteTable,
|
||||||
|
@ -15,6 +15,7 @@ from boto.ec2.launchspecification import LaunchSpecification
|
|||||||
|
|
||||||
from moto.core import BaseBackend
|
from moto.core import BaseBackend
|
||||||
from moto.core.models import Model
|
from moto.core.models import Model
|
||||||
|
from moto.core.utils import iso_8601_datetime_with_milliseconds
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
EC2ClientError,
|
EC2ClientError,
|
||||||
DependencyViolationError,
|
DependencyViolationError,
|
||||||
@ -70,6 +71,7 @@ from .utils import (
|
|||||||
random_instance_id,
|
random_instance_id,
|
||||||
random_internet_gateway_id,
|
random_internet_gateway_id,
|
||||||
random_ip,
|
random_ip,
|
||||||
|
random_nat_gateway_id,
|
||||||
random_key_pair,
|
random_key_pair,
|
||||||
random_private_ip,
|
random_private_ip,
|
||||||
random_public_ip,
|
random_public_ip,
|
||||||
@ -2955,6 +2957,70 @@ class CustomerGatewayBackend(object):
|
|||||||
return deleted
|
return deleted
|
||||||
|
|
||||||
|
|
||||||
|
class NatGateway(object):
|
||||||
|
|
||||||
|
def __init__(self, backend, subnet_id, allocation_id):
|
||||||
|
# public properties
|
||||||
|
self.id = random_nat_gateway_id()
|
||||||
|
self.subnet_id = subnet_id
|
||||||
|
self.allocation_id = allocation_id
|
||||||
|
self.state = 'available'
|
||||||
|
self.private_ip = random_private_ip()
|
||||||
|
|
||||||
|
# protected properties
|
||||||
|
self._created_at = datetime.utcnow()
|
||||||
|
self._backend = backend
|
||||||
|
# NOTE: this is the core of NAT Gateways creation
|
||||||
|
self._eni = self._backend.create_network_interface(backend.get_subnet(self.subnet_id), self.private_ip)
|
||||||
|
|
||||||
|
# associate allocation with ENI
|
||||||
|
self._backend.associate_address(eni=self._eni, allocation_id=self.allocation_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vpc_id(self):
|
||||||
|
subnet = self._backend.get_subnet(self.subnet_id)
|
||||||
|
return subnet.vpc_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def create_time(self):
|
||||||
|
return iso_8601_datetime_with_milliseconds(self._created_at)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def network_interface_id(self):
|
||||||
|
return self._eni.id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_ip(self):
|
||||||
|
eips = self._backend.address_by_allocation([self.allocation_id])
|
||||||
|
return eips[0].public_ip
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
||||||
|
ec2_backend = ec2_backends[region_name]
|
||||||
|
nat_gateway = ec2_backend.create_nat_gateway(
|
||||||
|
cloudformation_json['Properties']['SubnetId'],
|
||||||
|
cloudformation_json['Properties']['AllocationId'],
|
||||||
|
)
|
||||||
|
return nat_gateway
|
||||||
|
|
||||||
|
|
||||||
|
class NatGatewayBackend(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.nat_gateways = {}
|
||||||
|
|
||||||
|
def get_all_nat_gateways(self, filters):
|
||||||
|
return self.nat_gateways.values()
|
||||||
|
|
||||||
|
def create_nat_gateway(self, subnet_id, allocation_id):
|
||||||
|
nat_gateway = NatGateway(self, subnet_id, allocation_id)
|
||||||
|
self.nat_gateways[nat_gateway.id] = nat_gateway
|
||||||
|
return nat_gateway
|
||||||
|
|
||||||
|
def delete_nat_gateway(self, nat_gateway_id):
|
||||||
|
return self.nat_gateways.pop(nat_gateway_id)
|
||||||
|
|
||||||
|
|
||||||
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
||||||
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
|
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
|
||||||
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
|
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
|
||||||
@ -2963,7 +3029,8 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
|||||||
RouteTableBackend, RouteBackend, InternetGatewayBackend,
|
RouteTableBackend, RouteBackend, InternetGatewayBackend,
|
||||||
VPCGatewayAttachmentBackend, SpotRequestBackend,
|
VPCGatewayAttachmentBackend, SpotRequestBackend,
|
||||||
ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend,
|
ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend,
|
||||||
NetworkAclBackend, VpnGatewayBackend, CustomerGatewayBackend):
|
NetworkAclBackend, VpnGatewayBackend, CustomerGatewayBackend,
|
||||||
|
NatGatewayBackend):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(EC2Backend, self).__init__()
|
super(EC2Backend, self).__init__()
|
||||||
|
@ -29,6 +29,7 @@ from .vpcs import VPCs
|
|||||||
from .vpc_peering_connections import VPCPeeringConnections
|
from .vpc_peering_connections import VPCPeeringConnections
|
||||||
from .vpn_connections import VPNConnections
|
from .vpn_connections import VPNConnections
|
||||||
from .windows import Windows
|
from .windows import Windows
|
||||||
|
from .nat_gateways import NatGateways
|
||||||
|
|
||||||
|
|
||||||
class EC2Response(
|
class EC2Response(
|
||||||
@ -61,6 +62,7 @@ class EC2Response(
|
|||||||
VPCPeeringConnections,
|
VPCPeeringConnections,
|
||||||
VPNConnections,
|
VPNConnections,
|
||||||
Windows,
|
Windows,
|
||||||
|
NatGateways,
|
||||||
):
|
):
|
||||||
@property
|
@property
|
||||||
def ec2_backend(self):
|
def ec2_backend(self):
|
||||||
|
73
moto/ec2/responses/nat_gateways.py
Normal file
73
moto/ec2/responses/nat_gateways.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from moto.core.responses import BaseResponse
|
||||||
|
from moto.ec2.utils import filters_from_querystring
|
||||||
|
|
||||||
|
|
||||||
|
class NatGateways(BaseResponse):
|
||||||
|
|
||||||
|
def create_nat_gateway(self):
|
||||||
|
subnet_id = self._get_param('SubnetId')
|
||||||
|
allocation_id = self._get_param('AllocationId')
|
||||||
|
nat_gateway = self.ec2_backend.create_nat_gateway(subnet_id=subnet_id, allocation_id=allocation_id)
|
||||||
|
template = self.response_template(CREATE_NAT_GATEWAY)
|
||||||
|
return template.render(nat_gateway=nat_gateway)
|
||||||
|
|
||||||
|
def delete_nat_gateway(self):
|
||||||
|
nat_gateway_id = self._get_param('NatGatewayId')
|
||||||
|
nat_gateway = self.ec2_backend.delete_nat_gateway(nat_gateway_id)
|
||||||
|
template = self.response_template(DELETE_NAT_GATEWAY_RESPONSE)
|
||||||
|
return template.render(nat_gateway=nat_gateway)
|
||||||
|
|
||||||
|
def describe_nat_gateways(self):
|
||||||
|
filters = filters_from_querystring(self.querystring)
|
||||||
|
nat_gateways = self.ec2_backend.get_all_nat_gateways(filters)
|
||||||
|
template = self.response_template(DESCRIBE_NAT_GATEWAYS_RESPONSE)
|
||||||
|
return template.render(nat_gateways=nat_gateways)
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIBE_NAT_GATEWAYS_RESPONSE = """<DescribeNatGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2015-10-01/">
|
||||||
|
<requestId>bfed02c6-dae9-47c0-86a2-example</requestId>
|
||||||
|
<natGatewaySet>
|
||||||
|
{% for nat_gateway in nat_gateways %}
|
||||||
|
<item>
|
||||||
|
<subnetId>{{ nat_gateway.subnet_id }}</subnetId>
|
||||||
|
<natGatewayAddressSet>
|
||||||
|
<item>
|
||||||
|
<networkInterfaceId>{{ nat_gateway.network_interface_id }}</networkInterfaceId>
|
||||||
|
<publicIp>{{ nat_gateway.public_ip }}</publicIp>
|
||||||
|
<allocationId>{{ nat_gateway.allocation_id }}</allocationId>
|
||||||
|
<privateIp>{{ nat_gateway.private_ip }}</privateIp>
|
||||||
|
</item>
|
||||||
|
</natGatewayAddressSet>
|
||||||
|
<createTime>{{ nat_gateway.create_time }}</createTime>
|
||||||
|
<vpcId>{{ nat_gateway.vpc_id }}</vpcId>
|
||||||
|
<natGatewayId>{{ nat_gateway.id }}</natGatewayId>
|
||||||
|
<state>{{ nat_gateway.state }}</state>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</natGatewaySet>
|
||||||
|
</DescribeNatGatewaysResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
CREATE_NAT_GATEWAY = """<CreateNatGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2015-10-01/">
|
||||||
|
<requestId>1b74dc5c-bcda-403f-867d-example</requestId>
|
||||||
|
<natGateway>
|
||||||
|
<subnetId>{{ nat_gateway.subnet_id }}</subnetId>
|
||||||
|
<natGatewayAddressSet>
|
||||||
|
<item>
|
||||||
|
<allocationId>{{ nat_gateway.allocation_id }}</allocationId>
|
||||||
|
</item>
|
||||||
|
</natGatewayAddressSet>
|
||||||
|
<createTime>{{ nat_gateway.create_time }}</createTime>
|
||||||
|
<vpcId>{{ nat_gateway.vpc_id }}</vpcId>
|
||||||
|
<natGatewayId>{{ nat_gateway.id }}</natGatewayId>
|
||||||
|
<state>{{ nat_gateway.state }}</state>
|
||||||
|
</natGateway>
|
||||||
|
</CreateNatGatewayResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
DELETE_NAT_GATEWAY_RESPONSE = """<DeleteNatGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2015-10-01/">
|
||||||
|
<requestId>741fc8ab-6ebe-452b-b92b-example</requestId>
|
||||||
|
<natGatewayId>{{ nat_gateway.id }}</natGatewayId>
|
||||||
|
</DeleteNatGatewayResponse>"""
|
@ -9,6 +9,7 @@ EC2_RESOURCE_TO_PREFIX = {
|
|||||||
'image': 'ami',
|
'image': 'ami',
|
||||||
'instance': 'i',
|
'instance': 'i',
|
||||||
'internet-gateway': 'igw',
|
'internet-gateway': 'igw',
|
||||||
|
'nat-gateway': 'nat',
|
||||||
'network-acl': 'acl',
|
'network-acl': 'acl',
|
||||||
'network-acl-subnet-assoc': 'aclassoc',
|
'network-acl-subnet-assoc': 'aclassoc',
|
||||||
'network-interface': 'eni',
|
'network-interface': 'eni',
|
||||||
@ -33,8 +34,7 @@ EC2_RESOURCE_TO_PREFIX = {
|
|||||||
EC2_PREFIX_TO_RESOURCE = dict((v, k) for (k, v) in EC2_RESOURCE_TO_PREFIX.items())
|
EC2_PREFIX_TO_RESOURCE = dict((v, k) for (k, v) in EC2_RESOURCE_TO_PREFIX.items())
|
||||||
|
|
||||||
|
|
||||||
def random_id(prefix=''):
|
def random_id(prefix='', size=8):
|
||||||
size = 8
|
|
||||||
chars = list(range(10)) + ['a', 'b', 'c', 'd', 'e', 'f']
|
chars = list(range(10)) + ['a', 'b', 'c', 'd', 'e', 'f']
|
||||||
|
|
||||||
resource_id = ''.join(six.text_type(random.choice(chars)) for x in range(size))
|
resource_id = ''.join(six.text_type(random.choice(chars)) for x in range(size))
|
||||||
@ -133,6 +133,10 @@ def random_eni_attach_id():
|
|||||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['network-interface-attachment'])
|
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['network-interface-attachment'])
|
||||||
|
|
||||||
|
|
||||||
|
def random_nat_gateway_id():
|
||||||
|
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['nat-gateway'], size=17)
|
||||||
|
|
||||||
|
|
||||||
def random_public_ip():
|
def random_public_ip():
|
||||||
return '54.214.{0}.{1}'.format(random.choice(range(255)),
|
return '54.214.{0}.{1}'.format(random.choice(range(255)),
|
||||||
random.choice(range(255)))
|
random.choice(range(255)))
|
||||||
|
@ -1526,3 +1526,65 @@ def test_lambda_function():
|
|||||||
result['Functions'][0]['MemorySize'].should.equal(128)
|
result['Functions'][0]['MemorySize'].should.equal(128)
|
||||||
result['Functions'][0]['Role'].should.equal('test-role')
|
result['Functions'][0]['Role'].should.equal('test-role')
|
||||||
result['Functions'][0]['Runtime'].should.equal('nodejs')
|
result['Functions'][0]['Runtime'].should.equal('nodejs')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_cloudformation
|
||||||
|
@mock_ec2
|
||||||
|
def test_nat_gateway():
|
||||||
|
ec2_conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
vpc_id = ec2_conn.create_vpc(CidrBlock="10.0.0.0/16")['Vpc']['VpcId']
|
||||||
|
subnet_id = ec2_conn.create_subnet(CidrBlock='10.0.1.0/24', VpcId=vpc_id)['Subnet']['SubnetId']
|
||||||
|
route_table_id = ec2_conn.create_route_table(VpcId=vpc_id)['RouteTable']['RouteTableId']
|
||||||
|
|
||||||
|
template = {
|
||||||
|
"AWSTemplateFormatVersion": "2010-09-09",
|
||||||
|
"Resources": {
|
||||||
|
"NAT" : {
|
||||||
|
"DependsOn" : "vpcgatewayattachment",
|
||||||
|
"Type" : "AWS::EC2::NatGateway",
|
||||||
|
"Properties" : {
|
||||||
|
"AllocationId" : { "Fn::GetAtt" : ["EIP", "AllocationId"]},
|
||||||
|
"SubnetId" : subnet_id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EIP" : {
|
||||||
|
"Type" : "AWS::EC2::EIP",
|
||||||
|
"Properties" : {
|
||||||
|
"Domain" : "vpc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Route" : {
|
||||||
|
"Type" : "AWS::EC2::Route",
|
||||||
|
"Properties" : {
|
||||||
|
"RouteTableId" : route_table_id,
|
||||||
|
"DestinationCidrBlock" : "0.0.0.0/0",
|
||||||
|
"NatGatewayId" : { "Ref" : "NAT" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"internetgateway": {
|
||||||
|
"Type": "AWS::EC2::InternetGateway"
|
||||||
|
},
|
||||||
|
"vpcgatewayattachment": {
|
||||||
|
"Type": "AWS::EC2::VPCGatewayAttachment",
|
||||||
|
"Properties": {
|
||||||
|
"InternetGatewayId": {
|
||||||
|
"Ref": "internetgateway"
|
||||||
|
},
|
||||||
|
"VpcId": vpc_id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cf_conn = boto3.client('cloudformation', 'us-east-1')
|
||||||
|
cf_conn.create_stack(
|
||||||
|
StackName="test_stack",
|
||||||
|
TemplateBody=json.dumps(template),
|
||||||
|
)
|
||||||
|
|
||||||
|
result = ec2_conn.describe_nat_gateways()
|
||||||
|
|
||||||
|
result['NatGateways'].should.have.length_of(1)
|
||||||
|
result['NatGateways'][0]['VpcId'].should.equal(vpc_id)
|
||||||
|
result['NatGateways'][0]['SubnetId'].should.equal(subnet_id)
|
||||||
|
result['NatGateways'][0]['State'].should.equal('available')
|
||||||
|
100
tests/test_ec2/test_nat_gateway.py
Normal file
100
tests/test_ec2/test_nat_gateway.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import boto3
|
||||||
|
import sure # noqa
|
||||||
|
from moto import mock_ec2
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_describe_nat_gateways():
|
||||||
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
|
||||||
|
response = conn.describe_nat_gateways()
|
||||||
|
|
||||||
|
response['NatGateways'].should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_nat_gateway():
|
||||||
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
vpc = conn.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
vpc_id = vpc['Vpc']['VpcId']
|
||||||
|
subnet = conn.create_subnet(
|
||||||
|
VpcId=vpc_id,
|
||||||
|
CidrBlock='10.0.1.0/27',
|
||||||
|
AvailabilityZone='us-east-1a',
|
||||||
|
)
|
||||||
|
allocation_id = conn.allocate_address(Domain='vpc')['AllocationId']
|
||||||
|
subnet_id = subnet['Subnet']['SubnetId']
|
||||||
|
|
||||||
|
response = conn.create_nat_gateway(
|
||||||
|
SubnetId=subnet_id,
|
||||||
|
AllocationId=allocation_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
response['NatGateway']['VpcId'].should.equal(vpc_id)
|
||||||
|
response['NatGateway']['SubnetId'].should.equal(subnet_id)
|
||||||
|
response['NatGateway']['State'].should.equal('available')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_delete_nat_gateway():
|
||||||
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
vpc = conn.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
vpc_id = vpc['Vpc']['VpcId']
|
||||||
|
subnet = conn.create_subnet(
|
||||||
|
VpcId=vpc_id,
|
||||||
|
CidrBlock='10.0.1.0/27',
|
||||||
|
AvailabilityZone='us-east-1a',
|
||||||
|
)
|
||||||
|
allocation_id = conn.allocate_address(Domain='vpc')['AllocationId']
|
||||||
|
subnet_id = subnet['Subnet']['SubnetId']
|
||||||
|
|
||||||
|
nat_gateway = conn.create_nat_gateway(
|
||||||
|
SubnetId=subnet_id,
|
||||||
|
AllocationId=allocation_id,
|
||||||
|
)
|
||||||
|
nat_gateway_id = nat_gateway['NatGateway']['NatGatewayId']
|
||||||
|
response = conn.delete_nat_gateway(NatGatewayId=nat_gateway_id)
|
||||||
|
|
||||||
|
response.should.equal({
|
||||||
|
'NatGatewayId': nat_gateway_id,
|
||||||
|
'ResponseMetadata': {
|
||||||
|
'HTTPStatusCode': 200,
|
||||||
|
'RequestId': '741fc8ab-6ebe-452b-b92b-example'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_and_describe_nat_gateway():
|
||||||
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
vpc = conn.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
vpc_id = vpc['Vpc']['VpcId']
|
||||||
|
subnet = conn.create_subnet(
|
||||||
|
VpcId=vpc_id,
|
||||||
|
CidrBlock='10.0.1.0/27',
|
||||||
|
AvailabilityZone='us-east-1a',
|
||||||
|
)
|
||||||
|
allocation_id = conn.allocate_address(Domain='vpc')['AllocationId']
|
||||||
|
subnet_id = subnet['Subnet']['SubnetId']
|
||||||
|
|
||||||
|
create_response = conn.create_nat_gateway(
|
||||||
|
SubnetId=subnet_id,
|
||||||
|
AllocationId=allocation_id,
|
||||||
|
)
|
||||||
|
nat_gateway_id = create_response['NatGateway']['NatGatewayId']
|
||||||
|
describe_response = conn.describe_nat_gateways()
|
||||||
|
|
||||||
|
enis = conn.describe_network_interfaces()['NetworkInterfaces']
|
||||||
|
eni_id = enis[0]['NetworkInterfaceId']
|
||||||
|
public_ip = conn.describe_addresses(AllocationIds=[allocation_id])['Addresses'][0]['PublicIp']
|
||||||
|
|
||||||
|
describe_response['NatGateways'].should.have.length_of(1)
|
||||||
|
describe_response['NatGateways'][0]['NatGatewayId'].should.equal(nat_gateway_id)
|
||||||
|
describe_response['NatGateways'][0]['State'].should.equal('available')
|
||||||
|
describe_response['NatGateways'][0]['SubnetId'].should.equal(subnet_id)
|
||||||
|
describe_response['NatGateways'][0]['VpcId'].should.equal(vpc_id)
|
||||||
|
describe_response['NatGateways'][0]['NatGatewayAddresses'][0]['AllocationId'].should.equal(allocation_id)
|
||||||
|
describe_response['NatGateways'][0]['NatGatewayAddresses'][0]['NetworkInterfaceId'].should.equal(eni_id)
|
||||||
|
assert describe_response['NatGateways'][0]['NatGatewayAddresses'][0]['PrivateIp'].startswith('10.')
|
||||||
|
describe_response['NatGateways'][0]['NatGatewayAddresses'][0]['PublicIp'].should.equal(public_ip)
|
Loading…
Reference in New Issue
Block a user