From b9ea947aa0572234051d9ba22b77b862daa3b524 Mon Sep 17 00:00:00 2001 From: Andrew Garrett Date: Mon, 13 Mar 2017 14:09:51 +0000 Subject: [PATCH] Add ListHostedZonesByName --- moto/route53/responses.py | 47 +++++++++++++++++++++++++++- moto/route53/urls.py | 1 + tests/test_route53/test_route53.py | 50 ++++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/moto/route53/responses.py b/moto/route53/responses.py index 07f6e2303..984f305ab 100644 --- a/moto/route53/responses.py +++ b/moto/route53/responses.py @@ -7,7 +7,7 @@ from .models import route53_backend import xmltodict -class Route53 (BaseResponse): +class Route53(BaseResponse): def list_or_create_hostzone_response(self, request, full_url, headers): self.setup_class(request, full_url, headers) @@ -47,6 +47,32 @@ class Route53 (BaseResponse): template = Template(LIST_HOSTED_ZONES_RESPONSE) return 200, headers, template.render(zones=all_zones) + def list_hosted_zones_by_name_response(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + parsed_url = urlparse(full_url) + query_params = parse_qs(parsed_url.query) + dnsname = query_params.get("dnsname") + + if dnsname: + dnsname = dnsname[0] # parse_qs gives us a list, but this parameter doesn't repeat + # return all zones with that name (there can be more than one) + zones = [zone for zone in route53_backend.get_all_hosted_zones() if zone.name == dnsname] + else: + # sort by names, but with domain components reversed + # see http://boto3.readthedocs.io/en/latest/reference/services/route53.html#Route53.Client.list_hosted_zones_by_name + + def sort_key(zone): + domains = zone.name.split(".") + if domains[-1] == "": + domains = domains[-1:] + domains[:-1] + return ".".join(reversed(domains)) + + zones = route53_backend.get_all_hosted_zones() + zones = sorted(zones, key=sort_key) + + template = Template(LIST_HOSTED_ZONES_BY_NAME_RESPONSE) + return 200, headers, template.render(zones=zones) + def get_or_delete_hostzone_response(self, request, full_url, headers): self.setup_class(request, full_url, headers) parsed_url = urlparse(full_url) @@ -289,6 +315,25 @@ LIST_HOSTED_ZONES_RESPONSE = """ + + {% for zone in zones %} + + /hostedzone/{{ zone.id }} + {{ zone.name }} + + {% if zone.comment %} + {{ zone.comment }} + {% endif %} + {{ zone.private_zone }} + + {{ zone.rrsets|count }} + + {% endfor %} + + false +""" + CREATE_HEALTH_CHECK_RESPONSE = """ {{ health_check.to_xml() }} diff --git a/moto/route53/urls.py b/moto/route53/urls.py index 795f7d807..53abf23a2 100644 --- a/moto/route53/urls.py +++ b/moto/route53/urls.py @@ -18,6 +18,7 @@ url_paths = { '{0}/(?P[\d_-]+)/hostedzone$': Route53().list_or_create_hostzone_response, '{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)$': Route53().get_or_delete_hostzone_response, '{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset/?$': Route53().rrset_response, + '{0}/(?P[\d_-]+)/hostedzonesbyname': Route53().list_hosted_zones_by_name_response, '{0}/(?P[\d_-]+)/healthcheck': Route53().health_check_response, '{0}/(?P[\d_-]+)/tags/healthcheck/(?P[^/]+)$': tag_response1, '{0}/(?P[\d_-]+)/tags/hostedzone/(?P[^/]+)$': tag_response2, diff --git a/tests/test_route53/test_route53.py b/tests/test_route53/test_route53.py index ea8609556..b64c63a30 100644 --- a/tests/test_route53/test_route53.py +++ b/tests/test_route53/test_route53.py @@ -361,8 +361,9 @@ def test_hosted_zone_private_zone_preserved_boto3(): hosted_zones = conn.list_hosted_zones() hosted_zones["HostedZones"][0]["Config"]["PrivateZone"].should.equal(True) - # zone = conn.list_hosted_zones_by_name(DNSName="testdns.aws.com.") - # zone.config["PrivateZone"].should.equal(True) + hosted_zones = conn.list_hosted_zones_by_name(DNSName="testdns.aws.com.") + len(hosted_zones["HostedZones"]).should.equal(1) + hosted_zones["HostedZones"][0]["Config"]["PrivateZone"].should.equal(True) @mock_route53 @@ -445,3 +446,48 @@ def test_list_or_change_tags_for_resource_request(): response = conn.list_tags_for_resource( ResourceType='healthcheck', ResourceId=healthcheck_id) response['ResourceTagSet']['Tags'].should.be.empty + + +@mock_route53 +def test_list_hosted_zones_by_name(): + conn = boto3.client('route53', region_name='us-east-1') + conn.create_hosted_zone( + Name="test.b.com.", + CallerReference=str(hash('foo')), + HostedZoneConfig=dict( + PrivateZone=True, + Comment="test com", + ) + ) + conn.create_hosted_zone( + Name="test.a.org.", + CallerReference=str(hash('bar')), + HostedZoneConfig=dict( + PrivateZone=True, + Comment="test org", + ) + ) + conn.create_hosted_zone( + Name="test.a.org.", + CallerReference=str(hash('bar')), + HostedZoneConfig=dict( + PrivateZone=True, + Comment="test org 2", + ) + ) + + # test lookup + zones = conn.list_hosted_zones_by_name(DNSName="test.b.com.") + len(zones["HostedZones"]).should.equal(1) + zones["HostedZones"][0]["Name"].should.equal("test.b.com.") + zones = conn.list_hosted_zones_by_name(DNSName="test.a.org.") + len(zones["HostedZones"]).should.equal(2) + zones["HostedZones"][0]["Name"].should.equal("test.a.org.") + zones["HostedZones"][1]["Name"].should.equal("test.a.org.") + + # test sort order + zones = conn.list_hosted_zones_by_name() + len(zones["HostedZones"]).should.equal(3) + zones["HostedZones"][0]["Name"].should.equal("test.b.com.") + zones["HostedZones"][1]["Name"].should.equal("test.a.org.") + zones["HostedZones"][2]["Name"].should.equal("test.a.org.")