def setUp(self): # Create a controller for a fake resource. This will make the tests # independent from the evolution of the API (so if one changes the API # or the default policies there won't be any risk of breaking these # tests, or at least I hope so) super(TestPolicyEnforcementHook, self).setUp() self.mock_plugin = mock.Mock() attributes.RESOURCE_ATTRIBUTE_MAP.update(self.FAKE_RESOURCE) manager.NeutronManager.set_plugin_for_resource('mehs', self.mock_plugin) fake_controller = resource.CollectionsController('mehs', 'meh') manager.NeutronManager.set_controller_for_resource( 'mehs', fake_controller) # Inject policies for the fake resource policy.init() policy._ENFORCER.set_rules(oslo_policy.Rules.from_dict({ 'create_meh': '', 'update_meh': 'rule:admin_only', 'delete_meh': 'rule:admin_only', 'get_meh': 'rule:admin_only or field:mehs:id=xxx', 'get_meh:restricted_attr': 'rule:admin_only' }), overwrite=False)
def initialize_all(): manager.init() ext_mgr = extensions.PluginAwareExtensionManager.get_instance() ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP) # At this stage we have a fully populated resource attribute map; # build Pecan controllers and routes for all core resources plugin = directory.get_plugin() for resource, collection in router.RESOURCES.items(): resource_registry.register_resource_by_name(resource) new_controller = res_ctrl.CollectionsController(collection, resource, plugin=plugin) manager.NeutronManager.set_controller_for_resource( collection, new_controller) manager.NeutronManager.set_plugin_for_resource(collection, plugin) pecanized_resources = ext_mgr.get_pecan_resources() for pec_res in pecanized_resources: manager.NeutronManager.set_controller_for_resource( pec_res.collection, pec_res.controller) manager.NeutronManager.set_plugin_for_resource(pec_res.collection, pec_res.plugin) # Now build Pecan Controllers and routes for all extensions resources = ext_mgr.get_resources() # Extensions controller is already defined, we don't need it. resources.pop(0) for ext_res in resources: path_prefix = ext_res.path_prefix.strip('/') collection = ext_res.collection # Retrieving the parent resource. It is expected the format of # the parent resource to be: # {'collection_name': 'name-of-collection', # 'member_name': 'name-of-resource'} # collection_name does not appear to be used in the legacy code # inside the controller logic, so we can assume we do not need it. parent = ext_res.parent or {} parent_resource = parent.get('member_name') collection_key = collection if parent_resource: collection_key = '/'.join([parent_resource, collection]) collection_actions = ext_res.collection_actions member_actions = ext_res.member_actions if manager.NeutronManager.get_controller_for_resource(collection_key): # This is a collection that already has a pecan controller, we # do not need to do anything else continue legacy_controller = getattr(ext_res.controller, 'controller', ext_res.controller) new_controller = None if isinstance(legacy_controller, base.Controller): resource = legacy_controller.resource plugin = legacy_controller.plugin attr_info = legacy_controller.attr_info member_actions = legacy_controller.member_actions pagination = legacy_controller.allow_pagination sorting = legacy_controller.allow_sorting # NOTE(blogan): legacy_controller and ext_res both can both have # member_actions. the member_actions for ext_res are strictly for # routing, while member_actions for legacy_controller are used for # handling the request once the routing has found the controller. # They're always the same so we will just use the ext_res # member_action. new_controller = res_ctrl.CollectionsController( collection, resource, resource_info=attr_info, parent_resource=parent_resource, member_actions=member_actions, plugin=plugin, allow_pagination=pagination, allow_sorting=sorting, collection_actions=collection_actions) # new_controller.collection has replaced hyphens with underscores manager.NeutronManager.set_plugin_for_resource( new_controller.collection, plugin) if path_prefix: manager.NeutronManager.add_resource_for_path_prefix( collection, path_prefix) elif isinstance(legacy_controller, wsgi.Controller): new_controller = utils.ShimCollectionsController( collection, None, legacy_controller, collection_actions=collection_actions, member_actions=member_actions) else: LOG.warning( _LW("Unknown controller type encountered %s. It will" "be ignored."), legacy_controller) manager.NeutronManager.set_controller_for_resource( collection_key, new_controller) # Certain policy checks require that the extensions are loaded # and the RESOURCE_ATTRIBUTE_MAP populated before they can be # properly initialized. This can only be claimed with certainty # once this point in the code has been reached. In the event # that the policies have been initialized before this point, # calling reset will cause the next policy check to # re-initialize with all of the required data in place. policy.reset()
def initialize_all(): ext_mgr = extensions.PluginAwareExtensionManager.get_instance() ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP) # At this stage we have a fully populated resource attribute map; # build Pecan controllers and routes for every resource (both core # and extensions) pecanized_exts = [ ext for ext in ext_mgr.extensions.values() if hasattr(ext, 'get_pecan_controllers') ] non_pecanized_exts = set(ext_mgr.extensions.values()) - set(pecanized_exts) pecan_controllers = {} for ext in pecanized_exts: LOG.info( _LI("Extension %s is pecan-aware. Fetching resources " "and controllers"), ext.get_name()) controllers = ext.get_pecan_controllers() # controllers is actually a list of pairs where the first element is # the collection name and the second the actual controller for (collection, coll_controller) in controllers: pecan_controllers[collection] = coll_controller for collection in attributes.RESOURCE_ATTRIBUTE_MAP: resource = _handle_plurals(collection) plugin = _plugin_for_resource(collection) if plugin: manager.NeutronManager.set_plugin_for_resource(resource, plugin) else: LOG.warning( _LW("No plugin found for resource:%s. API calls " "may not be correctly dispatched"), resource) controller = pecan_controllers.get(collection) if not controller: LOG.debug("Building controller for resource:%s", resource) controller = res_ctrl.CollectionsController(collection, resource) else: LOG.debug("There are already controllers for resource: %s", resource) manager.NeutronManager.set_controller_for_resource( controller.collection, controller) LOG.info( _LI("Added controller for resource %(resource)s " "via URI path segment:%(collection)s"), { 'resource': resource, 'collection': collection }) initialize_legacy_extensions(non_pecanized_exts) # NOTE(salv-orlando): If you are care about code quality, please read below # Hackiness is strong with the piece of code below. It is used for # populating resource plurals and registering resources with the quota # engine, but the method it calls were not conceived with this aim. # Therefore it only leverages side-effects from those methods. Moreover, # as it is really not advisable to load an instance of # neutron.api.v2.router.APIRouter just to register resources with the # quota engine, core resources are explicitly registered here. # TODO(salv-orlando): The Pecan WSGI support should provide its own # solution to manage resource plurals and registration of resources with # the quota engine for resource in router.RESOURCES.keys(): resource_registry.register_resource_by_name(resource) for ext in ext_mgr.extensions.values(): # make each extension populate its plurals if hasattr(ext, 'get_resources'): ext.get_resources() if hasattr(ext, 'get_extended_resources'): ext.get_extended_resources('v2.0') # Certain policy checks require that the extensions are loaded # and the RESOURCE_ATTRIBUTE_MAP populated before they can be # properly initialized. This can only be claimed with certainty # once this point in the code has been reached. In the event # that the policies have been initialized before this point, # calling reset will cause the next policy check to # re-initialize with all of the required data in place. policy.reset()
def initialize_all(): ext_mgr = extensions.PluginAwareExtensionManager.get_instance() ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP) # At this stage we have a fully populated resource attribute map; # build Pecan controllers and routes for all core resources for resource, collection in router.RESOURCES.items(): resource_registry.register_resource_by_name(resource) plugin = manager.NeutronManager.get_plugin() new_controller = res_ctrl.CollectionsController(collection, resource, plugin=plugin) manager.NeutronManager.set_controller_for_resource( collection, new_controller) manager.NeutronManager.set_plugin_for_resource(resource, plugin) pecanized_resources = ext_mgr.get_pecan_resources() for pec_res in pecanized_resources: resource = attributes.PLURALS[pec_res.collection] manager.NeutronManager.set_controller_for_resource( pec_res.collection, pec_res.controller) manager.NeutronManager.set_plugin_for_resource(resource, pec_res.plugin) # Now build Pecan Controllers and routes for all extensions resources = ext_mgr.get_resources() # Extensions controller is already defined, we don't need it. resources.pop(0) for ext_res in resources: path_prefix = ext_res.path_prefix.strip('/') collection = ext_res.collection if manager.NeutronManager.get_controller_for_resource(collection): # This is a collection that already has a pecan controller, we # do not need to do anything else continue legacy_controller = getattr(ext_res.controller, 'controller', ext_res.controller) new_controller = None if isinstance(legacy_controller, base.Controller): resource = legacy_controller.resource plugin = legacy_controller.plugin attr_info = legacy_controller.attr_info # Retrieving the parent resource. It is expected the format of # the parent resource to be: # {'collection_name': 'name-of-collection', # 'member_name': 'name-of-resource'} # collection_name does not appear to be used in the legacy code # inside the controller logic, so we can assume we do not need it. parent = legacy_controller.parent or {} parent_resource = parent.get('member_name') new_controller = res_ctrl.CollectionsController( collection, resource, resource_info=attr_info, parent_resource=parent_resource) manager.NeutronManager.set_plugin_for_resource(resource, plugin) if path_prefix: manager.NeutronManager.add_resource_for_path_prefix( collection, path_prefix) elif isinstance(legacy_controller, wsgi.Controller): new_controller = utils.ShimCollectionsController( collection, None, legacy_controller) else: LOG.warning( _LW("Unknown controller type encountered %s. It will" "be ignored."), legacy_controller) manager.NeutronManager.set_controller_for_resource( collection, new_controller) # Certain policy checks require that the extensions are loaded # and the RESOURCE_ATTRIBUTE_MAP populated before they can be # properly initialized. This can only be claimed with certainty # once this point in the code has been reached. In the event # that the policies have been initialized before this point, # calling reset will cause the next policy check to # re-initialize with all of the required data in place. policy.reset()