Pecan: Define plugin crud methods in base class

Refactors the current pecan code to use predefined methods to get
the plugin methods the controllers will call.  This also adds in
parent resource information to build those method names, but parent
support will not be complete until a follow up patch.

Change-Id: I4e0e6ef96364991a9393bc5fba495e37dade68a1
Closes-Bug: #1596754
This commit is contained in:
Brandon Logan 2016-06-27 21:17:12 -05:00
parent 2f29a5db3c
commit a2016a6211
4 changed files with 64 additions and 15 deletions

View File

@ -101,7 +101,7 @@ class Controller(object):
LOG.info(_LI("Allow sorting is enabled because native "
"pagination requires native sorting"))
self._allow_sorting = True
self.parent = parent
if parent:
self._parent_id_name = '%s_id' % parent['member_name']
parent_part = '_%s' % parent['member_name']

View File

@ -36,11 +36,10 @@ class ItemController(utils.NeutronPecanController):
return self.get(*args, **kwargs)
def get(self, *args, **kwargs):
getter = getattr(self.plugin, 'get_%s' % self.resource)
neutron_context = request.context['neutron_context']
fields = request.context['query_params'].get('fields')
return {self.resource: getter(neutron_context, self.item,
fields=fields)}
return {self.resource: self.plugin_shower(neutron_context, self.item,
fields=fields)}
@utils.when(index, method='HEAD')
@utils.when(index, method='POST')
@ -53,19 +52,18 @@ class ItemController(utils.NeutronPecanController):
neutron_context = request.context['neutron_context']
resources = request.context['resources']
# TODO(kevinbenton): bulk?
updater = getattr(self.plugin, 'update_%s' % self.resource)
# Bulk update is not supported, 'resources' always contains a single
# elemenet
data = {self.resource: resources[0]}
return {self.resource: updater(neutron_context, self.item, data)}
return {self.resource: self.plugin_updater(neutron_context,
self.item, data)}
@utils.when(index, method='DELETE')
def delete(self):
# TODO(kevinbenton): setting code could be in a decorator
pecan.response.status = 204
neutron_context = request.context['neutron_context']
deleter = getattr(self.plugin, 'delete_%s' % self.resource)
return deleter(neutron_context, self.item)
return self.plugin_deleter(neutron_context, self.item)
@utils.expose()
def _lookup(self, collection, *remainder):
@ -100,9 +98,9 @@ class CollectionsController(utils.NeutronPecanController):
def get(self, *args, **kwargs):
# NOTE(blogan): query_params is set in the QueryParametersHook
query_params = request.context['query_params']
lister = getattr(self.plugin, 'get_%s' % self.collection)
neutron_context = request.context['neutron_context']
return {self.collection: lister(neutron_context, **query_params)}
return {self.collection: self.plugin_lister(neutron_context,
**query_params)}
@utils.when(index, method='HEAD')
@utils.when(index, method='PATCH')
@ -121,13 +119,12 @@ class CollectionsController(utils.NeutronPecanController):
def create(self, resources):
if len(resources) > 1:
# Bulk!
method = 'create_%s_bulk' % self.resource
creator = self.plugin_bulk_creator
key = self.collection
data = {key: [{self.resource: res} for res in resources]}
else:
method = 'create_%s' % self.resource
creator = self.plugin_creator
key = self.resource
data = {key: resources[0]}
creator = getattr(self.plugin, method)
neutron_context = request.context['neutron_context']
return {key: creator(neutron_context, data)}

View File

@ -90,8 +90,15 @@ def when(index, *args, **kwargs):
class NeutronPecanController(object):
LIST = 'list'
SHOW = 'show'
CREATE = 'create'
UPDATE = 'update'
DELETE = 'delete'
def __init__(self, collection, resource, plugin=None, resource_info=None,
allow_pagination=None, allow_sorting=None):
allow_pagination=None, allow_sorting=None,
parent_resource=None):
# Ensure dashes are always replaced with underscores
self.collection = collection and collection.replace('-', '_')
self.resource = resource and resource.replace('-', '_')
@ -117,6 +124,17 @@ class NeutronPecanController(object):
self.plugin)
self.primary_key = self._get_primary_key()
parent_resource = '_%s' % parent_resource if parent_resource else ''
self._parent_id_name = ('%s_id' % parent_resource
if parent_resource else None)
self._plugin_handlers = {
self.LIST: 'get%s_%s' % (parent_resource, self.collection),
self.SHOW: 'get%s_%s' % (parent_resource, self.resource)
}
for action in [self.CREATE, self.UPDATE, self.DELETE]:
self._plugin_handlers[action] = '%s%s_%s' % (
action, parent_resource, self.resource)
def build_field_list(self, request_fields):
added_fields = []
combined_fields = []
@ -148,6 +166,31 @@ class NeutronPecanController(object):
return key
return default_primary_key
@property
def plugin_lister(self):
return getattr(self.plugin, self._plugin_handlers[self.LIST])
@property
def plugin_shower(self):
return getattr(self.plugin, self._plugin_handlers[self.SHOW])
@property
def plugin_creator(self):
return getattr(self.plugin, self._plugin_handlers[self.CREATE])
@property
def plugin_bulk_creator(self):
return getattr(self.plugin,
'%s_bulk' % self._plugin_handlers[self.CREATE])
@property
def plugin_deleter(self):
return getattr(self.plugin, self._plugin_handlers[self.DELETE])
@property
def plugin_updater(self):
return getattr(self.plugin, self._plugin_handlers[self.UPDATE])
class ShimRequest(object):

View File

@ -70,8 +70,17 @@ def initialize_all():
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)
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(