consume neutron-lib resources attr map

Today we shim the RESOURCE_ATTRIBUTE_MAP in neutron; it references the
equivelant in neutron-lib named RESOURCES.

This patch removes neutron's RESOURCE_ATTRIBUTE_MAP and cleans up
neutron.api.v2.attributes in prep to delete it.
To do so:
- CORE_RESOURCES and RESOURCE_FOREIGN_KEYS are moved to the single
module that references them respectively and the are made private (no
consumers use them).
- get_collection_info is removed and instead the 2 uses in neutron
just use the get() method of the RESOURCES map. There are no external
uses of get_collection_info.
- References using RESOURCE_ATTRIBUTE_MAP are switched over to
neutron-lib's RESOURCES.
- The neutron.api.v2.attributes module is removed as it's empty now.
- A few api attribute UTs are removed; there's nothing to test as per
this patch.

NeutronLibImpact

Change-Id: Iaacee584d499c4d33d6d2dd9609c7ac0f2cfc386
This commit is contained in:
Boden R 2018-01-11 15:40:52 -07:00
parent 6e65876138
commit 44292f4c9a
14 changed files with 42 additions and 104 deletions

View File

@ -195,8 +195,8 @@ The check, performed in the ``__call__`` method, works as follows:
``network`` resource;
* if no parent resource or target field could be identified raise a
``PolicyCheckError`` exception;
* Retrieve a 'parent foreign key' from the ``RESOURCE_FOREIGN_KEYS`` data
structure in ``neutron.api.v2.attributes``. This foreign key is simply the
* Retrieve a 'parent foreign key' from the ``_RESOURCE_FOREIGN_KEYS`` data
structure in ``neutron.policy``. This foreign key is simply the
attribute acting as a primary key in the parent resource. A
``PolicyCheckError`` exception will be raised if such 'parent foreign key'
cannot be retrieved;
@ -288,7 +288,7 @@ Notes
imply a round-trip to the backend. This class of checks, when involving
retrieving attributes for 'parent' resources should be used very sparingly.
* In order for ``OwnerCheck`` rules to work, parent resources should have an
entry in ``neutron.api.v2.attributes.RESOURCE_FOREIGN_KEYS``; moreover the
entry in ``neutron.policy._RESOURCE_FOREIGN_KEYS``; moreover the
resource must be managed by the 'core' plugin (ie: the one defined in the
core_plugin configuration variable)

View File

