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):
|
class MethodNotSupported(SDKException):
|
||||||
"""The resource does not support this operation type."""
|
"""The resource does not support this operation type."""
|
||||||
pass
|
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
|
resource_key = None
|
||||||
resources_key = None
|
resources_key = None
|
||||||
|
|
||||||
|
# The attribute associated with the name
|
||||||
|
name_attribute = 'name'
|
||||||
|
|
||||||
# the base part of the url for this resource
|
# the base part of the url for this resource
|
||||||
base_path = ''
|
base_path = ''
|
||||||
|
|
||||||
@ -350,3 +353,24 @@ class Resource(collections.MutableMapping):
|
|||||||
resp = resp[cls.resources_key]
|
resp = resp[cls.resources_key]
|
||||||
|
|
||||||
return [cls.existing(**data) for data in resp]
|
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.
|
# under the License.
|
||||||
|
|
||||||
import httpretty
|
import httpretty
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from openstack import exceptions
|
||||||
from openstack import resource
|
from openstack import resource
|
||||||
from openstack import session
|
from openstack import session
|
||||||
from openstack.tests import base
|
from openstack.tests import base
|
||||||
@ -206,3 +208,81 @@ class ResourceTests(base.TestTransportBase):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.fail("Didn't raise attribute error")
|
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