Merge "V3 jsonschema validation: Group type specs"
This commit is contained in:
commit
db2ae0902a
43
cinder/api/schemas/group_specs.py
Normal file
43
cinder/api/schemas/group_specs.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Copyright (C) 2017 NTT DATA
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
|
|
||||||
|
group_specs_with_no_spaces_key_and_value_null = {
|
||||||
|
'type': 'object',
|
||||||
|
'patternProperties': {
|
||||||
|
'^[a-zA-Z0-9-_:.]{1,255}$': {
|
||||||
|
'type': ['string', 'null'], 'maxLength': 255
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'additionalProperties': False
|
||||||
|
}
|
||||||
|
|
||||||
|
create = {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'type': 'object',
|
||||||
|
'group_specs': group_specs_with_no_spaces_key_and_value_null,
|
||||||
|
},
|
||||||
|
'required': ['group_specs'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
update = copy.deepcopy(group_specs_with_no_spaces_key_and_value_null)
|
||||||
|
update.update({
|
||||||
|
'minProperties': 1,
|
||||||
|
'maxProperties': 1
|
||||||
|
})
|
@ -17,15 +17,15 @@
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import common
|
|
||||||
from cinder.api import microversions as mv
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
|
from cinder.api.schemas import group_specs
|
||||||
|
from cinder.api import validation
|
||||||
from cinder import db
|
from cinder import db
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder.policies import group_types as policy
|
from cinder.policies import group_types as policy
|
||||||
from cinder import rpc
|
from cinder import rpc
|
||||||
from cinder import utils
|
|
||||||
from cinder.volume import group_types
|
from cinder.volume import group_types
|
||||||
|
|
||||||
|
|
||||||
@ -55,16 +55,13 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
|
|
||||||
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, group_type_id, body=None):
|
@validation.schema(group_specs.create)
|
||||||
|
def create(self, req, group_type_id, body):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
context.authorize(policy.SPEC_POLICY)
|
context.authorize(policy.SPEC_POLICY)
|
||||||
self.assert_valid_body(body, 'group_specs')
|
|
||||||
|
|
||||||
self._check_type(context, group_type_id)
|
self._check_type(context, group_type_id)
|
||||||
specs = body['group_specs']
|
specs = body['group_specs']
|
||||||
self._check_key_names(specs.keys())
|
|
||||||
utils.validate_dictionary_string_length(specs)
|
|
||||||
|
|
||||||
db.group_type_specs_update_or_create(context,
|
db.group_type_specs_update_or_create(context,
|
||||||
group_type_id,
|
group_type_id,
|
||||||
specs)
|
specs)
|
||||||
@ -75,22 +72,15 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
return body
|
return body
|
||||||
|
|
||||||
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def update(self, req, group_type_id, id, body=None):
|
@validation.schema(group_specs.update)
|
||||||
|
def update(self, req, group_type_id, id, body):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
context.authorize(policy.SPEC_POLICY)
|
context.authorize(policy.SPEC_POLICY)
|
||||||
|
|
||||||
if not body:
|
|
||||||
expl = _('Request body empty')
|
|
||||||
raise webob.exc.HTTPBadRequest(explanation=expl)
|
|
||||||
self._check_type(context, group_type_id)
|
self._check_type(context, group_type_id)
|
||||||
if id not in body:
|
if id not in body:
|
||||||
expl = _('Request body and URI mismatch')
|
expl = _('Request body and URI mismatch')
|
||||||
raise webob.exc.HTTPBadRequest(explanation=expl)
|
raise webob.exc.HTTPBadRequest(explanation=expl)
|
||||||
if len(body) > 1:
|
|
||||||
expl = _('Request body contains too many items')
|
|
||||||
raise webob.exc.HTTPBadRequest(explanation=expl)
|
|
||||||
self._check_key_names(body.keys())
|
|
||||||
utils.validate_dictionary_string_length(body)
|
|
||||||
|
|
||||||
db.group_type_specs_update_or_create(context,
|
db.group_type_specs_update_or_create(context,
|
||||||
group_type_id,
|
group_type_id,
|
||||||
@ -137,13 +127,6 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
notifier_info)
|
notifier_info)
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
def _check_key_names(self, keys):
|
|
||||||
if not common.validate_key_names(keys):
|
|
||||||
expl = _('Key names can only contain alphanumeric characters, '
|
|
||||||
'underscores, periods, colons and hyphens.')
|
|
||||||
|
|
||||||
raise webob.exc.HTTPBadRequest(explanation=expl)
|
|
||||||
|
|
||||||
|
|
||||||
def create_resource():
|
def create_resource():
|
||||||
return wsgi.Resource(GroupTypeSpecsController())
|
return wsgi.Resource(GroupTypeSpecsController())
|
||||||
|
@ -18,6 +18,7 @@ import webob
|
|||||||
|
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import db
|
from cinder import db
|
||||||
|
from cinder import exception
|
||||||
from cinder import rpc
|
from cinder import rpc
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
|
||||||
@ -90,7 +91,8 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=mv.GROUP_TYPE)
|
version=mv.GROUP_TYPE)
|
||||||
self.controller.create(req, fake.GROUP_ID, create_fake_group_specs)
|
self.controller.create(req, fake.GROUP_ID,
|
||||||
|
body=create_fake_group_specs)
|
||||||
self.assertTrue(mock_rpc_notifier.called)
|
self.assertTrue(mock_rpc_notifier.called)
|
||||||
|
|
||||||
@mock.patch.object(rpc, 'get_notifier')
|
@mock.patch.object(rpc, 'get_notifier')
|
||||||
@ -111,7 +113,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
self.controller.update(req,
|
self.controller.update(req,
|
||||||
fake.GROUP_TYPE_ID,
|
fake.GROUP_TYPE_ID,
|
||||||
'id',
|
'id',
|
||||||
update_fake_group_specs)
|
body=update_fake_group_specs)
|
||||||
self.assertTrue(mock_rpc_notifier.called)
|
self.assertTrue(mock_rpc_notifier.called)
|
||||||
|
|
||||||
@mock.patch.object(db, 'group_type_specs_get',
|
@mock.patch.object(db, 'group_type_specs_get',
|
||||||
@ -155,7 +157,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
self.controller.create,
|
self.controller.create,
|
||||||
req,
|
req,
|
||||||
fake.GROUP_ID,
|
fake.GROUP_ID,
|
||||||
create_fake_group_specs)
|
body=create_fake_group_specs)
|
||||||
|
|
||||||
@mock.patch.object(rpc, 'get_notifier')
|
@mock.patch.object(rpc, 'get_notifier')
|
||||||
@mock.patch.object(db, 'group_type_get', return_value={})
|
@mock.patch.object(db, 'group_type_get', return_value={})
|
||||||
@ -178,15 +180,17 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=mv.GROUP_TYPE)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(exception.ValidationError,
|
||||||
self.controller.update,
|
self.controller.update,
|
||||||
req,
|
req,
|
||||||
fake.GROUP_TYPE_ID,
|
fake.GROUP_TYPE_ID,
|
||||||
'id')
|
'id', body=None)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
|
self.assertRaises(exception.ValidationError, self.controller.update,
|
||||||
req, fake.GROUP_TYPE_ID, 'id', fake_group_specs)
|
req, fake.GROUP_TYPE_ID, 'id',
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
|
body=fake_group_specs)
|
||||||
req, fake.GROUP_TYPE_ID, 'key1', fake_group_specs)
|
self.assertRaises(exception.ValidationError, self.controller.update,
|
||||||
|
req, fake.GROUP_TYPE_ID, 'key1',
|
||||||
|
body=fake_group_specs)
|
||||||
|
|
||||||
@mock.patch.object(db, 'group_type_specs_get',
|
@mock.patch.object(db, 'group_type_specs_get',
|
||||||
return_value=fake_group_specs)
|
return_value=fake_group_specs)
|
||||||
@ -216,5 +220,5 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=mv.GROUP_TYPE)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(exception.ValidationError, self.controller.create,
|
||||||
req, fake.GROUP_ID, incorrect_fake_group_specs)
|
req, fake.GROUP_ID, body=incorrect_fake_group_specs)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user