diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 9691131c8..97c707965 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -18,6 +18,7 @@ MODEL_MAP = { "AWS::EC2::EIP": ec2_models.ElasticAddress, "AWS::EC2::Instance": ec2_models.Instance, "AWS::EC2::InternetGateway": ec2_models.InternetGateway, + "AWS::EC2::NetworkInterface": ec2_models.NetworkInterface, "AWS::EC2::Route": ec2_models.Route, "AWS::EC2::RouteTable": ec2_models.RouteTable, "AWS::EC2::SecurityGroup": ec2_models.SecurityGroup, diff --git a/moto/ec2/models.py b/moto/ec2/models.py index aeb0c5c94..64d9e02f2 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -203,6 +203,10 @@ class NetworkInterface(object): raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "SecondaryPrivateIpAddresses" ]"') raise UnformattedGetAttTemplateException() + @property + def physical_resource_id(self): + return self.id + class NetworkInterfaceBackend(object): def __init__(self): diff --git a/tests/test_cloudformation/fixtures/vpc_eni.py b/tests/test_cloudformation/fixtures/vpc_eni.py new file mode 100644 index 000000000..ef9eb1d08 --- /dev/null +++ b/tests/test_cloudformation/fixtures/vpc_eni.py @@ -0,0 +1,34 @@ +from __future__ import unicode_literals + +template = { + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "VPC ENI Test CloudFormation", + "Resources": { + "ENI": { + "Type": "AWS::EC2::NetworkInterface", + "Properties": { + "SubnetId": {"Ref": "Subnet"} + } + }, + "Subnet": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "us-east-1a", + "VpcId": {"Ref": "VPC"}, + "CidrBlock": "10.0.0.0/24" + } + }, + "VPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16" + } + } + }, + "Outputs": { + "NinjaENI": { + "Description": "Elastic IP mapping to Auto-Scaling Group", + "Value": {"Ref": "ENI"} + } + } +} diff --git a/tests/test_ec2/test_elastic_network_interfaces.py b/tests/test_ec2/test_elastic_network_interfaces.py index 7d13cfc88..500d6a8a6 100644 --- a/tests/test_ec2/test_elastic_network_interfaces.py +++ b/tests/test_ec2/test_elastic_network_interfaces.py @@ -7,8 +7,10 @@ import boto from boto.exception import EC2ResponseError import sure # noqa -from moto import mock_ec2 +from moto import mock_ec2, mock_cloudformation from tests.helpers import requires_boto_gte +from tests.test_cloudformation.fixtures import vpc_eni +import json @mock_ec2 @@ -143,3 +145,21 @@ def test_elastic_network_interfaces_filtering(): # Unsupported filter conn.get_all_network_interfaces.when.called_with(filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError) + +@mock_ec2 +@mock_cloudformation +def test_elastic_network_interfaces_cloudformation(): + template = vpc_eni.template + template_json = json.dumps(template) + conn = boto.connect_cloudformation() + conn.create_stack( + "test_stack", + template_body=template_json, + ) + ec2_conn = boto.connect_ec2() + eni = ec2_conn.get_all_network_interfaces()[0] + + stack = conn.describe_stacks()[0] + resources = stack.describe_resources() + cfn_eni = [resource for resource in resources if resource.resource_type == 'AWS::EC2::NetworkInterface'][0] + cfn_eni.physical_resource_id.should.equal(eni.id)