From 2562da28c6171cc5372d3a695af00e22134a360b Mon Sep 17 00:00:00 2001 From: Dinesh Bhor Date: Tue, 19 Sep 2017 18:35:56 +0530 Subject: [PATCH] Fix 500 if user passes name with more than 80 characters Following apis are returning 500 error if user passes name with more than 80 characters: * md-tag-create * md-tag-update * md-object-create * md-object-update * md-property-create * md-property-update This happens because there is a discrepancy in db column length and glance-api length check in schema validation. In database the 'name' field for these API's is defined as of maximum 80 characters and in schema it is defined as of maximum 255 characters. So if user passes name with more than 80 characters and less than 255 characters database fails to store that value and shouts with following error which leads to 500 error to API user: (pymysql.err.DataError) (1406, u"Data too long for column 'name' at row 1") Fixed this issue by changing the maximum allowed length for 'name' from 255 to 80 in schema validation. APIImpact DocImpact Closes-Bug: #1719252 Change-Id: I4ae67457c3e4f5a6bfc3c1db2d305a9b7587395f --- .../v2/metadefs-namespaces-properties.inc | 2 +- api-ref/source/v2/metadefs-parameters.yaml | 11 +++-- glance/api/v2/metadef_namespaces.py | 2 +- glance/api/v2/metadef_objects.py | 2 +- glance/api/v2/metadef_tags.py | 2 +- .../tests/unit/v2/test_metadef_resources.py | 48 +++++++++++++++---- ...9252-name-validation-443a2e2a36be2cec.yaml | 9 ++++ 7 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 releasenotes/notes/bug-1719252-name-validation-443a2e2a36be2cec.yaml diff --git a/api-ref/source/v2/metadefs-namespaces-properties.inc b/api-ref/source/v2/metadefs-namespaces-properties.inc index 4059cbcf43..6579019be2 100644 --- a/api-ref/source/v2/metadefs-namespaces-properties.inc +++ b/api-ref/source/v2/metadefs-namespaces-properties.inc @@ -19,7 +19,7 @@ The schema is a subset of the JSON property definition schema. Normal response codes: 201 -Error response codes: 404 +Error response codes: 400, 404 Request diff --git a/api-ref/source/v2/metadefs-parameters.yaml b/api-ref/source/v2/metadefs-parameters.yaml index 96a326462a..9a58aa8391 100644 --- a/api-ref/source/v2/metadefs-parameters.yaml +++ b/api-ref/source/v2/metadefs-parameters.yaml @@ -16,7 +16,7 @@ Location: # variables in path name: description: | - Name of the resource type. + Name of the resource type. A Name is limited to 80 chars in length. in: path required: true type: string @@ -47,7 +47,7 @@ resource_type_name: type: string tag_name: description: | - The name of the tag. + The name of the tag. A Name is limited to 80 chars in length. in: path required: true type: string @@ -253,7 +253,7 @@ minLength: type: string name-property: description: | - The name of the property. + The name of the property. A Name is limited to 80 chars in length. in: body required: true type: string @@ -265,7 +265,7 @@ name-resource-type: type: string name-tag: description: | - The name of the tag. + The name of the tag. A Name is limited to 80 chars in length. in: body required: true type: string @@ -303,7 +303,8 @@ object-description-in-request: type: string object-name: description: | - The name of the object, suitable for use as an identifier. + The name of the object, suitable for use as an identifier. A Name is + limited to 80 chars in length. in: body required: true type: string diff --git a/glance/api/v2/metadef_namespaces.py b/glance/api/v2/metadef_namespaces.py index 3bd44907c5..935b6df78e 100644 --- a/glance/api/v2/metadef_namespaces.py +++ b/glance/api/v2/metadef_namespaces.py @@ -591,7 +591,7 @@ def get_schema_definitions(): "properties": { "name": { "type": "string", - "maxLength": 255 + "maxLength": 80 }, "title": { "type": "string" diff --git a/glance/api/v2/metadef_objects.py b/glance/api/v2/metadef_objects.py index c42d69f394..6f77a7de72 100644 --- a/glance/api/v2/metadef_objects.py +++ b/glance/api/v2/metadef_objects.py @@ -179,7 +179,7 @@ def _get_base_properties(): return { "name": { "type": "string", - "maxLength": 255 + "maxLength": 80 }, "description": { "type": "string" diff --git a/glance/api/v2/metadef_tags.py b/glance/api/v2/metadef_tags.py index 1ebb31cc3d..36f2a8ea37 100644 --- a/glance/api/v2/metadef_tags.py +++ b/glance/api/v2/metadef_tags.py @@ -203,7 +203,7 @@ def _get_base_properties(): return { "name": { "type": "string", - "maxLength": 255 + "maxLength": 80 }, "created_at": { "type": "string", diff --git a/glance/tests/unit/v2/test_metadef_resources.py b/glance/tests/unit/v2/test_metadef_resources.py index c3dfc1ca0c..a7ae428468 100644 --- a/glance/tests/unit/v2/test_metadef_resources.py +++ b/glance/tests/unit/v2/test_metadef_resources.py @@ -1039,7 +1039,7 @@ class TestMetadefsControllers(base.IsolatedUnitTest): 'Namespace3/' 'properties') request.body = jsonutils.dump_as_bytes({ - 'name': 'a' * 256, 'type': 'string', 'title': 'fake'}) + 'name': 'a' * 81, 'type': 'string', 'title': 'fake'}) exc = self.assertRaises(webob.exc.HTTPBadRequest, self.property_deserializer.create, @@ -1226,6 +1226,16 @@ class TestMetadefsControllers(base.IsolatedUnitTest): PROPERTY1, property) self.assertNotificationsLog([]) + def test_property_update_with_overlimit_name(self): + request = unit_test_utils.get_fake_request() + request.body = jsonutils.dump_as_bytes({ + 'name': 'a' * 81, 'type': 'string', 'title': 'fake'}) + exc = self.assertRaises(webob.exc.HTTPBadRequest, + self.property_deserializer.create, + request) + self.assertIn("Failed validating 'maxLength' in " + "schema['properties']['name']", exc.explanation) + def test_property_update_with_4byte_character(self): request = unit_test_utils.get_fake_request(tenant=TENANT3) @@ -1399,11 +1409,13 @@ class TestMetadefsControllers(base.IsolatedUnitTest): request = unit_test_utils.get_fake_request('/metadefs/namespaces/' 'Namespace3/' 'objects') - request.body = jsonutils.dump_as_bytes({'name': 'a' * 256}) + request.body = jsonutils.dump_as_bytes({'name': 'a' * 81}) - self.assertRaises(webob.exc.HTTPBadRequest, - self.deserializer.create, - request) + exc = self.assertRaises(webob.exc.HTTPBadRequest, + self.deserializer.create, + request) + self.assertIn("Failed validating 'maxLength' in " + "schema['properties']['name']", exc.explanation) def test_object_create_duplicate(self): request = unit_test_utils.get_fake_request() @@ -1556,6 +1568,15 @@ class TestMetadefsControllers(base.IsolatedUnitTest): self.object_controller.update, request, object, NAMESPACE1, OBJECT1) + def test_object_update_with_overlimit_name(self): + request = unit_test_utils.get_fake_request() + request.body = jsonutils.dump_as_bytes( + {"properties": {}, "name": "a" * 81, "required": []}) + exc = self.assertRaises(webob.exc.HTTPBadRequest, + self.deserializer.update, request) + self.assertIn("Failed validating 'maxLength' in " + "schema['properties']['name']", exc.explanation) + def test_object_update_conflict(self): request = unit_test_utils.get_fake_request(tenant=TENANT3) @@ -1888,9 +1909,11 @@ class TestMetadefsControllers(base.IsolatedUnitTest): def test_tag_create_overlimit_name(self): request = unit_test_utils.get_fake_request() - self.assertRaises(webob.exc.HTTPBadRequest, - self.tag_controller.create, - request, NAMESPACE1, 'a' * 256) + exc = self.assertRaises(webob.exc.HTTPBadRequest, + self.tag_controller.create, + request, NAMESPACE1, 'a' * 81) + self.assertIn("Failed validating 'maxLength' in " + "schema['properties']['name']", exc.explanation) def test_tag_create_with_4byte_character(self): request = unit_test_utils.get_fake_request() @@ -2036,6 +2059,15 @@ class TestMetadefsControllers(base.IsolatedUnitTest): self.tag_controller.update, request, tag, NAMESPACE1, TAG1) + def test_tag_update_with_name_overlimit(self): + request = unit_test_utils.get_fake_request() + request.body = jsonutils.dump_as_bytes( + {"properties": {}, "name": "a" * 81, "required": []}) + exc = self.assertRaises(webob.exc.HTTPBadRequest, + self.deserializer.update, request) + self.assertIn("Failed validating 'maxLength' in " + "schema['properties']['name']", exc.explanation) + def test_tag_update_conflict(self): request = unit_test_utils.get_fake_request(tenant=TENANT3) diff --git a/releasenotes/notes/bug-1719252-name-validation-443a2e2a36be2cec.yaml b/releasenotes/notes/bug-1719252-name-validation-443a2e2a36be2cec.yaml new file mode 100644 index 0000000000..f16306d0db --- /dev/null +++ b/releasenotes/notes/bug-1719252-name-validation-443a2e2a36be2cec.yaml @@ -0,0 +1,9 @@ +--- +other: + - | + The metadefs schemas for 'property', 'properties', 'tag', 'tags', + 'object', and 'objects' previously specified a 'name' element of maximum + 255 characters. Any attempt to add a name of greater than 80 characters + in length, however, resulted in a 500 response. The schemas have been + corrected to specify a maximum length of 80 characters for the 'name' + field.