diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 100bb57f1..cb5283b99 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -38,6 +38,7 @@ MODEL_MAP = { "AWS::RDS::DBSecurityGroup": rds_models.SecurityGroup, "AWS::RDS::DBSubnetGroup": rds_models.SubnetGroup, "AWS::Route53::HostedZone": route53_models.FakeZone, + "AWS::Route53::RecordSet": route53_models.RecordSet, "AWS::Route53::RecordSetGroup": route53_models.RecordSetGroup, "AWS::SQS::Queue": sqs_models.Queue, } diff --git a/moto/ec2/models.py b/moto/ec2/models.py index e9246a6bf..ee9e20034 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -299,6 +299,7 @@ class Instance(BotoInstance, TaggedEC2Resource): self.subnet_id = kwargs.get("subnet_id") self.key_name = kwargs.get("key_name") self.source_dest_check = "true" + self.private_ip_address = kwargs.get('private_ip_address') self.block_device_mapping = BlockDeviceMapping() self.block_device_mapping['/dev/sda1'] = BlockDeviceType(volume_id=random_volume_id()) @@ -344,6 +345,7 @@ class Instance(BotoInstance, TaggedEC2Resource): instance_type=properties.get("InstanceType", "m1.small"), subnet_id=properties.get("SubnetId"), key_name=properties.get("KeyName"), + private_ip_address=properties.get('PrivateIpAddress'), ) return reservation.instances[0] diff --git a/moto/route53/models.py b/moto/route53/models.py index cd500afeb..e6bb1c7a2 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -9,18 +9,31 @@ from moto.core.utils import get_random_hex class RecordSet(object): def __init__(self, kwargs): self.name = kwargs.get('Name') - self.type = kwargs.get('Type') + self._type = kwargs.get('Type') self.ttl = kwargs.get('TTL') self.records = kwargs.get('ResourceRecords', []) self.set_identifier = kwargs.get('SetIdentifier') self.weight = kwargs.get('Weight') + @classmethod + def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): + properties = cloudformation_json['Properties'] + + zone_name = properties["HostedZoneName"] + hosted_zone = route53_backend.get_hosted_zone_by_name(zone_name) + record_set = hosted_zone.add_rrset(properties) + return record_set + def to_xml(self): template = Template(""" {{ record_set.name }} - {{ record_set.type }} - {{ record_set.set_identifier }} - {{ record_set.weight }} + {{ record_set._type }} + {% if record_set.set_identifier %} + {{ record_set.set_identifier }} + {% endif %} + {% if record_set.weight %} + {{ record_set.weight }} + {% endif %} {{ record_set.ttl }} {% for record in record_set.records %} @@ -44,6 +57,7 @@ class FakeZone(object): def add_rrset(self, record_set): record_set = RecordSet(record_set) self.rrsets.append(record_set) + return record_set def delete_rrset(self, name): self.rrsets = [record_set for record_set in self.rrsets if record_set.name != name] @@ -51,7 +65,7 @@ class FakeZone(object): def get_record_sets(self, type_filter, name_filter): record_sets = list(self.rrsets) # Copy the list if type_filter: - record_sets = [record_set for record_set in record_sets if record_set.type == type_filter] + record_sets = [record_set for record_set in record_sets if record_set._type == type_filter] if name_filter: record_sets = [record_set for record_set in record_sets if record_set.name == name_filter] diff --git a/tests/test_cloudformation/fixtures/route53_ec2_instance_with_public_ip.py b/tests/test_cloudformation/fixtures/route53_ec2_instance_with_public_ip.py new file mode 100644 index 000000000..02fa57b8f --- /dev/null +++ b/tests/test_cloudformation/fixtures/route53_ec2_instance_with_public_ip.py @@ -0,0 +1,40 @@ +from __future__ import unicode_literals + +template = { + "Resources" : { + "Ec2Instance" : { + "Type" : "AWS::EC2::Instance", + "Properties" : { + "ImageId" : "ami-1234abcd", + "PrivateIpAddress": "10.0.0.25", + } + }, + + "HostedZone": { + "Type" : "AWS::Route53::HostedZone", + "Properties" : { + "Name" : "my_zone" + } + }, + + "myDNSRecord" : { + "Type" : "AWS::Route53::RecordSet", + "Properties" : { + "HostedZoneName" : { "Ref" : "HostedZone" }, + "Comment" : "DNS name for my instance.", + "Name" : { + "Fn::Join" : [ "", [ + {"Ref" : "Ec2Instance"}, ".", + {"Ref" : "AWS::Region"}, ".", + {"Ref" : "HostedZone"} ,"." + ] ] + }, + "Type" : "A", + "TTL" : "900", + "ResourceRecords" : [ + { "Fn::GetAtt" : [ "Ec2Instance", "PrivateIp" ] } + ] + } + } + }, +} \ No newline at end of file diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index 614203eec..636cdea24 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -27,6 +27,7 @@ from .fixtures import ( ec2_classic_eip, fn_join, rds_mysql_with_read_replica, + route53_ec2_instance_with_public_ip, route53_roundrobin, single_instance_with_ebs_volume, vpc_eip, @@ -812,3 +813,35 @@ def test_route53_roundrobin(): output = stack.outputs[0] output.key.should.equal('DomainName') output.value.should.equal('arn:aws:route53:::hostedzone/{0}'.format(zone_id)) + + +@mock_cloudformation() +@mock_ec2() +@mock_route53() +def test_route53_ec2_instance_with_public_ip(): + route53_conn = boto.connect_route53() + ec2_conn = boto.ec2.connect_to_region("us-west-1") + + template_json = json.dumps(route53_ec2_instance_with_public_ip.template) + conn = boto.cloudformation.connect_to_region("us-west-1") + stack = conn.create_stack( + "test_stack", + template_body=template_json, + ) + + instance_id = ec2_conn.get_all_reservations()[0].instances[0].id + + zones = route53_conn.get_all_hosted_zones()['ListHostedZonesResponse']['HostedZones'] + list(zones).should.have.length_of(1) + zone_id = zones[0]['Id'] + + rrsets = route53_conn.get_all_rrsets(zone_id) + rrsets.should.have.length_of(1) + + record_set1 = rrsets[0] + record_set1.name.should.equal('{0}.us-west-1.my_zone.'.format(instance_id)) + record_set1.identifier.should.equal(None) + record_set1.type.should.equal('A') + record_set1.ttl.should.equal('900') + record_set1.weight.should.equal(None) + record_set1.resource_records[0].should.equal("10.0.0.25")