DynamoDB - Exceptions for incorrect AttributeDefinitions in create_table (#4409) (#4428)

This commit is contained in:
Maksymilian Babarowski 2021-10-18 11:11:04 +02:00 committed by GitHub
parent a23e507abf
commit 9d552c39ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 191 additions and 9 deletions

View File

@ -203,15 +203,8 @@ class DynamoHandler(BaseResponse):
actual_attrs = [item["AttributeName"] for item in attr]
actual_attrs.sort()
if actual_attrs != expected_attrs:
er = "com.amazonaws.dynamodb.v20111205#ValidationException"
return self.error(
er,
"One or more parameter values were invalid: "
"Some index key attributes are not defined in AttributeDefinitions. "
"Keys: "
+ str(expected_attrs)
+ ", AttributeDefinitions: "
+ str(actual_attrs),
return self._throw_attr_error(
actual_attrs, expected_attrs, global_indexes or local_secondary_indexes
)
# get the stream specification
streams = body.get("StreamSpecification")
@ -231,6 +224,62 @@ class DynamoHandler(BaseResponse):
er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException"
return self.error(er, "Resource in use")
def _throw_attr_error(self, actual_attrs, expected_attrs, indexes):
def dump_list(list_):
return str(list_).replace("'", "")
er = "com.amazonaws.dynamodb.v20111205#ValidationException"
err_head = "One or more parameter values were invalid: "
if len(actual_attrs) > len(expected_attrs):
if indexes:
return self.error(
er,
err_head
+ "Some AttributeDefinitions are not used. AttributeDefinitions: "
+ dump_list(actual_attrs)
+ ", keys used: "
+ dump_list(expected_attrs),
)
else:
return self.error(
er,
err_head
+ "Number of attributes in KeySchema does not exactly match number of attributes defined in AttributeDefinitions",
)
elif len(actual_attrs) < len(expected_attrs):
if indexes:
return self.error(
er,
err_head
+ "Some index key attributes are not defined in AttributeDefinitions. Keys: "
+ dump_list(list(set(expected_attrs) - set(actual_attrs)))
+ ", AttributeDefinitions: "
+ dump_list(actual_attrs),
)
else:
return self.error(
er, "Invalid KeySchema: Some index key attribute have no definition"
)
else:
if indexes:
return self.error(
er,
err_head
+ "Some index key attributes are not defined in AttributeDefinitions. Keys: "
+ dump_list(list(set(expected_attrs) - set(actual_attrs)))
+ ", AttributeDefinitions: "
+ dump_list(actual_attrs),
)
else:
return self.error(
er,
err_head
+ "Some index key attributes are not defined in AttributeDefinitions. Keys: "
+ dump_list(expected_attrs)
+ ", AttributeDefinitions: "
+ dump_list(actual_attrs),
)
def delete_table(self):
name = self.body["TableName"]
table = self.dynamodb_backend.delete_table(name)

View File

@ -195,3 +195,136 @@ def test_batch_write_item_non_existing_table():
err = exc.value.response["Error"]
assert err["Code"].should.equal("ResourceNotFoundException")
assert err["Message"].should.equal("Requested resource not found")
@mock_dynamodb2
def test_create_table_with_redundant_attributes():
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "S"},
{"AttributeName": "created_at", "AttributeType": "N"},
],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Number of attributes in KeySchema does not exactly match number of attributes defined in AttributeDefinitions"
)
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "S"},
{"AttributeName": "user", "AttributeType": "S"},
{"AttributeName": "created_at", "AttributeType": "N"},
],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
GlobalSecondaryIndexes=[
{
"IndexName": "gsi_user-items",
"KeySchema": [{"AttributeName": "user", "KeyType": "HASH"}],
"Projection": {"ProjectionType": "ALL"},
}
],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Some AttributeDefinitions are not used. AttributeDefinitions: [created_at, id, user], keys used: [id, user]"
)
@mock_dynamodb2
def test_create_table_with_missing_attributes():
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"},],
KeySchema=[
{"AttributeName": "id", "KeyType": "HASH"},
{"AttributeName": "created_at", "KeyType": "RANGE"},
],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"Invalid KeySchema: Some index key attribute have no definition"
)
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"},],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
GlobalSecondaryIndexes=[
{
"IndexName": "gsi_user-items",
"KeySchema": [{"AttributeName": "user", "KeyType": "HASH"}],
"Projection": {"ProjectionType": "ALL"},
}
],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [user], AttributeDefinitions: [id]"
)
@mock_dynamodb2
def test_create_table_with_redundant_and_missing_attributes():
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[
{"AttributeName": "created_at", "AttributeType": "N"}
],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [id], AttributeDefinitions: [created_at]"
)
with pytest.raises(ClientError) as exc:
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "S"},
{"AttributeName": "created_at", "AttributeType": "N"},
],
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
GlobalSecondaryIndexes=[
{
"IndexName": "gsi_user-items",
"KeySchema": [{"AttributeName": "user", "KeyType": "HASH"}],
"Projection": {"ProjectionType": "ALL"},
}
],
BillingMode="PAY_PER_REQUEST",
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [user], AttributeDefinitions: [created_at, id]"
)