Enable less code in cratonclient resources
Previously, resource managers were overriding __init__, list, and create to include extra parameters, e.g., region_id. This slightly alters the base CRUDClient to accept extra request keyword arguments to merge into each request's arguments. Change-Id: Ia850417c7a94eea95d35c8a93141c70945d1a800
This commit is contained in:
@@ -24,10 +24,11 @@ class CRUDClient(object):
|
|||||||
base_path = None
|
base_path = None
|
||||||
resource_class = None
|
resource_class = None
|
||||||
|
|
||||||
def __init__(self, session, url):
|
def __init__(self, session, url, **extra_request_kwargs):
|
||||||
"""Initialize our Client with a session and base url."""
|
"""Initialize our Client with a session and base url."""
|
||||||
self.session = session
|
self.session = session
|
||||||
self.url = url.rstrip('/')
|
self.url = url.rstrip('/')
|
||||||
|
self.extra_request_kwargs = extra_request_kwargs
|
||||||
|
|
||||||
def build_url(self, path_arguments=None):
|
def build_url(self, path_arguments=None):
|
||||||
"""Build a complete URL from the url, base_path, and arguments.
|
"""Build a complete URL from the url, base_path, and arguments.
|
||||||
@@ -76,21 +77,34 @@ class CRUDClient(object):
|
|||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def create(self, **kwargs):
|
def merge_request_arguments(self, request_kwargs, skip_merge):
|
||||||
|
"""Merge the extra request arguments into the per-request args."""
|
||||||
|
if skip_merge:
|
||||||
|
return
|
||||||
|
|
||||||
|
keys = set(self.extra_request_kwargs.keys())
|
||||||
|
missing_keys = keys.difference(request_kwargs.keys())
|
||||||
|
for key in missing_keys:
|
||||||
|
request_kwargs[key] = self.extra_request_kwargs[key]
|
||||||
|
|
||||||
|
def create(self, skip_merge=False, **kwargs):
|
||||||
"""Create a new item based on the keyword arguments provided."""
|
"""Create a new item based on the keyword arguments provided."""
|
||||||
|
self.merge_request_arguments(kwargs, skip_merge)
|
||||||
url = self.build_url(path_arguments=kwargs)
|
url = self.build_url(path_arguments=kwargs)
|
||||||
response = self.session.post(url, json=kwargs)
|
response = self.session.post(url, json=kwargs)
|
||||||
return self.resource_class(self, response.json(), loaded=True)
|
return self.resource_class(self, response.json(), loaded=True)
|
||||||
|
|
||||||
def get(self, item_id=None, **kwargs):
|
def get(self, item_id=None, skip_merge=True, **kwargs):
|
||||||
"""Retrieve the item based on the keyword arguments provided."""
|
"""Retrieve the item based on the keyword arguments provided."""
|
||||||
|
self.merge_request_arguments(kwargs, skip_merge)
|
||||||
kwargs.setdefault(self.key + '_id', item_id)
|
kwargs.setdefault(self.key + '_id', item_id)
|
||||||
url = self.build_url(path_arguments=kwargs)
|
url = self.build_url(path_arguments=kwargs)
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
return self.resource_class(self, response.json(), loaded=True)
|
return self.resource_class(self, response.json(), loaded=True)
|
||||||
|
|
||||||
def list(self, **kwargs):
|
def list(self, skip_merge=False, **kwargs):
|
||||||
"""List the items from this endpoint."""
|
"""List the items from this endpoint."""
|
||||||
|
self.merge_request_arguments(kwargs, skip_merge)
|
||||||
url = self.build_url(path_arguments=kwargs)
|
url = self.build_url(path_arguments=kwargs)
|
||||||
response = self.session.get(url, params=kwargs)
|
response = self.session.get(url, params=kwargs)
|
||||||
return [
|
return [
|
||||||
@@ -98,15 +112,17 @@ class CRUDClient(object):
|
|||||||
for item in response.json()
|
for item in response.json()
|
||||||
]
|
]
|
||||||
|
|
||||||
def update(self, item_id=None, **kwargs):
|
def update(self, item_id=None, skip_merge=True, **kwargs):
|
||||||
"""Update the item based on the keyword arguments provided."""
|
"""Update the item based on the keyword arguments provided."""
|
||||||
|
self.merge_request_arguments(kwargs, skip_merge)
|
||||||
kwargs.setdefault(self.key + '_id', item_id)
|
kwargs.setdefault(self.key + '_id', item_id)
|
||||||
url = self.build_url(path_arguments=kwargs)
|
url = self.build_url(path_arguments=kwargs)
|
||||||
response = self.session.put(url, json=kwargs)
|
response = self.session.put(url, json=kwargs)
|
||||||
return self.resource_class(self, response.json(), loaded=True)
|
return self.resource_class(self, response.json(), loaded=True)
|
||||||
|
|
||||||
def delete(self, item_id=None, **kwargs):
|
def delete(self, item_id=None, skip_merge=True, **kwargs):
|
||||||
"""Delete the item based on the keyword arguments provided."""
|
"""Delete the item based on the keyword arguments provided."""
|
||||||
|
self.merge_request_arguments(kwargs, skip_merge)
|
||||||
kwargs.setdefault(self.key + '_id', item_id)
|
kwargs.setdefault(self.key + '_id', item_id)
|
||||||
url = self.build_url(path_arguments=kwargs)
|
url = self.build_url(path_arguments=kwargs)
|
||||||
response = self.session.delete(url, params=kwargs)
|
response = self.session.delete(url, params=kwargs)
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
cells_shell.do_cell_create(client, self.cell_valid_fields)
|
cells_shell.do_cell_create(client, self.cell_valid_fields)
|
||||||
@@ -170,8 +170,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
cells_shell.do_cell_create(client, self.cell_invalid_field)
|
cells_shell.do_cell_create(client, self.cell_invalid_field)
|
||||||
@@ -195,8 +195,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
valid_input = Namespace(region=1,
|
valid_input = Namespace(region=1,
|
||||||
@@ -212,8 +212,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
invalid_input = Namespace(region=1,
|
invalid_input = Namespace(region=1,
|
||||||
@@ -243,8 +243,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
test_args = Namespace(id=1, region=1)
|
test_args = Namespace(id=1, region=1)
|
||||||
@@ -268,8 +268,8 @@ class TestCellsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.cells = cells.CellManager(mock.ANY,
|
inventory.cells = cells.CellManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
test_args = Namespace(id=1, region=1)
|
test_args = Namespace(id=1, region=1)
|
||||||
|
|||||||
@@ -30,10 +30,16 @@ class TestCRUDClient(base.TestCase):
|
|||||||
super(TestCRUDClient, self).setUp()
|
super(TestCRUDClient, self).setUp()
|
||||||
self.session = mock.Mock()
|
self.session = mock.Mock()
|
||||||
self.resource_spec = mock.Mock(spec=crud.Resource)
|
self.resource_spec = mock.Mock(spec=crud.Resource)
|
||||||
self.client = crud.CRUDClient(self.session, 'http://example.com/v1/')
|
self.client = self.create_client()
|
||||||
self.client.base_path = '/test'
|
|
||||||
self.client.key = 'test_key'
|
def create_client(self, **kwargs):
|
||||||
self.client.resource_class = self.resource_spec
|
"""Create and configure a basic CRUDClient."""
|
||||||
|
client = crud.CRUDClient(self.session, 'http://example.com/v1/',
|
||||||
|
**kwargs)
|
||||||
|
client.base_path = '/test'
|
||||||
|
client.key = 'test_key'
|
||||||
|
client.resource_class = self.resource_spec
|
||||||
|
return client
|
||||||
|
|
||||||
def test_strips_trailing_forward_slash_from_url(self):
|
def test_strips_trailing_forward_slash_from_url(self):
|
||||||
"""Verify the client strips the trailing / in a URL."""
|
"""Verify the client strips the trailing / in a URL."""
|
||||||
@@ -73,6 +79,22 @@ class TestCRUDClient(base.TestCase):
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_merge_request_arguments(self):
|
||||||
|
"""Verify we include extra request arguments."""
|
||||||
|
client = self.create_client(extra_id=4321)
|
||||||
|
request_args = {}
|
||||||
|
|
||||||
|
client.merge_request_arguments(request_args, skip_merge=False)
|
||||||
|
self.assertEqual({'extra_id': 4321}, request_args)
|
||||||
|
|
||||||
|
def test_merge_request_arguments_skips_merging(self):
|
||||||
|
"""Verify we include extra request arguments."""
|
||||||
|
client = self.create_client(extra_id=4321)
|
||||||
|
request_args = {}
|
||||||
|
|
||||||
|
client.merge_request_arguments(request_args, skip_merge=True)
|
||||||
|
self.assertEqual({}, request_args)
|
||||||
|
|
||||||
def test_create_generates_a_post_request(self):
|
def test_create_generates_a_post_request(self):
|
||||||
"""Verify that using our create method will POST to our service."""
|
"""Verify that using our create method will POST to our service."""
|
||||||
response = self.session.post.return_value = mock.Mock()
|
response = self.session.post.return_value = mock.Mock()
|
||||||
|
|||||||
@@ -169,8 +169,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
hosts_shell.do_host_create(client, self.host_valid_fields)
|
hosts_shell.do_host_create(client, self.host_valid_fields)
|
||||||
@@ -182,8 +182,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
hosts_shell.do_host_create(client, self.host_invalid_field)
|
hosts_shell.do_host_create(client, self.host_invalid_field)
|
||||||
@@ -207,8 +207,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
valid_input = Namespace(region=1,
|
valid_input = Namespace(region=1,
|
||||||
@@ -224,8 +224,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
invalid_input = Namespace(region=1,
|
invalid_input = Namespace(region=1,
|
||||||
@@ -255,8 +255,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
test_args = Namespace(id=1, region=1)
|
test_args = Namespace(id=1, region=1)
|
||||||
@@ -280,8 +280,8 @@ class TestHostsShell(base.ShellTestCase):
|
|||||||
client = mock.Mock()
|
client = mock.Mock()
|
||||||
inventory = mock.Mock()
|
inventory = mock.Mock()
|
||||||
inventory.hosts = hosts.HostManager(mock.ANY,
|
inventory.hosts = hosts.HostManager(mock.ANY,
|
||||||
mock.ANY,
|
'http://127.0.0.1/',
|
||||||
'http://127.0.0.1/')
|
region_id=mock.ANY)
|
||||||
client.inventory = mock.Mock(name='inventory')
|
client.inventory = mock.Mock(name='inventory')
|
||||||
client.inventory.return_value = inventory
|
client.inventory.return_value = inventory
|
||||||
test_args = Namespace(id=1, region=1)
|
test_args = Namespace(id=1, region=1)
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ class TestInventory(base.TestCase):
|
|||||||
url = 'https://10.1.1.0:8080/'
|
url = 'https://10.1.1.0:8080/'
|
||||||
region_id = 1
|
region_id = 1
|
||||||
inventory.Inventory(session, url, region_id)
|
inventory.Inventory(session, url, region_id)
|
||||||
mock_hostmanager.assert_called_once_with(region_id, session, url)
|
mock_hostmanager.assert_called_once_with(
|
||||||
|
session,
|
||||||
|
url,
|
||||||
|
region_id=region_id,
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch('cratonclient.v1.cells.CellManager')
|
@mock.patch('cratonclient.v1.cells.CellManager')
|
||||||
def test_inventory_creates_cell_manager(self, cell_manager):
|
def test_inventory_creates_cell_manager(self, cell_manager):
|
||||||
@@ -37,4 +41,8 @@ class TestInventory(base.TestCase):
|
|||||||
url = 'https://10.1.1.0:8080/'
|
url = 'https://10.1.1.0:8080/'
|
||||||
region_id = 1
|
region_id = 1
|
||||||
inventory.Inventory(session, url, region_id)
|
inventory.Inventory(session, url, region_id)
|
||||||
cell_manager.assert_called_once_with(region_id, session, url)
|
cell_manager.assert_called_once_with(
|
||||||
|
session,
|
||||||
|
url,
|
||||||
|
region_id=region_id,
|
||||||
|
)
|
||||||
|
|||||||
@@ -27,22 +27,6 @@ class CellManager(crud.CRUDClient):
|
|||||||
key = 'cell'
|
key = 'cell'
|
||||||
base_path = '/cells'
|
base_path = '/cells'
|
||||||
resource_class = Cell
|
resource_class = Cell
|
||||||
region_id = 0
|
|
||||||
|
|
||||||
def __init__(self, region_id, session, url):
|
|
||||||
"""Initialize our CellManager object with region, session, and url."""
|
|
||||||
super(CellManager, self).__init__(session, url)
|
|
||||||
self.region_id = region_id
|
|
||||||
|
|
||||||
def list(self, **kwargs):
|
|
||||||
"""Retrieve the cells in a specific region."""
|
|
||||||
kwargs['region_id'] = self.region_id
|
|
||||||
return super(CellManager, self).list(**kwargs)
|
|
||||||
|
|
||||||
def create(self, **kwargs):
|
|
||||||
"""Create a cell in a specific region."""
|
|
||||||
kwargs['region_id'] = self.region_id
|
|
||||||
return super(CellManager, self).create(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
CELL_FIELDS = {
|
CELL_FIELDS = {
|
||||||
|
|||||||
@@ -27,22 +27,6 @@ class HostManager(crud.CRUDClient):
|
|||||||
key = 'host'
|
key = 'host'
|
||||||
base_path = '/hosts'
|
base_path = '/hosts'
|
||||||
resource_class = Host
|
resource_class = Host
|
||||||
region_id = 0
|
|
||||||
|
|
||||||
def __init__(self, region_id, session, url):
|
|
||||||
"""Initialize our HostManager object with region, session and url."""
|
|
||||||
super(HostManager, self).__init__(session, url)
|
|
||||||
self.region_id = region_id
|
|
||||||
|
|
||||||
def list(self, **kwargs):
|
|
||||||
"""Retrieve the hosts in a specific region."""
|
|
||||||
kwargs['region_id'] = self.region_id
|
|
||||||
return super(HostManager, self).list(**kwargs)
|
|
||||||
|
|
||||||
def create(self, **kwargs):
|
|
||||||
"""Create a host in a specific region."""
|
|
||||||
kwargs['region_id'] = self.region_id
|
|
||||||
return super(HostManager, self).create(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
HOST_FIELDS = {
|
HOST_FIELDS = {
|
||||||
|
|||||||
@@ -31,6 +31,6 @@ class Inventory(object):
|
|||||||
'https://10.1.1.0:8080/'.
|
'https://10.1.1.0:8080/'.
|
||||||
"""
|
"""
|
||||||
# TODO(cmspence): self.region = self.regions.get(region=region_id)
|
# TODO(cmspence): self.region = self.regions.get(region=region_id)
|
||||||
self.hosts = hosts.HostManager(region_id, session, url)
|
self.hosts = hosts.HostManager(session, url, region_id=region_id)
|
||||||
self.cells = cells.CellManager(region_id, session, url)
|
self.cells = cells.CellManager(session, url, region_id=region_id)
|
||||||
# TODO(cmspence): self.users, self.projects, self.workflows
|
# TODO(cmspence): self.users, self.projects, self.workflows
|
||||||
|
|||||||
Reference in New Issue
Block a user