diff --git a/examples/simple.py b/examples/simple.py index 7e9c25e4..9aec0d82 100644 --- a/examples/simple.py +++ b/examples/simple.py @@ -28,7 +28,7 @@ def create_post_delete(queue_name, messages): :params messages: Messages to post. :type messages: list """ - cli = client.Client(URL) + cli = client.Client(URL, version=1.1) queue = cli.queue(queue_name) queue.post(messages) diff --git a/zaqarclient/queues/v1/api.py b/zaqarclient/queues/v1/api.py index 8799dff2..d111ea30 100644 --- a/zaqarclient/queues/v1/api.py +++ b/zaqarclient/queues/v1/api.py @@ -172,6 +172,26 @@ class V1(api.Api): } }, + 'pool_update': { + 'ref': 'pools/{pool_name}', + 'method': 'PATCH', + 'required': ['pool_name'], + 'properties': { + 'pool_name': {'type': 'string'} + } + }, + + 'pool_list': { + 'ref': 'pools', + 'method': 'GET', + 'properties': { + 'pool_name': {'type': 'string'}, + 'marker': {'type': 'string'}, + 'limit': {'type': 'integer'}, + 'detailed': {'type': 'boolean'} + } + }, + 'pool_delete': { 'ref': 'pools/{pool_name}', 'method': 'DELETE', @@ -283,7 +303,29 @@ V1_1.schema.update({ 'pop': {'type': 'integer'}, } }, + + + 'flavor_update': { + 'ref': 'flavors/{flavor_name}', + 'method': 'PATCH', + 'required': ['flavor_name'], + 'properties': { + 'flavor_name': {'type': 'string'} + } + }, + + 'flavor_list': { + 'ref': 'flavors', + 'method': 'GET', + 'properties': { + 'flavor_name': {'type': 'string'}, + 'marker': {'type': 'string'}, + 'limit': {'type': 'integer'}, + 'detailed': {'type': 'boolean'} + } + }, }) + del V1_1.schema['queue_get_metadata'] del V1_1.schema['queue_set_metadata'] diff --git a/zaqarclient/queues/v1/client.py b/zaqarclient/queues/v1/client.py index d06ebc98..65c8048e 100644 --- a/zaqarclient/queues/v1/client.py +++ b/zaqarclient/queues/v1/client.py @@ -140,6 +140,24 @@ class Client(object): """ return pool.Pool(self, ref, **kwargs) + def pools(self, **params): + """Gets a list of pools from the server + + :param params: Filters to use for getting pools + :type params: **kwargs dict. + + :returns: A list of pools + :rtype: `list` + """ + req, trans = self._request_and_transport() + + pool_list = core.pool_list(trans, req, **params) + + return iterator._Iterator(self, + pool_list, + 'pools', + pool.create_object(self)) + @decorators.version(min_version=1.1) def flavor(self, ref, **kwargs): """Returns a flavor instance @@ -152,6 +170,25 @@ class Client(object): """ return flavor.Flavor(self, ref, **kwargs) + @decorators.version(min_version=1.1) + def flavors(self, **params): + """Gets a list of flavors from the server + + :param params: Filters to use for getting flavors + :type params: **kwargs dict. + + :returns: A list of flavors + :rtype: `list` + """ + req, trans = self._request_and_transport() + + flavor_list = core.flavor_list(trans, req, **params) + + return iterator._Iterator(self, + flavor_list, + 'flavors', + flavor.create_object(self)) + def health(self): """Gets the health status of Zaqar server.""" req, trans = self._request_and_transport() diff --git a/zaqarclient/queues/v1/core.py b/zaqarclient/queues/v1/core.py index b9a30e73..19f85b29 100644 --- a/zaqarclient/queues/v1/core.py +++ b/zaqarclient/queues/v1/core.py @@ -451,6 +451,50 @@ def pool_create(transport, request, pool_name, pool_data): transport.send(request) +def pool_update(transport, request, pool_name, pool_data): + """Updates the pool `pool_name` + + :param transport: Transport instance to use + :type transport: `transport.base.Transport` + :param request: Request instance ready to be sent. + :type request: `transport.request.Request` + :param pool_name: Pool reference name. + :type pool_name: `six.text_type` + :param pool_data: Pool's properties, i.e: weight, uri, options. + :type pool_data: `dict` + """ + + request.operation = 'pool_update' + request.params['pool_name'] = pool_name + request.content = json.dumps(pool_data) + + resp = transport.send(request) + return resp.deserialized_content + + +def pool_list(transport, request, **kwargs): + """Gets a list of pools + + :param transport: Transport instance to use + :type transport: `transport.base.Transport` + :param request: Request instance ready to be sent. + :type request: `transport.request.Request` + :param kwargs: Optional arguments for this operation. + - marker: Where to start getting pools from. + - limit: Maximum number of pools to get. + """ + + request.operation = 'pool_list' + request.params.update(kwargs) + + resp = transport.send(request) + + if not resp.content: + return {'links': [], 'pools': []} + + return resp.deserialized_content + + def pool_delete(transport, request, pool_name): """Deletes the pool `pool_name` @@ -505,6 +549,50 @@ def flavor_get(transport, request, flavor_name, callback=None): return resp.deserialized_content +def flavor_update(transport, request, flavor_name, flavor_data): + """Updates the flavor `flavor_name` + + :param transport: Transport instance to use + :type transport: `transport.base.Transport` + :param request: Request instance ready to be sent. + :type request: `transport.request.Request` + :param flavor_name: Flavor reference name. + :type flavor_name: `six.text_type` + :param flavor_data: Flavor's properties, i.e: pool, capabilities. + :type flavor_data: `dict` + """ + + request.operation = 'flavor_update' + request.params['flavor_name'] = flavor_name + request.content = json.dumps(flavor_data) + + resp = transport.send(request) + return resp.deserialized_content + + +def flavor_list(transport, request, **kwargs): + """Gets a list of flavors + + :param transport: Transport instance to use + :type transport: `transport.base.Transport` + :param request: Request instance ready to be sent. + :type request: `transport.request.Request` + :param kwargs: Optional arguments for this operation. + - marker: Where to start getting flavors from. + - limit: Maximum number of flavors to get. + """ + + request.operation = 'flavor_list' + request.params.update(kwargs) + + resp = transport.send(request) + + if not resp.content: + return {'links': [], 'flavors': []} + + return resp.deserialized_content + + def flavor_delete(transport, request, name): """Deletes the flavor `name` diff --git a/zaqarclient/queues/v1/flavor.py b/zaqarclient/queues/v1/flavor.py index c1386182..32588ce3 100644 --- a/zaqarclient/queues/v1/flavor.py +++ b/zaqarclient/queues/v1/flavor.py @@ -51,6 +51,17 @@ class Flavor(object): core.flavor_create(trans, req, self.name, data) + def update(self, flavor_data): + req, trans = self.client._request_and_transport() + core.flavor_update(trans, req, self.name, flavor_data) + + for key, value in flavor_data.items(): + setattr(self, key, value) + def delete(self): req, trans = self.client._request_and_transport() core.flavor_delete(trans, req, self.name) + + +def create_object(parent): + return lambda args: Flavor(parent, args["name"], auto_create=False) diff --git a/zaqarclient/queues/v1/pool.py b/zaqarclient/queues/v1/pool.py index ca83f1e6..879271c0 100644 --- a/zaqarclient/queues/v1/pool.py +++ b/zaqarclient/queues/v1/pool.py @@ -60,6 +60,17 @@ class Pool(object): core.pool_create(trans, req, self.name, data) + def update(self, pool_data): + req, trans = self.client._request_and_transport() + core.pool_update(trans, req, self.name, pool_data) + + for key, value in pool_data.items(): + setattr(self, key, value) + def delete(self): req, trans = self.client._request_and_transport() core.pool_delete(trans, req, self.name) + + +def create_object(parent): + return lambda args: Pool(parent, args["name"], auto_create=False) diff --git a/zaqarclient/tests/queues/flavor.py b/zaqarclient/tests/queues/flavor.py index f5e71f75..fc0665a3 100644 --- a/zaqarclient/tests/queues/flavor.py +++ b/zaqarclient/tests/queues/flavor.py @@ -16,6 +16,7 @@ import json import mock +from zaqarclient.queues.v1 import iterator from zaqarclient.tests.queues import base from zaqarclient.transport import errors from zaqarclient.transport import response @@ -58,6 +59,41 @@ class QueuesV1_1FlavorUnitTest(base.QueuesTestBase): self.assertEqual(flavor.name, 'test') self.assertEqual(flavor.pool, 'stomach') + def test_flavor_update(self): + flavor_data = {'pool': 'stomach'} + updated_data = {'pool': 'belly'} + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + resp = response.Response(None, json.dumps(updated_data)) + send_method.return_value = resp + + flavor = self.client.flavor('tasty', **flavor_data) + flavor.update({'pool': 'belly'}) + self.assertEqual('belly', flavor.pool) + + def test_flavor_list(self): + returned = { + 'links': [{ + 'rel': 'next', + 'href': '/v1.1/flavors?marker=6244-244224-783' + }], + 'flavors': [{ + 'name': 'tasty', + 'pool': 'stomach' + }] + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(returned)) + send_method.return_value = resp + + flavor_var = self.client.flavors(limit=1) + self.assertIsInstance(flavor_var, iterator._Iterator) + self.assertEqual(1, len(list(flavor_var))) + def test_flavor_delete(self): flavor_data = {'pool': 'stomach'} @@ -84,33 +120,72 @@ class QueuesV1_1FlavorFunctionalTest(base.QueuesTestBase): version = 1.1 def test_flavor_create(self): - pool_data = {'uri': 'sqlite://', + pool_data = {'uri': 'mongodb://127.0.0.1:27017', 'weight': 10, 'group': 'us'} - self.client.pool('stomach', **pool_data) + pool = self.client.pool('stomach', **pool_data) + self.addCleanup(pool.delete) flavor_data = {'pool': 'us'} flavor = self.client.flavor('tasty', **flavor_data) + self.addCleanup(flavor.delete) + self.assertEqual(flavor.name, 'tasty') self.assertEqual(flavor.pool, 'us') def test_flavor_get(self): pool_data = {'weight': 10, 'group': 'us', - 'uri': 'sqlite://'} + 'uri': 'mongodb://127.0.0.1:27017'} self.client.pool('stomach', **pool_data) + pool = self.client.pool('stomach', **pool_data) + self.addCleanup(pool.delete) + flavor_data = {'pool': 'us'} self.client.flavor('tasty', **flavor_data) flavor = self.client.flavor('tasty') + self.addCleanup(flavor.delete) + self.assertEqual(flavor.name, 'tasty') self.assertEqual(flavor.pool, 'us') - def test_flavor_delete(self): - pool_data = {'uri': 'sqlite://', + def test_flavor_update(self): + pool_data = {'weight': 10, + 'uri': 'mongodb://127.0.0.1:27017', + 'group': 'us'} + + pool = self.client.pool('stomach', **pool_data) + self.addCleanup(pool.delete) + + flavor_data = {'pool': 'us'} + flavor = self.client.flavor('tasty', **flavor_data) + self.addCleanup(flavor.delete) + flavor.update({'pool': 'belly'}) + self.assertEqual('belly', flavor.pool) + + def test_flavor_list(self): + pool_data = {'uri': 'mongodb://127.0.0.1:27017', 'weight': 10, 'group': 'us'} - self.client.pool('stomach', **pool_data) + + pool = self.client.pool('stomach', **pool_data) + self.addCleanup(pool.delete) + + flavor_data = {'pool': 'us'} + flavor = self.client.flavor("test_flavor", **flavor_data) + self.addCleanup(flavor.delete) + + flavors = self.client.flavors() + self.assertTrue(isinstance(flavors, iterator._Iterator)) + self.assertEqual(1, len(list(flavors))) + + def test_flavor_delete(self): + pool_data = {'uri': 'mongodb://127.0.0.1:27017', + 'weight': 10, + 'group': 'us'} + pool = self.client.pool('stomach', **pool_data) + self.addCleanup(pool.delete) flavor_data = {'pool': 'us'} flavor = self.client.flavor('tasty', **flavor_data) diff --git a/zaqarclient/tests/queues/pool.py b/zaqarclient/tests/queues/pool.py index 263b45c6..1c0fbfd5 100644 --- a/zaqarclient/tests/queues/pool.py +++ b/zaqarclient/tests/queues/pool.py @@ -16,6 +16,7 @@ import json import mock +from zaqarclient.queues.v1 import iterator from zaqarclient.tests.queues import base from zaqarclient.transport import errors from zaqarclient.transport import response @@ -58,6 +59,48 @@ class QueuesV1PoolUnitTest(base.QueuesTestBase): self.assertEqual(pool.name, 'test') self.assertEqual(pool.weight, 10) + def test_pool_update(self): + pool_data = {'weight': 10, + 'uri': 'sqlite://', + 'options': {}} + updated_data = {'weight': 20, + 'uri': 'sqlite://', + 'options': {}} + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(updated_data)) + send_method.return_value = resp + + pool = self.client.pool('test', **pool_data) + pool.update({'weight': 20}) + self.assertEqual(20, pool.weight) + + def test_pool_list(self): + returned = { + 'links': [{ + 'rel': 'next', + 'href': '/v1.1/pools?marker=6244-244224-783' + }], + 'pools': [{ + 'name': 'stomach', + 'weight': 20, + 'uri': 'sqlite://', + 'options': {} + }] + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(returned)) + send_method.return_value = resp + + pools_var = self.client.pools(limit=1) + self.assertIsInstance(pools_var, iterator._Iterator) + self.assertEqual(1, len(list(pools_var))) + def test_pool_delete(self): pool_data = {'weight': 10, 'uri': 'sqlite://', @@ -84,25 +127,48 @@ class QueuesV1PoolFunctionalTest(base.QueuesTestBase): def test_pool_get(self): pool_data = {'weight': 10, - 'uri': 'sqlite://'} + 'uri': 'mongodb://127.0.0.1:27017'} self.client.pool('test', **pool_data) pool = self.client.pool('test') + self.assertEqual(pool.name, 'test') self.assertEqual(pool.weight, 10) - self.assertEqual(pool.uri, 'sqlite://') + self.assertEqual(pool.uri, 'mongodb://127.0.0.1:27017') def test_pool_create(self): pool_data = {'weight': 10, - 'uri': 'sqlite://'} + 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('test', **pool_data) + self.addCleanup(pool.delete) self.assertEqual(pool.name, 'test') self.assertEqual(pool.weight, 10) + def test_pool_update(self): + pool_data = {'weight': 10, + 'uri': 'mongodb://127.0.0.1:27017', + 'options': {}} + + pool = self.client.pool('test', **pool_data) + self.addCleanup(pool.delete) + pool.update({'weight': 20}) + self.assertEqual(20, pool.weight) + + def test_pool_list(self): + pool_data = {'weight': 10, + 'uri': 'mongodb://127.0.0.1:27017', + 'options': {}} + pool = self.client.pool('test', **pool_data) + self.addCleanup(pool.delete) + + pools = self.client.pools() + self.assertTrue(isinstance(pools, iterator._Iterator)) + self.assertEqual(1, len(list(pools))) + def test_pool_delete(self): pool_data = {'weight': 10, - 'uri': 'sqlite://'} + 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('test', **pool_data) pool.delete()