Route53 - Error on batch changes that are too large (#4674)
This commit is contained in:
parent
7776668a5a
commit
3d105361ef
@ -72,3 +72,12 @@ class QueryLoggingConfigAlreadyExists(Route53ClientError):
|
||||
def __init__(self):
|
||||
message = "A query logging configuration already exists for this hosted zone"
|
||||
super().__init__("QueryLoggingConfigAlreadyExists", message)
|
||||
|
||||
|
||||
class InvalidChangeBatch(Route53ClientError):
|
||||
|
||||
code = 400
|
||||
|
||||
def __init__(self):
|
||||
message = "Number of records limit of 1000 exceeded."
|
||||
super().__init__("InvalidChangeBatch", message)
|
||||
|
@ -6,7 +6,7 @@ from jinja2 import Template
|
||||
import xmltodict
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from moto.route53.exceptions import Route53ClientError
|
||||
from moto.route53.exceptions import Route53ClientError, InvalidChangeBatch
|
||||
from moto.route53.models import route53_backend
|
||||
|
||||
XMLNS = "https://route53.amazonaws.com/doc/2013-04-01/"
|
||||
@ -112,6 +112,23 @@ class Route53(BaseResponse):
|
||||
]["Change"]
|
||||
]
|
||||
|
||||
# Enforce quotas https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets
|
||||
# - A request cannot contain more than 1,000 ResourceRecord elements. When the value of the Action element is UPSERT, each ResourceRecord element is counted twice.
|
||||
effective_rr_count = 0
|
||||
for value in change_list:
|
||||
record_set = value["ResourceRecordSet"]
|
||||
if (
|
||||
"ResourceRecords" not in record_set
|
||||
or not record_set["ResourceRecords"]
|
||||
):
|
||||
continue
|
||||
resource_records = list(record_set["ResourceRecords"].values())[0]
|
||||
effective_rr_count += len(resource_records)
|
||||
if value["Action"] == "UPSERT":
|
||||
effective_rr_count += len(resource_records)
|
||||
if effective_rr_count > 1000:
|
||||
raise InvalidChangeBatch
|
||||
|
||||
error_msg = route53_backend.change_resource_record_sets(zoneid, change_list)
|
||||
if error_msg:
|
||||
return 400, headers, error_msg
|
||||
|
@ -1472,3 +1472,124 @@ def test_get_change():
|
||||
|
||||
response["ChangeInfo"]["Id"].should.equal(change_id)
|
||||
response["ChangeInfo"]["Status"].should.equal("INSYNC")
|
||||
|
||||
|
||||
@mock_route53
|
||||
def test_change_resource_record_sets_records_limit():
|
||||
conn = boto3.client("route53", region_name="us-east-1")
|
||||
conn.create_hosted_zone(
|
||||
Name="db.",
|
||||
CallerReference=str(hash("foo")),
|
||||
HostedZoneConfig=dict(PrivateZone=True, Comment="db"),
|
||||
)
|
||||
|
||||
zones = conn.list_hosted_zones_by_name(DNSName="db.")
|
||||
len(zones["HostedZones"]).should.equal(1)
|
||||
zones["HostedZones"][0]["Name"].should.equal("db.")
|
||||
hosted_zone_id = zones["HostedZones"][0]["Id"]
|
||||
|
||||
# Changes creating exactly 1,000 resource records.
|
||||
changes = []
|
||||
for ci in range(4):
|
||||
resourcerecords = []
|
||||
for rri in range(250):
|
||||
resourcerecords.append({"Value": "127.0.0.%d" % (rri)})
|
||||
changes.append(
|
||||
{
|
||||
"Action": "CREATE",
|
||||
"ResourceRecordSet": {
|
||||
"Name": "foo%d.db." % (ci),
|
||||
"Type": "A",
|
||||
"TTL": 10,
|
||||
"ResourceRecords": resourcerecords,
|
||||
},
|
||||
}
|
||||
)
|
||||
create_1000_resource_records_payload = {
|
||||
"Comment": "Create four records with 250 resource records each",
|
||||
"Changes": changes,
|
||||
}
|
||||
|
||||
conn.change_resource_record_sets(
|
||||
HostedZoneId=hosted_zone_id, ChangeBatch=create_1000_resource_records_payload
|
||||
)
|
||||
|
||||
# Changes creating over 1,000 resource records.
|
||||
too_many_changes = create_1000_resource_records_payload["Changes"].copy()
|
||||
too_many_changes.append(
|
||||
{
|
||||
"Action": "CREATE",
|
||||
"ResourceRecordSet": {
|
||||
"Name": "toomany.db.",
|
||||
"Type": "A",
|
||||
"TTL": 10,
|
||||
"ResourceRecords": [{"Value": "127.0.0.1"}],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
create_1001_resource_records_payload = {
|
||||
"Comment": "Create four records with 250 resource records each, plus one more",
|
||||
"Changes": too_many_changes,
|
||||
}
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
conn.change_resource_record_sets(
|
||||
HostedZoneId=hosted_zone_id,
|
||||
ChangeBatch=create_1001_resource_records_payload,
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("InvalidChangeBatch")
|
||||
|
||||
# Changes upserting exactly 500 resource records.
|
||||
changes = []
|
||||
for ci in range(2):
|
||||
resourcerecords = []
|
||||
for rri in range(250):
|
||||
resourcerecords.append({"Value": "127.0.0.%d" % (rri)})
|
||||
changes.append(
|
||||
{
|
||||
"Action": "UPSERT",
|
||||
"ResourceRecordSet": {
|
||||
"Name": "foo%d.db." % (ci),
|
||||
"Type": "A",
|
||||
"TTL": 10,
|
||||
"ResourceRecords": resourcerecords,
|
||||
},
|
||||
}
|
||||
)
|
||||
upsert_500_resource_records_payload = {
|
||||
"Comment": "Upsert two records with 250 resource records each",
|
||||
"Changes": changes,
|
||||
}
|
||||
|
||||
conn.change_resource_record_sets(
|
||||
HostedZoneId=hosted_zone_id, ChangeBatch=upsert_500_resource_records_payload
|
||||
)
|
||||
|
||||
# Changes upserting over 1,000 resource records.
|
||||
too_many_changes = upsert_500_resource_records_payload["Changes"].copy()
|
||||
too_many_changes.append(
|
||||
{
|
||||
"Action": "UPSERT",
|
||||
"ResourceRecordSet": {
|
||||
"Name": "toomany.db.",
|
||||
"Type": "A",
|
||||
"TTL": 10,
|
||||
"ResourceRecords": [{"Value": "127.0.0.1"}],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
upsert_501_resource_records_payload = {
|
||||
"Comment": "Upsert two records with 250 resource records each, plus one more",
|
||||
"Changes": too_many_changes,
|
||||
}
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
conn.change_resource_record_sets(
|
||||
HostedZoneId=hosted_zone_id, ChangeBatch=upsert_501_resource_records_payload
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("InvalidChangeBatch")
|
||||
err["Message"].should.equal("Number of records limit of 1000 exceeded.")
|
||||
|
Loading…
Reference in New Issue
Block a user