From 313f175471dd87775f764b8692c6bbf9c54a8f0a Mon Sep 17 00:00:00 2001 From: dynarro Date: Tue, 4 Aug 2015 21:50:29 +0200 Subject: [PATCH] Added support to v2 Zaqarclient v2 currently has missing features that involve the management of subscriptions, but in order to these to work it is necessary to add other features such as 'queues', 'messages', 'claims', 'pools' and 'flavors'. I added 'queues' and 'messages' as a priorital step before start working with the other features and with subscriptions as well. Change-Id: Iea082cbf9e1d0e4a745bc10e41e1206af6132fad --- setup.cfg | 4 + tests/functional/queues/v2/__init__.py | 0 tests/functional/queues/v2/test_queues.py | 26 ++++++ tests/unit/queues/v2/__init__.py | 0 tests/unit/queues/v2/test_client.py | 55 +++++++++++ tests/unit/queues/v2/test_core.py | 20 ++++ tests/unit/queues/v2/test_message.py | 109 ++++++++++++++++++++++ tests/unit/queues/v2/test_queues.py | 27 ++++++ zaqarclient/queues/client.py | 4 +- zaqarclient/queues/v2/__init__.py | 0 zaqarclient/queues/v2/api.py | 6 ++ zaqarclient/queues/v2/client.py | 44 +++++++++ zaqarclient/queues/v2/core.py | 43 +++++++++ zaqarclient/queues/v2/message.py | 5 + zaqarclient/queues/v2/queues.py | 39 ++++++++ zaqarclient/tests/queues/queues.py | 4 + zaqarclient/tests/queues/v2/__init__.py | 0 zaqarclient/tests/queues/v2/messages.py | 61 ++++++++++++ zaqarclient/tests/queues/v2/queues.py | 24 +++++ 19 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 tests/functional/queues/v2/__init__.py create mode 100644 tests/functional/queues/v2/test_queues.py create mode 100644 tests/unit/queues/v2/__init__.py create mode 100644 tests/unit/queues/v2/test_client.py create mode 100644 tests/unit/queues/v2/test_core.py create mode 100644 tests/unit/queues/v2/test_message.py create mode 100644 tests/unit/queues/v2/test_queues.py create mode 100644 zaqarclient/queues/v2/__init__.py create mode 100644 zaqarclient/queues/v2/api.py create mode 100644 zaqarclient/queues/v2/client.py create mode 100644 zaqarclient/queues/v2/core.py create mode 100644 zaqarclient/queues/v2/message.py create mode 100644 zaqarclient/queues/v2/queues.py create mode 100644 zaqarclient/tests/queues/v2/__init__.py create mode 100644 zaqarclient/tests/queues/v2/messages.py create mode 100644 zaqarclient/tests/queues/v2/queues.py diff --git a/setup.cfg b/setup.cfg index 60384163..39ea95b7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,9 +40,13 @@ zaqarclient.transport = http.v1.1 = zaqarclient.transport.http:HttpTransport https.v1.1 = zaqarclient.transport.http:HttpTransport + http.v2 = zaqarclient.transport.http:HttpTransport + https.v2 = zaqarclient.transport.http:HttpTransport + zaqarclient.api = queues.v1 = zaqarclient.queues.v1.api:V1 queues.v1.1 = zaqarclient.queues.v1.api:V1_1 + queues.v2 = zaqarclient.queues.v2.api:V2 openstack.messaging.v1 = queue_list = zaqarclient.queues.v1.cli:ListQueues diff --git a/tests/functional/queues/v2/__init__.py b/tests/functional/queues/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/functional/queues/v2/test_queues.py b/tests/functional/queues/v2/test_queues.py new file mode 100644 index 00000000..5ef40ca6 --- /dev/null +++ b/tests/functional/queues/v2/test_queues.py @@ -0,0 +1,26 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from zaqarclient.tests.queues import queues +from zaqarclient.transport import http + + +class QueuesV2QueueHttpFunctionalTest(queues.QueuesV2QueueFunctionalTest): + + is_functional = True + transport_cls = http.HttpTransport + url = 'http://127.0.0.1:8888' + version = 2 diff --git a/tests/unit/queues/v2/__init__.py b/tests/unit/queues/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/queues/v2/test_client.py b/tests/unit/queues/v2/test_client.py new file mode 100644 index 00000000..4433c87a --- /dev/null +++ b/tests/unit/queues/v2/test_client.py @@ -0,0 +1,55 @@ +# Copyright 2014 IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import mock + +import ddt + +from zaqarclient.queues import client +from zaqarclient.queues.v1 import core +from zaqarclient.tests import base +from zaqarclient.transport import errors + +VERSIONS = [2] + + +@ddt.ddt +class TestClient(base.TestBase): + + @ddt.data(*VERSIONS) + def test_transport(self, version): + cli = client.Client('http://example.com', + version, {}) + self.assertIsNotNone(cli.transport()) + + @ddt.data(*VERSIONS) + def test_health_ok(self, version): + cli = client.Client('http://example.com', + version, {}) + with mock.patch.object(core, 'health', autospec=True) as core_health: + core_health.return_value = None + self.assertTrue(cli.health()) + + @ddt.data(*VERSIONS) + def test_health_bad(self, version): + cli = client.Client('http://example.com', + version, {}) + + def raise_error(*args, **kwargs): + raise errors.ServiceUnavailableError() + + with mock.patch.object(core, 'health', autospec=True) as core_health: + core_health.side_effect = raise_error + self.assertFalse(cli.health()) diff --git a/tests/unit/queues/v2/test_core.py b/tests/unit/queues/v2/test_core.py new file mode 100644 index 00000000..7df54596 --- /dev/null +++ b/tests/unit/queues/v2/test_core.py @@ -0,0 +1,20 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from tests.unit.queues.v1 import test_core + + +class TestV2Core(test_core.TestV1Core): + pass diff --git a/tests/unit/queues/v2/test_message.py b/tests/unit/queues/v2/test_message.py new file mode 100644 index 00000000..6cef88f0 --- /dev/null +++ b/tests/unit/queues/v2/test_message.py @@ -0,0 +1,109 @@ +# Copyright (c) 2013 Rackspace, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import mock + +from tests.unit.queues.v1 import test_message as msg +from zaqarclient.queues.v1 import iterator as iterate +from zaqarclient.queues.v1 import message +from zaqarclient.transport import http +from zaqarclient.transport import response + + +class TestMessageIterator(msg.TestMessageIterator): + def test_no_next_iteration(self): + messages = {'links': [], + 'messages': [{ + 'href': '/v2/queues/mine/messages/123123423', + 'ttl': 800, + 'age': 790, + 'body': {'event': 'ActivateAccount', + 'mode': 'active'} + }] + } + + iterator = iterate._Iterator(self.queue.client, + messages, + 'messages', + message.create_object(self.queue)) + iterated = [msg for msg in iterator] + self.assertEqual(len(iterated), 1) + + def test_stream(self): + messages = {'links': [], + 'messages': [{ + 'href': '/v2/queues/mine/messages/123123423', + 'ttl': 800, + 'age': 790, + 'body': {'event': 'ActivateAccount', + 'mode': 'active'} + }] + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(messages)) + send_method.return_value = resp + + # NOTE(flaper87): The first iteration will return 1 message + # and then call `_next_page` which will use the rel-next link + # to get a new set of messages. + link = {'rel': 'next', + 'href': "/v2/queues/mine/messages?marker=6244-244224-783"} + messages['links'].append(link) + + iterator = iterate._Iterator(self.queue.client, + messages, + 'messages', + message.create_object(self.queue)) + iterated = [msg for msg in iterator.stream()] + self.assertEqual(len(iterated), 2) + + def test_iterator_respect_paging(self): + messages = {'links': [], + 'messages': [{ + 'href': '/v2/queues/mine/messages/123123423', + 'ttl': 800, + 'age': 790, + 'body': {'event': 'ActivateAccount', + 'mode': 'active'} + }] + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(messages)) + send_method.return_value = resp + + link = {'rel': 'next', + 'href': "/v2/queues/mine/messages?marker=6244-244224-783"} + messages['links'].append(link) + + iterator = iterate._Iterator(self.queue.client, + messages, + 'messages', + message.create_object(self.queue)) + iterated = [msg for msg in iterator] + self.assertEqual(len(iterated), 1) + + +class QueuesV2MessageHttpUnitTest(msg.QueuesV1MessageHttpUnitTest): + + transport_cls = http.HttpTransport + url = 'http://127.0.0.1:8888/v2' + version = 2 diff --git a/tests/unit/queues/v2/test_queues.py b/tests/unit/queues/v2/test_queues.py new file mode 100644 index 00000000..88103b86 --- /dev/null +++ b/tests/unit/queues/v2/test_queues.py @@ -0,0 +1,27 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from tests.unit.queues.v1 import test_queues +from zaqarclient.transport import http + + +class QueuesV2QueueHttpUnitTest(test_queues.QueuesV1QueueHttpUnitTest): + + transport_cls = http.HttpTransport + url = 'http://127.0.0.1:8888/v2' + version = 2 + + def test_queue_exists(self): + pass diff --git a/zaqarclient/queues/client.py b/zaqarclient/queues/client.py index e898c8b8..9c035cf4 100644 --- a/zaqarclient/queues/client.py +++ b/zaqarclient/queues/client.py @@ -70,9 +70,11 @@ the underlying API, although not recommended. """ from zaqarclient import errors from zaqarclient.queues.v1 import client as cv1 +from zaqarclient.queues.v2 import client as cv2 _CLIENTS = {1: cv1.Client, - 1.1: cv1.Client} + 1.1: cv1.Client, + 2: cv2.Client} def Client(url=None, version=None, conf=None): diff --git a/zaqarclient/queues/v2/__init__.py b/zaqarclient/queues/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/zaqarclient/queues/v2/api.py b/zaqarclient/queues/v2/api.py new file mode 100644 index 00000000..cabeef30 --- /dev/null +++ b/zaqarclient/queues/v2/api.py @@ -0,0 +1,6 @@ +from zaqarclient.queues.v1 import api + + +class V2(api.V1_1): + label = 'v2' + schema = api.V1_1.schema.copy() diff --git a/zaqarclient/queues/v2/client.py b/zaqarclient/queues/v2/client.py new file mode 100644 index 00000000..18d2e812 --- /dev/null +++ b/zaqarclient/queues/v2/client.py @@ -0,0 +1,44 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import uuid + +from zaqarclient.queues.v1 import client + + +class Client(client.Client): + """Client base class + + :param url: Zaqar's instance base url. + :type url: `six.text_type` + :param version: API Version pointing to. + :type version: `int` + :param options: Extra options: + - client_uuid: Custom client uuid. A new one + will be generated, if not passed. + - auth_opts: Authentication options: + - backend + - options + :type options: `dict` + """ + + def __init__(self, url=None, version=2, conf=None): + self.conf = conf or {} + + self.api_url = url + self.api_version = version + self.auth_opts = self.conf.get('auth_opts', {}) + self.client_uuid = self.conf.get('client_uuid', + uuid.uuid4().hex) diff --git a/zaqarclient/queues/v2/core.py b/zaqarclient/queues/v2/core.py new file mode 100644 index 00000000..0ee7c1e5 --- /dev/null +++ b/zaqarclient/queues/v2/core.py @@ -0,0 +1,43 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +This module defines a lower level API for queues' v2. This level of the +API is responsible for packing up the final request, sending it to the server +and handling asynchronous requests. + +Functions present in this module assume that: + + 1. The transport instance is ready to `send` the + request to the server. + + 2. Transport instance holds the conf instance to use for this + request. +""" + +from zaqarclient.queues.v1 import core + +queue_create = core.queue_create +queue_exists = core.queue_exists +queue_get = core.queue_get +queue_get_metadata = core.queue_get_metadata +queue_set_metadata = core.queue_set_metadata +queue_get_stats = core.queue_get_stats +queue_delete = core.queue_delete +queue_list = core.queue_list +message_list = core.message_list +message_post = core.message_post +message_delete = core.message_delete +message_delete_many = core.message_delete_many diff --git a/zaqarclient/queues/v2/message.py b/zaqarclient/queues/v2/message.py new file mode 100644 index 00000000..41a8a687 --- /dev/null +++ b/zaqarclient/queues/v2/message.py @@ -0,0 +1,5 @@ +from zaqarclient.queues.v1 import message + + +class Message(message.Message): + pass diff --git a/zaqarclient/queues/v2/queues.py b/zaqarclient/queues/v2/queues.py new file mode 100644 index 00000000..3cf0fbf4 --- /dev/null +++ b/zaqarclient/queues/v2/queues.py @@ -0,0 +1,39 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from zaqarclient import errors +from zaqarclient.queues.v1 import queues +from zaqarclient.queues.v2 import core +from zaqarclient.queues.v2 import message + + +class Queue(queues.Queue): + + def message(self, message_id): + """Gets a message by id + + :param message_id: Message's reference + :type message_id: `six.text_type` + + :returns: A message + :rtype: `dict` + """ + req, trans = self.client._request_and_transport() + if self.client.api_version >= 2: + raise errors.InvalidOperation("Unavailable on versions >= 2") + else: + msg = core.message_get(trans, req, self._name, + message_id) + return message.Message(self, **msg) diff --git a/zaqarclient/tests/queues/queues.py b/zaqarclient/tests/queues/queues.py index a0431bbb..e23e93a5 100644 --- a/zaqarclient/tests/queues/queues.py +++ b/zaqarclient/tests/queues/queues.py @@ -461,3 +461,7 @@ class QueuesV1_1QueueFunctionalTest(QueuesV1QueueFunctionalTest): remaining = queue.messages(echo=True) self.assertEqual(1, len(list(remaining))) + + +class QueuesV2QueueFunctionalTest(QueuesV1_1QueueFunctionalTest): + pass diff --git a/zaqarclient/tests/queues/v2/__init__.py b/zaqarclient/tests/queues/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/zaqarclient/tests/queues/v2/messages.py b/zaqarclient/tests/queues/v2/messages.py new file mode 100644 index 00000000..26d30a76 --- /dev/null +++ b/zaqarclient/tests/queues/v2/messages.py @@ -0,0 +1,61 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import mock + +from zaqarclient.tests.queues.v1 import messages +from zaqarclient.transport import response + + +class QueuesV2MessageUnitTest(messages.QueuesV1MessageUnitTest): + + def test_message_delete(self): + returned = { + 'href': '/v2/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01', + 'ttl': 800, + 'age': 790, + 'body': {'event': 'ActivateAccount', 'mode': 'active'} + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(returned)) + send_method.return_value = resp + + msg = self.queue.message('50b68a50d6f5b8c8a7c62b01') + + send_method.return_value = None + self.assertIsNone(msg.delete()) + + def test_message_delete_with_claim(self): + returned = { + 'href': '/v2/queues/fizbit/messages/50b68a50d6?claim_id=5388b5dd0', + 'ttl': 800, + 'age': 790, + 'body': {'event': 'ActivateAccount', 'mode': 'active'} + } + + with mock.patch.object(self.transport, 'send', + autospec=True) as send_method: + + resp = response.Response(None, json.dumps(returned)) + send_method.return_value = resp + + msg = self.queue.message('50b68a50d6') + + send_method.return_value = None + self.assertIsNone(msg.delete()) diff --git a/zaqarclient/tests/queues/v2/queues.py b/zaqarclient/tests/queues/v2/queues.py new file mode 100644 index 00000000..45f9592e --- /dev/null +++ b/zaqarclient/tests/queues/v2/queues.py @@ -0,0 +1,24 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from zaqarclient.tests.queues.v1 import queues + + +class QueuesV2QueueUnitTest(queues.QueuesV1_1QueueUnitTest): + pass + + +class QueuesV2QueueFunctionalTest(queues.QueuesV1_1QueueFunctionalTest): + pass