diff --git a/quantum/api/v2/base.py b/quantum/api/v2/base.py index 9c9c0c494..8f6267701 100644 --- a/quantum/api/v2/base.py +++ b/quantum/api/v2/base.py @@ -515,6 +515,8 @@ class Controller(object): Controller._populate_tenant_id(context, res_dict, is_create) + Controller._verify_attributes(res_dict, attr_info) + if is_create: # POST for attr, attr_vals in attr_info.iteritems(): if attr_vals['allow_post']: @@ -555,6 +557,13 @@ class Controller(object): raise webob.exc.HTTPBadRequest(msg) 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): # TODO(salvatore-orlando): consider whether this check can be folded # in the policy engine diff --git a/quantum/tests/unit/test_api_v2.py b/quantum/tests/unit/test_api_v2.py index f5510058b..0256fe3b8 100644 --- a/quantum/tests/unit/test_api_v2.py +++ b/quantum/tests/unit/test_api_v2.py @@ -1101,12 +1101,26 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): expect_errors=True) 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): def setUp(self): plugin = 'quantum.tests.unit.test_api_v2.TestSubresourcePlugin' QuantumManager._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')] config.parse(args=args) cfg.CONF.set_override('core_plugin', plugin) @@ -1119,7 +1133,15 @@ class SubresourceTest(unittest.TestCase): 'parent': {'collection_name': 'networks', '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() self.api = webtest.TestApp(api) @@ -1129,6 +1151,8 @@ class SubresourceTest(unittest.TestCase): self.plugin = None router.SUB_RESOURCES = {} cfg.CONF.reset() + # Restore the global RESOURCE_ATTRIBUTE_MAP + attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map def test_index_sub_resource(self): instance = self.plugin.return_value @@ -1162,7 +1186,7 @@ class SubresourceTest(unittest.TestCase): instance = self.plugin.return_value 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), body) instance.update_network_dummy.assert_called_once_with(mock.ANY, diff --git a/quantum/tests/unit/test_db_plugin.py b/quantum/tests/unit/test_db_plugin.py index 5d2fb2a7d..d78213f5e 100644 --- a/quantum/tests/unit/test_db_plugin.py +++ b/quantum/tests/unit/test_db_plugin.py @@ -1715,7 +1715,7 @@ class TestNetworksV2(QuantumDbPluginV2TestCase): name = 'net1' keys = [('subnets', []), ('name', name), ('admin_state_up', True), ('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: self.assertEqual(net['network'][k], v) diff --git a/quantum/tests/unit/test_servicetype.py b/quantum/tests/unit/test_servicetype.py index bfac2c8b4..5319ffcc3 100644 --- a/quantum/tests/unit/test_servicetype.py +++ b/quantum/tests/unit/test_servicetype.py @@ -146,8 +146,8 @@ class ServiceTypeExtensionTestCase(ServiceTypeTestCaseBase): tenant_id = 'fake' if env and 'quantum.context' in env: tenant_id = env['quantum.context'].tenant_id - data = {self.resource_name: {'name': svc_type_name, - 'tenant-id': tenant_id}} + data = {self.resource_name: {'name': svc_type_name}} + svc_type_id = _uuid() return_value = {'id': svc_type_id, 'name': svc_type_name}