Move find_resource family to API binding layer

find_resource variants are also used by OSC plugin.
It looks reasonable to move them to the API binding layer.

This commit does not touch the related unit tests
to ensure backward compatibility.

Related-Bug: #1521291
Change-Id: Iec3e9b379255111f5390325778a1d07bf73b29d6
This commit is contained in:
Akihiro Motoki 2016-07-27 22:37:13 +00:00
parent ec20f7f85c
commit 84c42160e9
5 changed files with 100 additions and 97 deletions

View File

@ -20,7 +20,6 @@ import abc
import argparse
import functools
import logging
import re
from cliff import command
from cliff import lister
@ -32,104 +31,26 @@ from neutronclient._i18n import _
from neutronclient.common import exceptions
from neutronclient.common import utils
HEX_ELEM = '[0-9A-Fa-f]'
UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}',
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
HEX_ELEM + '{12}'])
HYPHEN_OPTS = ['tags_any', 'not_tags', 'not_tags_any']
def _get_resource_plural(resource, client):
plurals = getattr(client, 'EXTED_PLURALS', [])
for k in plurals:
if plurals[k] == resource:
return k
return resource + 's'
def find_resource_by_id(client, resource, resource_id, cmd_resource=None,
parent_id=None, fields=None):
if not cmd_resource:
cmd_resource = resource
cmd_resource_plural = _get_resource_plural(cmd_resource, client)
resource_plural = _get_resource_plural(resource, client)
obj_lister = getattr(client, "list_%s" % cmd_resource_plural)
# perform search by id only if we are passing a valid UUID
match = re.match(UUID_PATTERN, resource_id)
collection = resource_plural
if match:
params = {'id': resource_id}
if fields:
params['fields'] = fields
if parent_id:
data = obj_lister(parent_id, **params)
else:
data = obj_lister(**params)
if data and data[collection]:
return data[collection][0]
not_found_message = (_("Unable to find %(resource)s with id "
"'%(id)s'") %
{'resource': resource, 'id': resource_id})
# 404 is raised by exceptions.NotFound to simulate serverside behavior
raise exceptions.NotFound(message=not_found_message)
return client.find_resource_by_id(resource, resource_id, cmd_resource,
parent_id, fields)
def find_resourceid_by_id(client, resource, resource_id, cmd_resource=None,
parent_id=None):
info = find_resource_by_id(client, resource, resource_id, cmd_resource,
parent_id, fields='id')
return info['id']
def _find_resource_by_name(client, resource, name, project_id=None,
cmd_resource=None, parent_id=None, fields=None):
if not cmd_resource:
cmd_resource = resource
cmd_resource_plural = _get_resource_plural(cmd_resource, client)
resource_plural = _get_resource_plural(resource, client)
obj_lister = getattr(client, "list_%s" % cmd_resource_plural)
params = {'name': name}
if fields:
params['fields'] = fields
if project_id:
params['tenant_id'] = project_id
if parent_id:
data = obj_lister(parent_id, **params)
else:
data = obj_lister(**params)
collection = resource_plural
info = data[collection]
if len(info) > 1:
raise exceptions.NeutronClientNoUniqueMatch(resource=resource,
name=name)
elif len(info) == 0:
not_found_message = (_("Unable to find %(resource)s with name "
"'%(name)s'") %
{'resource': resource, 'name': name})
# 404 is raised by exceptions.NotFound to simulate serverside behavior
raise exceptions.NotFound(message=not_found_message)
else:
return info[0]
return find_resource_by_id(client, resource, resource_id, cmd_resource,
parent_id, fields='id')['id']
def find_resource_by_name_or_id(client, resource, name_or_id,
project_id=None, cmd_resource=None,
parent_id=None, fields=None):
try:
return find_resource_by_id(client, resource, name_or_id,
cmd_resource, parent_id, fields)
except exceptions.NotFound:
try:
return _find_resource_by_name(client, resource, name_or_id,
project_id, cmd_resource, parent_id,
fields)
except exceptions.NotFound:
not_found_message = (_("Unable to find %(resource)s with name "
"or id '%(name_or_id)s'") %
{'resource': resource,
'name_or_id': name_or_id})
raise exceptions.NotFound(
message=not_found_message)
return client.find_resource(resource, name_or_id, project_id,
cmd_resource, parent_id, fields)
def find_resourceid_by_name_or_id(client, resource, name_or_id,
@ -695,8 +616,7 @@ class ListCommand(NeutronCommand, lister.Lister):
return search_opts
def call_server(self, neutron_client, search_opts, parsed_args):
resource_plural = _get_resource_plural(self.cmd_resource,
neutron_client)
resource_plural = neutron_client.get_resource_plural(self.cmd_resource)
obj_lister = getattr(neutron_client, "list_%s" % resource_plural)
if self.parent_id:
data = obj_lister(self.parent_id, **search_opts)
@ -729,7 +649,7 @@ class ListCommand(NeutronCommand, lister.Lister):
if dirs:
search_opts.update({'sort_dir': dirs})
data = self.call_server(neutron_client, search_opts, parsed_args)
collection = _get_resource_plural(self.resource, neutron_client)
collection = neutron_client.get_resource_plural(self.resource)
return data.get(collection, [])
def extend_list(self, data, parsed_args):

View File

@ -20,8 +20,7 @@ TAG_RESOURCES = ['network']
def _convert_resource_args(client, parsed_args):
resource_type = neutronv20._get_resource_plural(
parsed_args.resource_type, client)
resource_type = client.get_resource_plural(parsed_args.resource_type)
resource_id = neutronv20.find_resourceid_by_name_or_id(
client, parsed_args.resource_type, parsed_args.resource)
return resource_type, resource_id

View File

@ -250,8 +250,7 @@ class CLITestV20Base(base.BaseTestCase):
ress[resource].update({'name': name})
resstr = self.client.serialize(ress)
# url method body
resource_plural = neutronV2_0._get_resource_plural(cmd_resource,
self.client)
resource_plural = self.client.get_resource_plural(cmd_resource)
path = getattr(self.client, resource_plural + "_path")
if parent_id:
path = path % parent_id

View File

@ -15,7 +15,6 @@ import sys
from mox3 import mox
from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV2_0
from neutronclient.neutron.v2_0 import network
from neutronclient.neutron.v2_0 import tag
from neutronclient import shell
@ -68,14 +67,12 @@ class CLITestV20Tag(test_cli20.CLITestV20Base):
def _make_tag_path(self, resource, resource_id, tag):
path = getattr(self.client, "tag_path")
resource_plural = neutronV2_0._get_resource_plural(resource,
self.client)
resource_plural = self.client.get_resource_plural(resource)
return path % (resource_plural, resource_id, tag)
def _make_tags_path(self, resource, resource_id):
path = getattr(self.client, "tags_path")
resource_plural = neutronV2_0._get_resource_plural(resource,
self.client)
resource_plural = self.client.get_resource_plural(resource)
return path % (resource_plural, resource_id)
def test_add_tag(self):

View File

@ -18,6 +18,7 @@
import inspect
import itertools
import logging
import re
import time
import debtcollector.renames
@ -35,6 +36,11 @@ from neutronclient.common import utils
_logger = logging.getLogger(__name__)
HEX_ELEM = '[0-9A-Fa-f]'
UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}',
HEX_ELEM + '{4}', HEX_ELEM + '{4}',
HEX_ELEM + '{12}'])
def exception_handler_v20(status_code, error_content):
"""Exception handler for API v2.0 client.
@ -396,6 +402,88 @@ class ClientBase(object):
else:
return _TupleWithMeta((), resp)
def get_resource_plural(self, resource):
for k in self.EXTED_PLURALS:
if self.EXTED_PLURALS[k] == resource:
return k
return resource + 's'
def _find_resource_by_id(self, resource, resource_id, cmd_resource=None,
parent_id=None, fields=None):
if not cmd_resource:
cmd_resource = resource
cmd_resource_plural = self.get_resource_plural(cmd_resource)
resource_plural = self.get_resource_plural(resource)
# TODO(amotoki): Use show_%s instead of list_%s
obj_lister = getattr(self, "list_%s" % cmd_resource_plural)
# perform search by id only if we are passing a valid UUID
match = re.match(UUID_PATTERN, resource_id)
collection = resource_plural
if match:
params = {'id': resource_id}
if fields:
params['fields'] = fields
if parent_id:
data = obj_lister(parent_id, **params)
else:
data = obj_lister(**params)
if data and data[collection]:
return data[collection][0]
not_found_message = (_("Unable to find %(resource)s with id "
"'%(id)s'") %
{'resource': resource, 'id': resource_id})
# 404 is raised by exceptions.NotFound to simulate serverside behavior
raise exceptions.NotFound(message=not_found_message)
def _find_resource_by_name(self, resource, name, project_id=None,
cmd_resource=None, parent_id=None, fields=None):
if not cmd_resource:
cmd_resource = resource
cmd_resource_plural = self.get_resource_plural(cmd_resource)
resource_plural = self.get_resource_plural(resource)
obj_lister = getattr(self, "list_%s" % cmd_resource_plural)
params = {'name': name}
if fields:
params['fields'] = fields
if project_id:
params['tenant_id'] = project_id
if parent_id:
data = obj_lister(parent_id, **params)
else:
data = obj_lister(**params)
collection = resource_plural
info = data[collection]
if len(info) > 1:
raise exceptions.NeutronClientNoUniqueMatch(resource=resource,
name=name)
elif len(info) == 0:
not_found_message = (_("Unable to find %(resource)s with name "
"'%(name)s'") %
{'resource': resource, 'name': name})
# 404 is raised by exceptions.NotFound
# to simulate serverside behavior
raise exceptions.NotFound(message=not_found_message)
else:
return info[0]
def find_resource(self, resource, name_or_id, project_id=None,
cmd_resource=None, parent_id=None, fields=None):
try:
return self._find_resource_by_id(resource, name_or_id,
cmd_resource, parent_id, fields)
except exceptions.NotFound:
try:
return self._find_resource_by_name(
resource, name_or_id, project_id,
cmd_resource, parent_id, fields)
except exceptions.NotFound:
not_found_message = (_("Unable to find %(resource)s with name "
"or id '%(name_or_id)s'") %
{'resource': resource,
'name_or_id': name_or_id})
raise exceptions.NotFound(
message=not_found_message)
class Client(ClientBase):