Merge "Add mandatory option for validating the json input"
This commit is contained in:
commit
89d8d638c1
@ -12,6 +12,8 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from zun.common import exception
|
||||||
|
|
||||||
|
|
||||||
class APIBase(object):
|
class APIBase(object):
|
||||||
|
|
||||||
@ -20,6 +22,10 @@ class APIBase(object):
|
|||||||
if field in kwargs:
|
if field in kwargs:
|
||||||
value = kwargs[field]
|
value = kwargs[field]
|
||||||
setattr(self, field, value)
|
setattr(self, field, value)
|
||||||
|
else:
|
||||||
|
if self.fields[field].get('mandatory', False):
|
||||||
|
message = 'Required field %s is missing' % field
|
||||||
|
raise exception.ValidationError(detail=message)
|
||||||
|
|
||||||
def __setattr__(self, field, value):
|
def __setattr__(self, field, value):
|
||||||
if field in self.fields:
|
if field in self.fields:
|
||||||
|
@ -94,20 +94,6 @@ class NameType(String):
|
|||||||
raise exception.InvalidValue(message)
|
raise exception.InvalidValue(message)
|
||||||
|
|
||||||
|
|
||||||
class ImageNameType(NameType):
|
|
||||||
type_name = 'ImageNameType'
|
|
||||||
# ImageNameType allows to be Non-None or a string matches pattern
|
|
||||||
# `[a-zA-Z0-9][a-zA-Z0-9_.-].` with minimum length is 2 and maximum length
|
|
||||||
# 255 string type.
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def validate(cls, value, pattern=None):
|
|
||||||
if value is None:
|
|
||||||
message = _('Repo/Image is mandatory. Cannot be left blank.')
|
|
||||||
raise exception.InvalidValue(message)
|
|
||||||
return super(ImageNameType, cls).validate(value, pattern)
|
|
||||||
|
|
||||||
|
|
||||||
class Integer(object):
|
class Integer(object):
|
||||||
type_name = 'Integer'
|
type_name = 'Integer'
|
||||||
|
|
||||||
|
@ -67,10 +67,11 @@ class Container(base.APIBase):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'image': {
|
'image': {
|
||||||
'validate': types.ImageNameType.validate,
|
'validate': types.NameType.validate,
|
||||||
'validate_args': {
|
'validate_args': {
|
||||||
'pattern': types.image_name_pattern
|
'pattern': types.image_name_pattern
|
||||||
},
|
},
|
||||||
|
'mandatory': True
|
||||||
},
|
},
|
||||||
'links': {
|
'links': {
|
||||||
'validate': types.List(types.Custom(link.Link)).validate,
|
'validate': types.List(types.Custom(link.Link)).validate,
|
||||||
|
@ -48,10 +48,11 @@ class Image(base.APIBase):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'repo': {
|
'repo': {
|
||||||
'validate': types.ImageNameType.validate,
|
'validate': types.NameType.validate,
|
||||||
'validate_args': {
|
'validate_args': {
|
||||||
'pattern': types.image_name_pattern
|
'pattern': types.image_name_pattern
|
||||||
},
|
},
|
||||||
|
'mandatory': True
|
||||||
},
|
},
|
||||||
'tag': {
|
'tag': {
|
||||||
'validate': types.NameType.validate,
|
'validate': types.NameType.validate,
|
||||||
|
@ -264,6 +264,10 @@ class InvalidValue(Invalid):
|
|||||||
message = _("Received value '%(value)s' is invalid for type %(type)s.")
|
message = _("Received value '%(value)s' is invalid for type %(type)s.")
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationError(Invalid):
|
||||||
|
message = "%(detail)s"
|
||||||
|
|
||||||
|
|
||||||
class InvalidUUID(Invalid):
|
class InvalidUUID(Invalid):
|
||||||
message = _("Expected a uuid but received %(uuid)s.")
|
message = _("Expected a uuid but received %(uuid)s.")
|
||||||
|
|
||||||
|
@ -236,21 +236,6 @@ class TestTypes(test_base.BaseTestCase):
|
|||||||
value,
|
value,
|
||||||
pattern=types.container_name_pattern)
|
pattern=types.container_name_pattern)
|
||||||
|
|
||||||
def test_image_name_type(self):
|
|
||||||
valid_image_names = ['abc', 'ABC', '123', 'a12', 'A12', 'aA1', 'a_',
|
|
||||||
'A_', 'A-', 'a-', 'aa', 'a' * 255]
|
|
||||||
for value in valid_image_names:
|
|
||||||
self.assertEqual(
|
|
||||||
value, types.ImageNameType.validate(
|
|
||||||
value, pattern=types.image_name_pattern))
|
|
||||||
|
|
||||||
invalid_image_names = [None, 'a@', 'a', "", '*' * 265]
|
|
||||||
for value in invalid_image_names:
|
|
||||||
self.assertRaises(exception.InvalidValue,
|
|
||||||
types.ImageNameType.validate,
|
|
||||||
value,
|
|
||||||
pattern=types.image_name_pattern)
|
|
||||||
|
|
||||||
def test_container_memory_type(self):
|
def test_container_memory_type(self):
|
||||||
test_value = '4m'
|
test_value = '4m'
|
||||||
value = types.MemoryType.validate(test_value)
|
value = types.MemoryType.validate(test_value)
|
||||||
|
@ -52,6 +52,19 @@ class TestContainerController(api_base.FunctionalTest):
|
|||||||
self.assertEqual(202, response.status_int)
|
self.assertEqual(202, response.status_int)
|
||||||
self.assertTrue(mock_container_create.called)
|
self.assertTrue(mock_container_create.called)
|
||||||
|
|
||||||
|
@patch('zun.compute.api.API.container_create')
|
||||||
|
def test_create_container_image_not_specified(self, mock_container_create):
|
||||||
|
|
||||||
|
params = ('{"name": "MyDocker",'
|
||||||
|
'"command": "env", "memory": "512m",'
|
||||||
|
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||||
|
with self.assertRaisesRegexp(AppError,
|
||||||
|
"Required field image is missing"):
|
||||||
|
self.app.post('/v1/containers/',
|
||||||
|
params=params,
|
||||||
|
content_type='application/json')
|
||||||
|
self.assertTrue(mock_container_create.not_called)
|
||||||
|
|
||||||
@patch('zun.compute.api.API.container_create')
|
@patch('zun.compute.api.API.container_create')
|
||||||
def test_create_container_set_project_id_and_user_id(
|
def test_create_container_set_project_id_and_user_id(
|
||||||
self, mock_container_create):
|
self, mock_container_create):
|
||||||
|
@ -44,11 +44,12 @@ class TestImageController(api_base.FunctionalTest):
|
|||||||
|
|
||||||
@patch('zun.compute.api.API.image_pull')
|
@patch('zun.compute.api.API.image_pull')
|
||||||
def test_image_pull_with_no_repo(self, mock_image_pull):
|
def test_image_pull_with_no_repo(self, mock_image_pull):
|
||||||
mock_image_pull.side_effect = lambda x, y: y
|
params = {}
|
||||||
|
with self.assertRaisesRegexp(AppError,
|
||||||
self.assertRaises(AppError, self.app.post, '/v1/images/',
|
"Required field repo is missing"):
|
||||||
|
self.app.post('/v1/images/',
|
||||||
|
params=params,
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
|
|
||||||
self.assertTrue(mock_image_pull.not_called)
|
self.assertTrue(mock_image_pull.not_called)
|
||||||
|
|
||||||
@patch('zun.compute.api.API.image_pull')
|
@patch('zun.compute.api.API.image_pull')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user