diff --git a/docs/docs/services/route53.rst b/docs/docs/services/route53.rst index 1e03288c7..66dc661df 100644 --- a/docs/docs/services/route53.rst +++ b/docs/docs/services/route53.rst @@ -64,7 +64,7 @@ route53 - [ ] get_health_check_last_failure_reason - [ ] get_health_check_status - [X] get_hosted_zone -- [ ] get_hosted_zone_count +- [X] get_hosted_zone_count - [ ] get_hosted_zone_limit - [X] get_query_logging_config Return query logging config, if it exists. diff --git a/moto/route53/models.py b/moto/route53/models.py index 6004550bf..7cdb755e9 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -498,6 +498,9 @@ class Route53Backend(BaseBackend): raise NoSuchHostedZone(id_) return the_zone + def get_hosted_zone_count(self): + return len(self.list_hosted_zones()) + def get_hosted_zone_by_name(self, name): for zone in self.list_hosted_zones(): if zone.name == name: diff --git a/moto/route53/responses.py b/moto/route53/responses.py index cb8295b97..8d49c5799 100644 --- a/moto/route53/responses.py +++ b/moto/route53/responses.py @@ -93,6 +93,12 @@ class Route53(BaseResponse): template = Template(LIST_HOSTED_ZONES_BY_VPC_RESPONSE) return 200, headers, template.render(zones=zones, xmlns=XMLNS) + def get_hosted_zone_count_response(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + num_zones = route53_backend.get_hosted_zone_count() + template = Template(GET_HOSTED_ZONE_COUNT_RESPONSE) + return 200, headers, template.render(zone_count=num_zones, xmlns=XMLNS) + @error_handler def get_or_delete_hostzone_response(self, request, full_url, headers): self.setup_class(request, full_url, headers) @@ -414,6 +420,11 @@ DELETE_HOSTED_ZONE_RESPONSE = """ xmlns="https://route53.amazonaws.com/doc/2012-12-12/"> + {{ zone_count }} +""" + + GET_HOSTED_ZONE_RESPONSE = """ /hostedzone/{{ zone.id }} diff --git a/moto/route53/urls.py b/moto/route53/urls.py index 6b4bb324c..09b305b4b 100644 --- a/moto/route53/urls.py +++ b/moto/route53/urls.py @@ -18,6 +18,7 @@ url_paths = { r"{0}/(?P[\d_-]+)/hostedzone/(?P[^/]+)/rrset/?$": Route53().rrset_response, r"{0}/(?P[\d_-]+)/hostedzonesbyname": Route53().list_hosted_zones_by_name_response, r"{0}/(?P[\d_-]+)/hostedzonesbyvpc": Route53().list_hosted_zones_by_vpc_response, + r"{0}/(?P[\d_-]+)/hostedzonecount": Route53().get_hosted_zone_count_response, r"{0}/(?P[\d_-]+)/healthcheck": Route53().health_check_response, r"{0}/(?P[\d_-]+)/healthcheck/(?P[^/]+)$": Route53().health_check_response, r"{0}/(?P[\d_-]+)/tags/healthcheck/(?P[^/]+)$": tag_response1, diff --git a/tests/test_route53/test_route53.py b/tests/test_route53/test_route53.py index 2ce91b0d5..7e9467eab 100644 --- a/tests/test_route53/test_route53.py +++ b/tests/test_route53/test_route53.py @@ -61,6 +61,57 @@ def test_delete_hosted_zone(): res.should.have.length_of(1) +@mock_route53 +def test_get_hosted_zone_count_no_zones(): + conn = boto3.client("route53", region_name="us-east-1") + zone_count = conn.get_hosted_zone_count() + zone_count.should.have.key("HostedZoneCount") + isinstance(zone_count["HostedZoneCount"], int).should.be.true + zone_count["HostedZoneCount"].should.be.equal(0) + + +@mock_route53 +def test_get_hosted_zone_count_one_zone(): + conn = boto3.client("route53", region_name="us-east-1") + zone = "a" + zone_name = f"test.{zone}.com." + conn.create_hosted_zone( + Name=zone_name, + CallerReference=str(hash("foo")), + HostedZoneConfig=dict(PrivateZone=False, Comment=f"test {zone} com"), + ) + zone_count = conn.get_hosted_zone_count() + zone_count.should.have.key("HostedZoneCount") + isinstance(zone_count["HostedZoneCount"], int).should.be.true + zone_count["HostedZoneCount"].should.be.equal(1) + + +@mock_route53 +def test_get_hosted_zone_count_many_zones(): + conn = boto3.client("route53", region_name="us-east-1") + zones = {} + zone_indexes = [] + for char in range(ord("a"), ord("d") + 1): + for char2 in range(ord("a"), ord("z") + 1): + zone_indexes.append(f"{chr(char)}{chr(char2)}") + + # Create 100-ish zones and make sure we get 100 back. This works + # for 702 zones {a..zz}, but seemed a needless waste of + # time/resources. + for zone in zone_indexes: + zone_name = f"test.{zone}.com." + zones[zone] = conn.create_hosted_zone( + Name=zone_name, + CallerReference=str(hash("foo")), + HostedZoneConfig=dict(PrivateZone=False, Comment=f"test {zone} com"), + ) + zone_count = conn.get_hosted_zone_count() + zone_count.should.have.key("HostedZoneCount") + isinstance(zone_count["HostedZoneCount"], int).should.be.true + zone_count["HostedZoneCount"].shouldnt.be.equal(0) + zone_count["HostedZoneCount"].should.be.equal(len(zone_indexes)) + + @mock_route53 def test_get_unknown_hosted_zone(): conn = boto3.client("route53", region_name="us-east-1")