Merge "V3 jsonschema validation: Group type specs"

This commit is contained in:
Zuul 2017-12-14 17:17:23 +00:00 committed by Gerrit Code Review
commit db2ae0902a
3 changed files with 64 additions and 34 deletions

View 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
})

View File

@ -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())

View File

@ -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)