diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 32b9f351f..26eab6e87 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -26,6 +26,7 @@ MODEL_MAP = { "AWS::EC2::EIP": ec2_models.ElasticAddress, "AWS::EC2::Instance": ec2_models.Instance, "AWS::EC2::InternetGateway": ec2_models.InternetGateway, + "AWS::EC2::NatGateway": ec2_models.NatGateway, "AWS::EC2::NetworkInterface": ec2_models.NetworkInterface, "AWS::EC2::Route": ec2_models.Route, "AWS::EC2::RouteTable": ec2_models.RouteTable, diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 719c5e94f..db2b71bcb 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -2994,6 +2994,15 @@ class NatGateway(object): 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): diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index 4a7ff7f77..5f52bb9a9 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -1526,3 +1526,65 @@ def test_lambda_function(): result['Functions'][0]['MemorySize'].should.equal(128) result['Functions'][0]['Role'].should.equal('test-role') 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')