Raising error if invalid attribute passed in.

400 will be returned when invalid attributes
are passed into Quantum API.

Fixed the some test cases failed since the
enforcement of invalid attribute checking

Fixes: bug #1076179

Change-Id: I4e9e2891c444f9dcd051f7b325d3c9403b28db86
This commit is contained in:
Jason Zhang 2013-02-12 18:40:12 -08:00
parent 61b2cf8e6e
commit 61bdda62e8
4 changed files with 38 additions and 5 deletions

View File

@ -482,6 +482,8 @@ class Controller(object):
Controller._populate_tenant_id(context, res_dict, is_create) Controller._populate_tenant_id(context, res_dict, is_create)
Controller._verify_attributes(res_dict, attr_info)
if is_create: # POST if is_create: # POST
for attr, attr_vals in attr_info.iteritems(): for attr, attr_vals in attr_info.iteritems():
if attr_vals['allow_post']: if attr_vals['allow_post']:
@ -522,6 +524,13 @@ class Controller(object):
raise webob.exc.HTTPBadRequest(msg) raise webob.exc.HTTPBadRequest(msg)
return body return body
@staticmethod
def _verify_attributes(res_dict, attr_info):
extra_keys = set(res_dict.keys()) - set(attr_info.keys())
if extra_keys:
msg = _("Unrecognized attribute(s) '%s'") % ', '.join(extra_keys)
raise webob.exc.HTTPBadRequest(msg)
def _validate_network_tenant_ownership(self, request, resource_item): def _validate_network_tenant_ownership(self, request, resource_item):
# TODO(salvatore-orlando): consider whether this check can be folded # TODO(salvatore-orlando): consider whether this check can be folded
# in the policy engine # in the policy engine

View File

@ -672,12 +672,26 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase):
expect_errors=True) expect_errors=True)
self.assertEqual(res.status_int, 400) self.assertEqual(res.status_int, 400)
def test_invalid_attribute_field(self):
data = {'network': {'invalid_key1': "foo1", 'invalid_key2': "foo2"}}
res = self.api.put(_get_path('networks', id=_uuid()),
self.serialize(data),
content_type='application/' + self.fmt,
expect_errors=True)
self.assertEqual(res.status_int, 400)
class SubresourceTest(unittest.TestCase): class SubresourceTest(unittest.TestCase):
def setUp(self): def setUp(self):
plugin = 'quantum.tests.unit.test_api_v2.TestSubresourcePlugin' plugin = 'quantum.tests.unit.test_api_v2.TestSubresourcePlugin'
QuantumManager._instance = None QuantumManager._instance = None
PluginAwareExtensionManager._instance = None PluginAwareExtensionManager._instance = None
# Save the global RESOURCE_ATTRIBUTE_MAP
self.saved_attr_map = {}
for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems():
self.saved_attr_map[resource] = attrs.copy()
args = ['--config-file', etcdir('quantum.conf.test')] args = ['--config-file', etcdir('quantum.conf.test')]
config.parse(args=args) config.parse(args=args)
cfg.CONF.set_override('core_plugin', plugin) cfg.CONF.set_override('core_plugin', plugin)
@ -690,7 +704,15 @@ class SubresourceTest(unittest.TestCase):
'parent': {'collection_name': 'networks', 'parent': {'collection_name': 'networks',
'member_name': 'network'} 'member_name': 'network'}
} }
attributes.RESOURCE_ATTRIBUTE_MAP['dummies'] = {
'foo': {'allow_post': True, 'allow_put': True,
'validate': {'type:string': None},
'default': '', 'is_visible': True},
'tenant_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'required_by_policy': True,
'is_visible': True}
}
api = router.APIRouter() api = router.APIRouter()
self.api = webtest.TestApp(api) self.api = webtest.TestApp(api)
@ -699,6 +721,8 @@ class SubresourceTest(unittest.TestCase):
self.api = None self.api = None
self.plugin = None self.plugin = None
cfg.CONF.reset() cfg.CONF.reset()
# Restore the global RESOURCE_ATTRIBUTE_MAP
attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
def test_index_sub_resource(self): def test_index_sub_resource(self):
instance = self.plugin.return_value instance = self.plugin.return_value
@ -732,7 +756,7 @@ class SubresourceTest(unittest.TestCase):
instance = self.plugin.return_value instance = self.plugin.return_value
dummy_id = _uuid() dummy_id = _uuid()
body = {'dummy': {'foo': 'bar', 'tenant_id': _uuid()}} body = {'dummy': {'foo': 'bar'}}
self.api.put_json('/networks/id1' + _get_path('dummies', id=dummy_id), self.api.put_json('/networks/id1' + _get_path('dummies', id=dummy_id),
body) body)
instance.update_network_dummy.assert_called_once_with(mock.ANY, instance.update_network_dummy.assert_called_once_with(mock.ANY,

View File

@ -1503,7 +1503,7 @@ class TestNetworksV2(QuantumDbPluginV2TestCase):
name = 'net1' name = 'net1'
keys = [('subnets', []), ('name', name), ('admin_state_up', True), keys = [('subnets', []), ('name', name), ('admin_state_up', True),
('status', 'ACTIVE'), ('shared', False)] ('status', 'ACTIVE'), ('shared', False)]
with self.network(name=name, arg_list=('test',), test=None) as net: with self.network(name=name) as net:
for k, v in keys: for k, v in keys:
self.assertEqual(net['network'][k], v) self.assertEqual(net['network'][k], v)

View File

@ -146,8 +146,8 @@ class ServiceTypeExtensionTestCase(ServiceTypeTestCaseBase):
tenant_id = 'fake' tenant_id = 'fake'
if env and 'quantum.context' in env: if env and 'quantum.context' in env:
tenant_id = env['quantum.context'].tenant_id tenant_id = env['quantum.context'].tenant_id
data = {self.resource_name: {'name': svc_type_name, data = {self.resource_name: {'name': svc_type_name}}
'tenant-id': tenant_id}}
svc_type_id = _uuid() svc_type_id = _uuid()
return_value = {'id': svc_type_id, return_value = {'id': svc_type_id,
'name': svc_type_name} 'name': svc_type_name}