diff --git a/contrib/tempest/tempest/api/keyvalue/in_progress/rest/test_create_table_negative.py b/contrib/tempest/tempest/api/keyvalue/in_progress/rest/test_create_table_negative.py index 52fe370e..da01af04 100644 --- a/contrib/tempest/tempest/api/keyvalue/in_progress/rest/test_create_table_negative.py +++ b/contrib/tempest/tempest/api/keyvalue/in_progress/rest/test_create_table_negative.py @@ -144,27 +144,6 @@ class MagnetoDBCreateTableNegativeTestCase(MagnetoDBTestCase): self.smoke_schema, request_lsi) - @test.attr(type=['CreT-71', 'negative']) - def test_create_table_schema_hash_only_with_index(self): - index_attrs = [{'attribute_name': 'attr_name1', - 'attribute_type': 'S'}, - ] - request_lsi = [ - { - 'index_name': 'index_name', - 'key_schema': [ - {'attribute_name': self.hashkey, 'key_type': 'HASH'}, - {'attribute_name': 'attr_name1', 'key_type': 'RANGE'} - ], - 'projection': {'projection_type': 'ALL'} - } - ] - with self.assertRaises(exceptions.BadRequest): - self._create_test_table(self.one_attr + index_attrs, - self.tname, - self.schema_hash_only, - request_lsi) - @test.attr(type=['CreT-80', 'negative']) def test_create_table_index_without_projection_type_with_non_key(self): index_attrs = [{'attribute_name': 'attr_name1', diff --git a/contrib/tempest/tempest/api/keyvalue/stable/rest/test_create_table_negative.py b/contrib/tempest/tempest/api/keyvalue/stable/rest/test_create_table_negative.py index ee1ad7c6..e731b9dc 100644 --- a/contrib/tempest/tempest/api/keyvalue/stable/rest/test_create_table_negative.py +++ b/contrib/tempest/tempest/api/keyvalue/stable/rest/test_create_table_negative.py @@ -182,6 +182,32 @@ class MagnetoDBCreateTableNegativeTestCase(MagnetoDBTestCase): self.tname, self.smoke_schema, request_lsi) + @test.attr(type=['CreT-71', 'negative']) + def test_create_table_schema_hash_only_with_index(self): + index_attrs = [{'attribute_name': 'attr_name1', + 'attribute_type': 'S'}, + ] + request_lsi = [ + { + 'index_name': 'index_name', + 'key_schema': [ + {'attribute_name': self.hashkey, 'key_type': 'HASH'}, + {'attribute_name': 'attr_name1', 'key_type': 'RANGE'} + ], + 'projection': {'projection_type': 'ALL'} + } + ] + with self.assertRaises(exceptions.BadRequest) as raises_cm: + self._create_test_table(self.one_attr + index_attrs, + self.tname, + self.schema_hash_only, + request_lsi) + error_msg = raises_cm.exception._error_string + self.assertIn("Bad Request", error_msg) + self.assertIn("Table without range key in primary key schema " + "can not have indices", + error_msg) + @test.attr(type=['CreT-72', 'negative']) def test_create_table_two_indexes_with_same_key(self): index_attrs = [{'attribute_name': 'attr_name', diff --git a/magnetodb/api/openstack/v1/data/create_table.py b/magnetodb/api/openstack/v1/data/create_table.py index 32d259ff..e65a5ea7 100644 --- a/magnetodb/api/openstack/v1/data/create_table.py +++ b/magnetodb/api/openstack/v1/data/create_table.py @@ -80,6 +80,12 @@ class CreateTableController(): range_keys = [] if len(key_attrs) > 1: range_keys.append(key_attrs[1]) + else: + # table has hash type primary key + if len(index_def_map) > 0: + raise exception.ValidationError( + _("Table without range key in primary key schema " + "can not have indices")) for index in index_def_map.values(): range_keys.append(index.alt_range_key_attr) try: diff --git a/magnetodb/tests/unittests/api/openstack/v1/test_create_table.py b/magnetodb/tests/unittests/api/openstack/v1/test_create_table.py index 42aaa3cc..a489b89f 100644 --- a/magnetodb/tests/unittests/api/openstack/v1/test_create_table.py +++ b/magnetodb/tests/unittests/api/openstack/v1/test_create_table.py @@ -262,16 +262,73 @@ class CreateTableTest(test_base_testcase.APITestCase): "Subject": models.AttributeType('S'), "LastPostDateTime": models.AttributeType('S') }, - key_attributes=["ForumName"], - index_def_map={ - "LastPostIndex": models.IndexDefinition("ForumName", - "LastPostDateTime") - } + key_attributes=["ForumName"] ), models.TableMeta.TABLE_STATUS_ACTIVE, 123 ) conn = httplib.HTTPConnection('localhost:8080') + body = """ + { + "attribute_definitions": [ + { + "attribute_name": "ForumName", + "attribute_type": "S" + }, + { + "attribute_name": "Subject", + "attribute_type": "S" + }, + { + "attribute_name": "LastPostDateTime", + "attribute_type": "S" + } + ], + "table_name": "Thread", + "key_schema": [ + { + "attribute_name": "ForumName", + "key_type": "HASH" + } + ] + } + """ + + expected_response = {'table_description': { + 'attribute_definitions': [ + {'attribute_name': 'Subject', 'attribute_type': 'S'}, + {'attribute_name': 'LastPostDateTime', 'attribute_type': 'S'}, + {'attribute_name': 'ForumName', 'attribute_type': 'S'} + ], + 'creation_date_time': 123, + 'item_count': 0, + 'key_schema': [ + {'attribute_name': 'ForumName', 'key_type': 'HASH'} + ], + 'table_id': '00000000-0000-0000-0000-000000000000', + 'table_name': 'Thread', + 'table_size_bytes': 0, + 'table_status': 'ACTIVE', + 'links': [ + {'href': self.table_url, 'rel': 'self'}, + {'href': self.table_url, 'rel': 'bookmark'} + ]}} + + conn.request("POST", self.url, headers=self.headers, body=body) + + response = conn.getresponse() + self.assertEqual(200, response.status) + + self.assertTrue(mock_create_table.called) + + json_response = response.read() + response_payload = json.loads(json_response) + + self.assertEqual(expected_response, response_payload) + + def test_create_table_index_invalid_key_type(self): + conn = httplib.HTTPConnection('localhost:8080') + body = """ { "attribute_definitions": [ @@ -316,49 +373,23 @@ class CreateTableTest(test_base_testcase.APITestCase): } """ - expected_response = {'table_description': { - 'attribute_definitions': [ - {'attribute_name': 'Subject', 'attribute_type': 'S'}, - {'attribute_name': 'LastPostDateTime', 'attribute_type': 'S'}, - {'attribute_name': 'ForumName', 'attribute_type': 'S'} - ], - 'creation_date_time': 123, - 'item_count': 0, - 'key_schema': [ - {'attribute_name': 'ForumName', 'key_type': 'HASH'} - ], - 'local_secondary_indexes': [ - {'index_name': 'LastPostIndex', - 'index_size_bytes': 0, - 'item_count': 0, - 'key_schema': [ - {'attribute_name': 'ForumName', - 'key_type': 'HASH'}, - {'attribute_name': 'LastPostDateTime', - 'key_type': 'RANGE'} - ], - 'projection': {'projection_type': 'ALL'}} - ], - 'table_id': '00000000-0000-0000-0000-000000000000', - 'table_name': 'Thread', - 'table_size_bytes': 0, - 'table_status': 'ACTIVE', - 'links': [ - {'href': self.table_url, 'rel': 'self'}, - {'href': self.table_url, 'rel': 'bookmark'} - ]}} - conn.request("POST", self.url, headers=self.headers, body=body) response = conn.getresponse() - self.assertEqual(200, response.status) - self.assertTrue(mock_create_table.called) + self.assertEqual(400, response.status) json_response = response.read() response_payload = json.loads(json_response) - self.assertEqual(expected_response, response_payload) + expected_error = { + 'message': "Table without range key in primary key schema " + "can not have indices", + 'traceback': None, + 'type': 'ValidationError', + } + + self.assertEqual(expected_error, response_payload['error']) def test_create_table_invalid_name_character(self): conn = httplib.HTTPConnection('localhost:8080') @@ -850,4 +881,4 @@ class CreateTableTest(test_base_testcase.APITestCase): 'type': 'ValidationError', } - self.assertEqual(expected_error, response_payload['error']) \ No newline at end of file + self.assertEqual(expected_error, response_payload['error'])