From 42cd333d51ae5831f9906b44bb86da696d2b5cb4 Mon Sep 17 00:00:00 2001 From: Steve Pulec Date: Sat, 17 Jan 2015 14:50:19 -0500 Subject: [PATCH] Refactor Route53 record sets. --- moto/route53/models.py | 58 +++++++++++++++++-- moto/route53/responses.py | 26 ++++----- .../test_cloudformation_stack_integration.py | 11 +++- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/moto/route53/models.py b/moto/route53/models.py index f87b32820..cd500afeb 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -1,8 +1,39 @@ from __future__ import unicode_literals + +from jinja2 import Template + from moto.core import BaseBackend 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.ttl = kwargs.get('TTL') + self.records = kwargs.get('ResourceRecords', []) + self.set_identifier = kwargs.get('SetIdentifier') + self.weight = kwargs.get('Weight') + + def to_xml(self): + template = Template(""" + {{ record_set.name }} + {{ record_set.type }} + {{ record_set.set_identifier }} + {{ record_set.weight }} + {{ record_set.ttl }} + + {% for record in record_set.records %} + + {{ record }} + + {% endfor %} + + + """) + return template.render(record_set=self) + + class FakeZone(object): def __init__(self, name, id_): @@ -10,11 +41,21 @@ class FakeZone(object): self.id = id_ self.rrsets = [] - def add_rrset(self, name, rrset): - self.rrsets.append(rrset) + def add_rrset(self, record_set): + record_set = RecordSet(record_set) + self.rrsets.append(record_set) def delete_rrset(self, name): - self.rrsets = [record_set for record_set in self.rrsets if record_set['Name'] != name] + self.rrsets = [record_set for record_set in self.rrsets if record_set.name != name] + + 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] + if name_filter: + record_sets = [record_set for record_set in record_sets if record_set.name == name_filter] + + return record_sets @property def physical_resource_id(self): @@ -30,9 +71,14 @@ class FakeZone(object): class RecordSetGroup(object): - def __init__(self, record_sets): + def __init__(self, hosted_zone_id, record_sets): + self.hosted_zone_id = hosted_zone_id self.record_sets = record_sets + @property + def physical_resource_id(self): + return "arn:aws:route53:::hostedzone/{0}".format(self.hosted_zone_id) + @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] @@ -41,9 +87,9 @@ class RecordSetGroup(object): hosted_zone = route53_backend.get_hosted_zone_by_name(zone_name) record_sets = properties["RecordSets"] for record_set in record_sets: - hosted_zone.add_rrset(record_set["Name"], record_set) + hosted_zone.add_rrset(record_set) - record_set_group = RecordSetGroup(record_sets) + record_set_group = RecordSetGroup(hosted_zone.id, record_sets) return record_set_group diff --git a/moto/route53/responses.py b/moto/route53/responses.py index 71a2acd7d..d110ebd55 100644 --- a/moto/route53/responses.py +++ b/moto/route53/responses.py @@ -3,7 +3,6 @@ from jinja2 import Template from six.moves.urllib.parse import parse_qs, urlparse from .models import route53_backend import xmltodict -import dicttoxml def list_or_create_hostzone_response(request, full_url, headers): @@ -53,33 +52,28 @@ def rrset_response(request, full_url, headers): for value in change_list: action = value['Action'] - rrset = value['ResourceRecordSet'] - + record_set = value['ResourceRecordSet'] if action == 'CREATE': - the_zone.add_rrset(rrset["Name"], rrset) + record_set['ResourceRecords'] = [x['Value'] for x in record_set['ResourceRecords'].values()] + the_zone.add_rrset(record_set) elif action == "DELETE": - the_zone.delete_rrset(rrset["Name"]) + the_zone.delete_rrset(record_set["Name"]) return 200, headers, CHANGE_RRSET_RESPONSE elif method == "GET": querystring = parse_qs(parsed_url.query) template = Template(LIST_RRSET_REPONSE) - rrset_list = [] - for record_set in the_zone.rrsets: - if 'type' in querystring and querystring["type"][0] != record_set["Type"]: - continue - if 'name' in querystring and querystring["name"][0] != record_set["Name"]: - continue - rrset_list.append(dicttoxml.dicttoxml({"ResourceRecordSet": record_set}, root=False)) - - return 200, headers, template.render(rrsets=rrset_list) + type_filter = querystring.get("type", [None])[0] + name_filter = querystring.get("name", [None])[0] + record_sets = the_zone.get_record_sets(type_filter, name_filter) + return 200, headers, template.render(record_sets=record_sets) LIST_RRSET_REPONSE = """ - {% for rrset in rrsets %} - {{ rrset }} + {% for record_set in record_sets %} + {{ record_set.to_xml() }} {% endfor %} """ diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index a138a4963..614203eec 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -780,7 +780,7 @@ def test_route53_roundrobin(): template_json = json.dumps(route53_roundrobin.template) conn = boto.cloudformation.connect_to_region("us-west-1") - conn.create_stack( + stack = conn.create_stack( "test_stack", template_body=template_json, ) @@ -798,7 +798,7 @@ def test_route53_roundrobin(): record_set1.type.should.equal('CNAME') record_set1.ttl.should.equal('900') record_set1.weight.should.equal('3') - # FIXME record_set1.resource_records[0].should.equal("aws.amazon.com") + record_set1.resource_records[0].should.equal("aws.amazon.com") record_set2 = rrsets[1] record_set2.name.should.equal('test_stack.us-west-1.my_zone.') @@ -806,4 +806,9 @@ def test_route53_roundrobin(): record_set2.type.should.equal('CNAME') record_set2.ttl.should.equal('900') record_set2.weight.should.equal('1') - # FIXME record_set2.resource_records[0].should.equal("www.amazon.com") + record_set2.resource_records[0].should.equal("www.amazon.com") + + stack = conn.describe_stacks()[0] + output = stack.outputs[0] + output.key.should.equal('DomainName') + output.value.should.equal('arn:aws:route53:::hostedzone/{0}'.format(zone_id))