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:
parent
445809d8e9
commit
67e0fae211
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user