From 88d991e3060bb80f12b2c73b66e78ed028986ea1 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Mon, 27 Feb 2023 22:05:50 -0100 Subject: [PATCH] DynamoDB: describe_table() - return correct error msg (#5997) --- moto/dynamodb/exceptions.py | 28 +++++++++++++++++----------- moto/dynamodb/models/__init__.py | 6 ++++-- tests/test_dynamodb/test_dynamodb.py | 4 +++- tests/test_dynamodb/test_server.py | 19 ++++++++++++++++++- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/moto/dynamodb/exceptions.py b/moto/dynamodb/exceptions.py index 87642779a..017c35b7c 100644 --- a/moto/dynamodb/exceptions.py +++ b/moto/dynamodb/exceptions.py @@ -4,12 +4,15 @@ from moto.core.exceptions import JsonRESTError from moto.dynamodb.limits import HASH_KEY_MAX_LENGTH, RANGE_KEY_MAX_LENGTH +ERROR_TYPE_PREFIX = "com.amazonaws.dynamodb.v20120810#" + + class DynamodbException(JsonRESTError): pass class MockValidationException(DynamodbException): - error_type = "com.amazonaws.dynamodb.v20111205#ValidationException" + error_type = ERROR_TYPE_PREFIX + "ValidationException" def __init__(self, message: str): super().__init__(MockValidationException.error_type, message=message) @@ -190,7 +193,7 @@ class IncorrectDataType(MockValidationException): class ConditionalCheckFailed(DynamodbException): - error_type = "com.amazonaws.dynamodb.v20111205#ConditionalCheckFailedException" + error_type = ERROR_TYPE_PREFIX + "ConditionalCheckFailedException" def __init__(self, msg: Optional[str] = None): super().__init__( @@ -279,44 +282,47 @@ class TooManyAddClauses(InvalidUpdateExpression): class ResourceNotFoundException(JsonRESTError): - def __init__(self, msg: Optional[str] = None): - err = "com.amazonaws.dynamodb.v20111205#ResourceNotFoundException" - super().__init__(err, msg or "Requested resource not found") + def __init__(self, msg: Optional[str] = None, table_name: Optional[str] = None): + err = ERROR_TYPE_PREFIX + "ResourceNotFoundException" + default_msg = "Requested resource not found" + if table_name is not None: + default_msg += f": Table: {table_name} not found" + super().__init__(err, msg or default_msg) class TableNotFoundException(JsonRESTError): def __init__(self, name: str): - err = "com.amazonaws.dynamodb.v20111205#TableNotFoundException" + err = ERROR_TYPE_PREFIX + "TableNotFoundException" super().__init__(err, f"Table not found: {name}") class SourceTableNotFoundException(JsonRESTError): def __init__(self, source_table_name: str): - er = "com.amazonaws.dynamodb.v20111205#SourceTableNotFoundException" + er = ERROR_TYPE_PREFIX + "SourceTableNotFoundException" super().__init__(er, f"Source table not found: {source_table_name}") class BackupNotFoundException(JsonRESTError): def __init__(self, backup_arn: str): - er = "com.amazonaws.dynamodb.v20111205#BackupNotFoundException" + er = ERROR_TYPE_PREFIX + "BackupNotFoundException" super().__init__(er, f"Backup not found: {backup_arn}") class TableAlreadyExistsException(JsonRESTError): def __init__(self, target_table_name: str): - er = "com.amazonaws.dynamodb.v20111205#TableAlreadyExistsException" + er = ERROR_TYPE_PREFIX + "TableAlreadyExistsException" super().__init__(er, f"Table already exists: {target_table_name}") class ResourceInUseException(JsonRESTError): def __init__(self) -> None: - er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException" + er = ERROR_TYPE_PREFIX + "ResourceInUseException" super().__init__(er, "Resource in use") class StreamAlreadyEnabledException(JsonRESTError): def __init__(self) -> None: - er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException" + er = ERROR_TYPE_PREFIX + "ResourceInUseException" super().__init__(er, "Cannot enable stream") diff --git a/moto/dynamodb/models/__init__.py b/moto/dynamodb/models/__init__.py index 7b03cb1ba..333b1ed63 100644 --- a/moto/dynamodb/models/__init__.py +++ b/moto/dynamodb/models/__init__.py @@ -123,8 +123,10 @@ class DynamoDBBackend(BaseBackend): return tables, None def describe_table(self, name: str) -> Dict[str, Any]: - table = self.get_table(name) - return table.describe(base_key="Table") + # We can't use get_table() here, because the error message is slightly different for this operation + if name not in self.tables: + raise ResourceNotFoundException(table_name=name) + return self.tables[name].describe(base_key="Table") def update_table( self, diff --git a/tests/test_dynamodb/test_dynamodb.py b/tests/test_dynamodb/test_dynamodb.py index 2146184dc..d7b19810c 100644 --- a/tests/test_dynamodb/test_dynamodb.py +++ b/tests/test_dynamodb/test_dynamodb.py @@ -66,7 +66,9 @@ def test_describe_missing_table_boto3(): conn.describe_table(TableName="messages") ex.value.response["Error"]["Code"].should.equal("ResourceNotFoundException") ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) - ex.value.response["Error"]["Message"].should.equal("Requested resource not found") + ex.value.response["Error"]["Message"].should.equal( + "Requested resource not found: Table: messages not found" + ) @mock_dynamodb diff --git a/tests/test_dynamodb/test_server.py b/tests/test_dynamodb/test_server.py index 9afa08076..ae6ddc88f 100644 --- a/tests/test_dynamodb/test_server.py +++ b/tests/test_dynamodb/test_server.py @@ -1,5 +1,6 @@ +import json import sure # noqa # pylint: disable=unused-import - +from moto import mock_dynamodb import moto.server as server """ @@ -7,6 +8,7 @@ Test the different server responses """ +@mock_dynamodb def test_table_list(): backend = server.create_backend_app("dynamodb") test_client = backend.test_client() @@ -17,3 +19,18 @@ def test_table_list(): res = test_client.get("/", headers=headers) res.data.should.contain(b"TableNames") res.headers.should.have.key("X-Amz-Crc32") + + headers = {"X-Amz-Target": "DynamoDB_20120810.DescribeTable"} + res = test_client.post( + "/", headers=headers, data=json.dumps({"TableName": "test-table2"}) + ) + res.headers.should.have.key("X-Amzn-ErrorType").equals( + "com.amazonaws.dynamodb.v20120810#ResourceNotFoundException" + ) + body = json.loads(res.data.decode("utf-8")) + body.should.equal( + { + "__type": "com.amazonaws.dynamodb.v20120810#ResourceNotFoundException", + "message": "Requested resource not found: Table: test-table2 not found", + } + )