Support Route53 create_hosted_zone raising ClientError ConflictingDomainExists (#7249)
This commit is contained in:
parent
9153f7bf73
commit
24b94fc192
@ -1,5 +1,5 @@
|
||||
"""Exceptions raised by the Route53 service."""
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
|
||||
from moto.core.exceptions import RESTError
|
||||
|
||||
@ -12,6 +12,19 @@ class Route53ClientError(RESTError):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class ConflictingDomainExists(Route53ClientError):
|
||||
"""Domain already exists."""
|
||||
|
||||
code = 400
|
||||
|
||||
def __init__(self, domain_name: str, delegation_set_id: Optional[str]) -> None:
|
||||
message = (
|
||||
f"Cannot create hosted zone with DelegationSetId DelegationSetId:{delegation_set_id} as the DNSName"
|
||||
f"{domain_name} conflicts with existing ones sharing the delegation set"
|
||||
)
|
||||
super().__init__("ConflictingDomainExists", message)
|
||||
|
||||
|
||||
class InvalidInput(Route53ClientError):
|
||||
"""Malformed ARN for the CloudWatch log group."""
|
||||
|
||||
|
@ -12,6 +12,7 @@ from jinja2 import Template
|
||||
from moto.core import BackendDict, BaseBackend, BaseModel, CloudFormationModel
|
||||
from moto.moto_api._internal import mock_random as random
|
||||
from moto.route53.exceptions import (
|
||||
ConflictingDomainExists,
|
||||
DnsNameInvalidForZone,
|
||||
HostedZoneNotEmpty,
|
||||
InvalidActionValue,
|
||||
@ -532,6 +533,24 @@ class Route53Backend(BaseBackend):
|
||||
self.query_logging_configs: Dict[str, QueryLoggingConfig] = {}
|
||||
self.delegation_sets: Dict[str, DelegationSet] = dict()
|
||||
|
||||
def _has_prev_conflicting_domain(
|
||||
self, name: str, delegation_set_id: Optional[str]
|
||||
) -> bool:
|
||||
"""Check if a conflicting domain exists in the backend"""
|
||||
if not delegation_set_id:
|
||||
return False
|
||||
for zone in self.zones.values():
|
||||
if not zone.delegation_set or zone.delegation_set.id != delegation_set_id:
|
||||
# Delegation sets don't match, so can't possibly conflict
|
||||
continue
|
||||
if (
|
||||
zone.name == name
|
||||
or zone.name.endswith(f".{name}")
|
||||
or name.endswith(f".{zone.name}")
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
def create_hosted_zone(
|
||||
self,
|
||||
name: str,
|
||||
@ -542,6 +561,8 @@ class Route53Backend(BaseBackend):
|
||||
comment: Optional[str] = None,
|
||||
delegation_set_id: Optional[str] = None,
|
||||
) -> FakeZone:
|
||||
if self._has_prev_conflicting_domain(name, delegation_set_id):
|
||||
raise ConflictingDomainExists(name, delegation_set_id)
|
||||
new_id = create_route53_zone_id()
|
||||
caller_reference = caller_reference or create_route53_caller_reference()
|
||||
delegation_set = self.create_reusable_delegation_set(
|
||||
|
@ -1516,3 +1516,54 @@ def test_get_dns_sec():
|
||||
)["HostedZone"]["Id"]
|
||||
dns_sec = client.get_dnssec(HostedZoneId=hosted_zone_id)
|
||||
assert dns_sec["Status"] == {"ServeSignature": "NOT_SIGNING"}
|
||||
|
||||
|
||||
@mock_route53
|
||||
@pytest.mark.parametrize(
|
||||
"domain1,domain2",
|
||||
(
|
||||
["a.com", "a.com"],
|
||||
["a.b.com", "b.com"],
|
||||
["b.com", "a.b.com"],
|
||||
["a.b.com", "a.b.com"],
|
||||
),
|
||||
)
|
||||
def test_conflicting_domain_exists(domain1, domain2):
|
||||
delegation_set_id = "N10015061S366L6NMTRKQ"
|
||||
conn = boto3.client("route53", region_name="us-east-1")
|
||||
conn.create_hosted_zone(
|
||||
Name=domain1,
|
||||
CallerReference=str(hash("foo")),
|
||||
DelegationSetId=delegation_set_id,
|
||||
)
|
||||
with pytest.raises(ClientError) as exc_info:
|
||||
conn.create_hosted_zone(
|
||||
Name=domain2,
|
||||
CallerReference=str(hash("bar")),
|
||||
DelegationSetId=delegation_set_id,
|
||||
)
|
||||
assert exc_info.value.response.get("Error").get("Code") == "ConflictingDomainExists"
|
||||
for string in [delegation_set_id, domain2]:
|
||||
assert string in exc_info.value.response.get("Error").get("Message")
|
||||
|
||||
# Now test that these domains can be created with different delegation set ids
|
||||
conn.create_hosted_zone(
|
||||
Name=domain1,
|
||||
CallerReference=str(hash("foo")),
|
||||
)
|
||||
conn.create_hosted_zone(
|
||||
Name=domain2,
|
||||
CallerReference=str(hash("bar")),
|
||||
)
|
||||
|
||||
# And, finally, test that these domains can be created with different named delegation sets
|
||||
conn.create_hosted_zone(
|
||||
Name=domain1,
|
||||
CallerReference=str(hash("foo")),
|
||||
DelegationSetId="1",
|
||||
)
|
||||
conn.create_hosted_zone(
|
||||
Name=domain2,
|
||||
CallerReference=str(hash("bar")),
|
||||
DelegationSetId="2",
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user