@ -1,43 +0,0 @@
# Copyright (c) 2012 OpenStack Foundation.
# 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.
from neutron_lib.api import attributes as attrs
from neutron_lib.api.definitions import network as net_def
from neutron_lib.api.definitions import port as port_def
from neutron_lib.api.definitions import subnet as subnet_def
from neutron_lib.api.definitions import subnetpool as subnetpool_def
# Define constants for base resource name
CORE_RESOURCES = {net_def.RESOURCE_NAME: net_def.COLLECTION_NAME,
subnet_def.RESOURCE_NAME: subnet_def.COLLECTION_NAME,
subnetpool_def.RESOURCE_NAME: subnetpool_def.COLLECTION_NAME,
port_def.RESOURCE_NAME: port_def.COLLECTION_NAME}
RESOURCE_ATTRIBUTE_MAP = attrs.RESOURCES
# Identify the attribute used by a resource to reference another resource
RESOURCE_FOREIGN_KEYS = {
net_def.COLLECTION_NAME: 'network_id'
}
def get_collection_info(collection):
"""Helper function to retrieve attribute info.
:param collection: Collection or plural name of the resource
"""
return RESOURCE_ATTRIBUTE_MAP.get(collection)

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api import attributes
from neutron_lib.api import converters
from neutron_lib.db import constants as db_const
from neutron_lib import exceptions as n_exc
@ -22,7 +23,6 @@ import pecan
from pecan import request
from neutron._i18n import _
from neutron.api.v2 import attributes
from neutron.pecan_wsgi.controllers import utils
from neutron.quota import resource_registry
@ -83,7 +83,7 @@ class QuotaController(utils.NeutronPecanController):
"%ss" % RESOURCE_NAME, RESOURCE_NAME)
# Ensure limits for all registered resources are returned
attr_dict = attributes.RESOURCE_ATTRIBUTE_MAP[self.collection]
attr_dict = attributes.RESOURCES[self.collection]
for quota_resource in resource_registry.get_all_resources().keys():
attr_dict[quota_resource] = {
'allow_post': False,

View File

@ -14,13 +14,16 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api.definitions import network as net_def
from neutron_lib.api.definitions import port as port_def
from neutron_lib.api.definitions import subnet as subnet_def
from neutron_lib.api.definitions import subnetpool as subnetpool_def
from oslo_config import cfg
from oslo_log import log
import pecan
from pecan import request
import six.moves.urllib.parse as urlparse
from neutron.api.v2 import attributes
from neutron.api.views import versions as versions_view
from neutron import manager
from neutron.pecan_wsgi.controllers import extensions as ext_ctrl
@ -31,6 +34,11 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
_VERSION_INFO = {}
_CORE_RESOURCES = {net_def.RESOURCE_NAME: net_def.COLLECTION_NAME,
subnet_def.RESOURCE_NAME: subnet_def.COLLECTION_NAME,
subnetpool_def.RESOURCE_NAME:
subnetpool_def.COLLECTION_NAME,
port_def.RESOURCE_NAME: port_def.COLLECTION_NAME}
def _load_version_info(version_info):
@ -88,7 +96,7 @@ class V2Controller(object):
pecan.abort(404)
layout = []
for name, collection in attributes.CORE_RESOURCES.items():
for name, collection in _CORE_RESOURCES.items():
href = urlparse.urljoin(pecan.request.path_url, collection)
resource = {'name': name,
'collection': collection,

View File

@ -17,6 +17,7 @@ from collections import defaultdict
import copy
import functools
from neutron_lib.api import attributes
from neutron_lib import constants
from oslo_log import log as logging
from oslo_utils import excutils
@ -25,7 +26,6 @@ from pecan import request
from neutron._i18n import _
from neutron.api import api_common
from neutron.api.v2 import attributes as api_attributes
from neutron.db import api as db_api
from neutron import manager
from neutron_lib import exceptions
@ -210,7 +210,7 @@ class NeutronPecanController(object):
@property
def resource_info(self):
if not self._resource_info:
self._resource_info = api_attributes.get_collection_info(
self._resource_info = attributes.RESOURCES.get(
self.collection)
return self._resource_info

View File

@ -13,10 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api import attributes
from neutron_lib.plugins import directory
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base
from neutron import manager
from neutron.pecan_wsgi.controllers import resource as res_ctrl
@ -38,7 +38,7 @@ RESOURCES = {'network': 'networks',
def initialize_all():
manager.init()
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)
ext_mgr.extend_resources("2.0", attributes.RESOURCES)
# At this stage we have a fully populated resource attribute map;
# build Pecan controllers and routes for all core resources
plugin = directory.get_plugin()

View File

@ -33,7 +33,6 @@ from oslo_utils import excutils
import webob.exc
from neutron._i18n import _
from neutron.api.v2 import attributes
from neutron.common import exceptions as n_exc
@ -153,7 +152,7 @@ def in_pending_status(status):
def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[attr_name]
attr_info = lib_attrs.RESOURCES[attr_name]
attr_ops = lib_attrs.AttributeInfo(attr_info)
try:
attr_ops.populate_project_id(context, res_dict, True)

View File

@ -16,6 +16,8 @@
import collections
import re
from neutron_lib.api import attributes
from neutron_lib.api.definitions import network as net_apidef
from neutron_lib import constants
from neutron_lib import context
from neutron_lib import exceptions
@ -28,7 +30,6 @@ from oslo_utils import excutils
import six
from neutron._i18n import _
from neutron.api.v2 import attributes
from neutron.common import cache_utils as cache
from neutron.common import constants as const
@ -39,6 +40,11 @@ _ENFORCER = None
ADMIN_CTX_POLICY = 'context_is_admin'
ADVSVC_CTX_POLICY = 'context_is_advsvc'
# Identify the attribute used by a resource to reference another resource
_RESOURCE_FOREIGN_KEYS = {
net_apidef.COLLECTION_NAME: 'network_id'
}
def reset():
global _ENFORCER
@ -160,7 +166,7 @@ def _build_match_rule(action, target, pluralized):
action, pluralized)
if enforce_attr_based_check:
# assigning to variable with short name for improving readability
res_map = attributes.RESOURCE_ATTRIBUTE_MAP
res_map = attributes.RESOURCES
if resource in res_map:
for attribute_name in res_map[resource]:
if _is_attribute_explicitly_set(attribute_name,
@ -264,7 +270,7 @@ class OwnerCheck(policy.Check):
raise exceptions.PolicyCheckError(
policy="%s:%s" % (self.kind, self.match),
reason=err_reason)
parent_foreign_key = attributes.RESOURCE_FOREIGN_KEYS.get(
parent_foreign_key = _RESOURCE_FOREIGN_KEYS.get(
"%ss" % parent_res, None)
if not parent_foreign_key:
err_reason = (_("Unable to verify match:%(match)s as the "
@ -296,7 +302,7 @@ class FieldCheck(policy.Check):
# Value might need conversion - we need help from the attribute map
try:
attr = attributes.RESOURCE_ATTRIBUTE_MAP[resource][field]
attr = attributes.RESOURCES[resource][field]
conv_func = attr['convert_to']
except KeyError:
conv_func = lambda x: x

View File

@ -15,11 +15,11 @@
import os.path
from neutron_lib.api import attributes
from neutron_lib import context
from neutron_lib import fixture
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron import policy
from neutron.tests import base
@ -69,7 +69,7 @@ class APIPolicyTestCase(base.BaseTestCase):
admin_context = context.get_admin_context()
tenant_context = context.Context('test_user', 'test_tenant_id', False)
extension_manager.extend_resources(self.api_version,
attributes.RESOURCE_ATTRIBUTE_MAP)
attributes.RESOURCES)
self.assertTrue(self._check_external_router_policy(admin_context))
self.assertFalse(self._check_external_router_policy(tenant_context))
@ -82,7 +82,7 @@ class APIPolicyTestCase(base.BaseTestCase):
policy.reset()
extension_manager = extensions.ExtensionManager(self.extension_path)
extension_manager.extend_resources(self.api_version,
attributes.RESOURCE_ATTRIBUTE_MAP)
attributes.RESOURCES)
policy.init()
admin_context = context.get_admin_context()
tenant_context = context.Context('test_user', 'test_tenant_id', False)

View File

@ -14,6 +14,7 @@
# under the License.
import mock
from neutron_lib.api import attributes
from neutron_lib.callbacks import events
from neutron_lib import context
from neutron_lib.db import constants as db_const
@ -22,7 +23,6 @@ from oslo_config import cfg
from oslo_policy import policy as oslo_policy
from oslo_serialization import jsonutils
from neutron.api.v2 import attributes
from neutron.db.quota import driver as quota_driver
from neutron import manager
from neutron.pecan_wsgi.controllers import resource
@ -159,7 +159,7 @@ class TestPolicyEnforcementHook(test_functional.PecanFunctionalTest):
# tests, or at least I hope so)
super(TestPolicyEnforcementHook, self).setUp()
self.mock_plugin = mock.Mock()
attributes.RESOURCE_ATTRIBUTE_MAP.update(self.FAKE_RESOURCE)
attributes.RESOURCES.update(self.FAKE_RESOURCE)
manager.NeutronManager.set_plugin_for_resource('mehs',
self.mock_plugin)
fake_controller = resource.CollectionsController('mehs', 'meh')

View File

@ -1,32 +0,0 @@
# Copyright 2012 OpenStack Foundation
# 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.
from neutron.api.v2 import attributes
from neutron.tests import base
class TestHelpers(base.DietTestCase):
def _verify_port_attributes(self, attrs):
for test_attribute in ('id', 'name', 'mac_address', 'network_id',
'tenant_id', 'fixed_ips', 'status'):
self.assertIn(test_attribute, attrs)
def test_get_collection_info(self):
attrs = attributes.get_collection_info('ports')
self._verify_port_attributes(attrs)
def test_get_collection_info_missing(self):
self.assertFalse(attributes.get_collection_info('meh'))

View File

@ -16,6 +16,7 @@
import os
import mock
from neutron_lib.api import attributes
from neutron_lib.api import converters
from neutron_lib.callbacks import registry
from neutron_lib import constants
@ -35,7 +36,6 @@ import webtest
from neutron.api import api_common
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base as v2_base
from neutron.api.v2 import router
from neutron import policy
@ -125,7 +125,7 @@ class APIv2TestCase(APIv2TestBase):
return sorted(policy_attrs)
def _do_field_list(self, resource, base_fields):
attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[resource]
attr_info = attributes.RESOURCES[resource]
policy_attrs = self._get_policy_attrs(attr_info)
for name, info in attr_info.items():
if info.get('primary_key'):
@ -1260,7 +1260,7 @@ class V2Views(base.BaseTestCase):
def _view(self, keys, collection, resource):
data = dict((key, 'value') for key in keys)
data['fake'] = 'value'
attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[collection]
attr_info = attributes.RESOURCES[collection]
controller = v2_base.Controller(None, collection, resource, attr_info)
res = controller._view(context.get_admin_context(), data)
self.assertNotIn('fake', res)

View File

@ -10,12 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api import attributes
from neutron_lib import context
from oslo_utils import uuidutils
import testscenarios
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.common import config
import neutron.extensions
from neutron.objects.qos import policy
@ -87,7 +87,7 @@ class TestTagApiBase(test_securitygroup.SecurityGroupsTestCase,
extensions_path, {'router': l3_plugin, 'TAG': plugin,
'sec': sec_plugin}
)
ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)
ext_mgr.extend_resources("2.0", attributes.RESOURCES)
app = config.load_paste_app('extensions_test_app')
self.ext_api = extensions.ExtensionMiddleware(app, ext_mgr=ext_mgr)

View File

@ -16,6 +16,7 @@
"""Test of Policy Engine For Neutron"""
import mock
from neutron_lib.api import attributes
from neutron_lib import constants
from neutron_lib import context
from neutron_lib import exceptions
@ -29,7 +30,6 @@ from oslo_serialization import jsonutils
from oslo_utils import importutils
import neutron
from neutron.api.v2 import attributes
from neutron.common import constants as n_const
from neutron import policy
from neutron.tests import base
@ -207,7 +207,7 @@ class NeutronPolicyTestCase(base.BaseTestCase):
def setUp(self):
super(NeutronPolicyTestCase, self).setUp()
# Add Fake resources to RESOURCE_ATTRIBUTE_MAP
attributes.RESOURCE_ATTRIBUTE_MAP.update(FAKE_RESOURCES)
attributes.RESOURCES.update(FAKE_RESOURCES)
self._set_rules()
self.patcher = mock.patch.object(neutron.policy,