Add find method to resource

Add a find method to the resource to search by name or id.

Change-Id: I993e0ab2fffd3cd10407406316c483f8051dca1b
This commit is contained in:
Terry Howe 2014-07-03 14:48:34 -06:00
parent 445809d8e9
commit 67e0fae211
3 changed files with 114 additions and 0 deletions

View File

@ -66,3 +66,13 @@ class HttpException(SDKException):
class MethodNotSupported(SDKException):
"""The resource does not support this operation type."""
pass
class ResourceNotFound(SDKException):
"""The requested resource was not found."""
pass
class DuplicateResource(SDKException):
"""More than one resource exists with that name."""
pass

View File

@ -101,6 +101,9 @@ class Resource(collections.MutableMapping):
resource_key = None
resources_key = None
# The attribute associated with the name
name_attribute = 'name'
# the base part of the url for this resource
base_path = ''
@ -350,3 +353,24 @@ class Resource(collections.MutableMapping):
resp = resp[cls.resources_key]
return [cls.existing(**data) for data in resp]
@classmethod
def find(cls, session, name_or_id):
try:
info = cls.list(session, id=name_or_id, fields='id')
if len(info) == 1:
return info[0]
except exceptions.HttpException:
pass
if cls.name_attribute:
params = {cls.name_attribute: name_or_id, 'fields': 'id'}
info = cls.list(session, **params)
if len(info) == 1:
return info[0]
if len(info) > 1:
msg = "More than one %s exists with the name '%s'."
msg = (msg % (cls.resource_key, name_or_id))
raise exceptions.DuplicateResource(msg)
msg = ("No %s with a name or ID of '%s' exists." %
(cls.resource_key, name_or_id))
raise exceptions.ResourceNotFound(msg)

View File

@ -11,7 +11,9 @@
# under the License.
import httpretty
import mock
from openstack import exceptions
from openstack import resource
from openstack import session
from openstack.tests import base
@ -206,3 +208,81 @@ class ResourceTests(base.TestTransportBase):
pass
else:
self.fail("Didn't raise attribute error")
class FakeResponse:
def __init__(self, response):
self.body = response
class TestFind(base.TestCase):
NAME = 'matrix'
ID = 'Fishburne'
def setUp(self):
super(TestFind, self).setUp()
self.mock_session = mock.Mock()
self.mock_get = mock.Mock()
self.mock_session.get = self.mock_get
self.matrix = {'id': self.ID}
def test_name(self):
self.mock_get.side_effect = [
FakeResponse({FakeResource.resources_key: []}),
FakeResponse({FakeResource.resources_key: [self.matrix]})
]
result = FakeResource.find(self.mock_session, self.NAME)
self.assertEqual(self.ID, result.id)
p = {'fields': 'id', 'name': self.NAME}
self.mock_get.assert_called_with('/fakes', params=p, service=None)
def test_id(self):
resp = FakeResponse({FakeResource.resources_key: [self.matrix]})
self.mock_get.return_value = resp
result = FakeResource.find(self.mock_session, self.ID)
self.assertEqual(self.ID, result.id)
p = {'fields': 'id', 'id': self.ID}
self.mock_get.assert_called_with('/fakes', params=p, service=None)
def test_nameo(self):
self.mock_get.side_effect = [
FakeResponse({FakeResource.resources_key: []}),
FakeResponse({FakeResource.resources_key: [self.matrix]})
]
FakeResource.name_attribute = 'nameo'
result = FakeResource.find(self.mock_session, self.NAME)
FakeResource.name_attribute = 'name'
self.assertEqual(self.ID, result.id)
p = {'fields': 'id', 'nameo': self.NAME}
self.mock_get.assert_called_with('/fakes', params=p, service=None)
def test_dups(self):
dup = {'id': 'Larry'}
resp = FakeResponse({FakeResource.resources_key: [self.matrix, dup]})
self.mock_get.return_value = resp
self.assertRaises(exceptions.DuplicateResource, FakeResource.find,
self.mock_session, self.NAME)
def test_nada(self):
resp = FakeResponse({FakeResource.resources_key: []})
self.mock_get.return_value = resp
self.assertRaises(exceptions.ResourceNotFound, FakeResource.find,
self.mock_session, self.NAME)
def test_no_name(self):
self.mock_get.side_effect = [
FakeResponse({FakeResource.resources_key: []}),
FakeResponse({FakeResource.resources_key: [self.matrix]})
]
FakeResource.name_attribute = None
self.assertRaises(exceptions.ResourceNotFound, FakeResource.find,
self.mock_session, self.NAME)