python-zaqarclient-1.11.0/0000775000175000017500000000000013364112773015457 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/lower-constraints.txt0000666000175000017500000000244413364112606021716 0ustar zuulzuul00000000000000alabaster==0.7.10 appdirs==1.3.0 Babel==2.3.4 cliff==2.8.0 cmd2==0.8.0 colorama==0.3.9 coverage==4.0 ddt==1.0.1 debtcollector==1.2.0 decorator==3.4.0 deprecation==1.0 docutils==0.11 dogpile.cache==0.6.2 dulwich==0.15.0 extras==1.0.0 fixtures==3.0.0 flake8==2.5.5 hacking==0.12.0 imagesize==0.7.1 iso8601==0.1.11 Jinja2==2.10 jmespath==0.9.0 jsonpatch==1.16 jsonpointer==1.13 jsonschema==2.6.0 keystoneauth1==3.4.0 linecache2==1.0.0 MarkupSafe==1.0 mccabe==0.2.1 mock==2.0.0 monotonic==0.6 msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 openstackdocstheme==1.18.1 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 osc-lib==1.8.0 oslo.config==5.2.0 oslo.context==2.19.2 oslo.i18n==3.15.3 oslo.log==3.36.0 oslo.serialization==2.18.0 oslo.utils==3.33.0 pbr==2.0.0 pep8==1.5.7 prettytable==0.7.2 pyflakes==0.8.1 Pygments==2.2.0 pyinotify==0.9.6 pyparsing==2.1.0 pyperclip==1.5.27 python-dateutil==2.5.3 python-mimeparse==1.6.0 python-subunit==1.0.0 pytz==2013.6 PyYAML==3.12 reno==2.5.0 requests==2.14.2 requests-mock==1.2.0 requestsexceptions==1.2.0 rfc3986==0.3.1 simplejson==3.5.1 six==1.10.0 snowballstemmer==1.2.1 Sphinx==1.6.5 sphinxcontrib-websupport==1.0.1 stestr==1.0.0 stevedore==1.20.0 termcolor==1.1.0 testtools==2.2.0 traceback2==1.4.0 unittest2==1.1.0 wrapt==1.7.0 python-zaqarclient-1.11.0/tests/0000775000175000017500000000000013364112773016621 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/0000775000175000017500000000000013364112773017600 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/0000775000175000017500000000000013364112773021107 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v2/0000775000175000017500000000000013364112773021436 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v2/test_subscription.py0000666000175000017500000000152413364112606025572 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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 subscriptions as sub from zaqarclient.transport import http class QueuesV2SubscriptionHttpUnitTest(sub.QueuesV2SubscriptionUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/v2/test_flavor.py0000666000175000017500000000147313364112606024342 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 flavor from zaqarclient.transport import http class QueuesV2FlavorHttpUnitTest(flavor.QueuesV2FlavorUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/v2/test_core.py0000666000175000017500000000124513364112606023776 0ustar zuulzuul00000000000000# 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 python-zaqarclient-1.11.0/tests/unit/queues/v2/test_pool.py0000666000175000017500000000146313364112606024021 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 pool from zaqarclient.transport import http class QueuesV2PoolHttpUnitTest(pool.QueuesV2PoolUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/v2/test_queues.py0000666000175000017500000000154713364112606024362 0ustar zuulzuul00000000000000# 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 QueuesV2QueueHttpUnitTest(queues.QueuesV2QueueUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 def test_queue_exists(self): pass python-zaqarclient-1.11.0/tests/unit/queues/v2/test_claims.py0000666000175000017500000000147013364112606024316 0ustar zuulzuul00000000000000# Copyright (c) Rackspace Hosting. # # 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 claims from zaqarclient.transport import http class QueuesV2ClaimsHttpUnitTest(claims.QueueV2ClaimUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/v2/__init__.py0000666000175000017500000000000013364112606023532 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v2/test_client.py0000666000175000017500000000342213364112606024323 0ustar zuulzuul00000000000000# 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.tests.queues import base from zaqarclient.transport import errors from zaqarclient.transport import http VERSIONS = [2] @ddt.ddt class TestClient(base.QueuesTestBase): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = VERSIONS[0] @ddt.data(*VERSIONS) def test_transport(self, version): cli = client.Client('http://example.com', version, {"auth_opts": {'backend': 'noauth'}}) self.assertIsNotNone(cli.transport()) @ddt.data(*VERSIONS) def test_ping_ok(self, version): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.return_value = None self.assertTrue(self.client.ping()) @ddt.data(*VERSIONS) def test_ping_bad(self, version): def raise_error(*args, **kwargs): raise errors.ServiceUnavailableError() with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.side_effect = raise_error self.assertFalse(self.client.ping()) python-zaqarclient-1.11.0/tests/unit/queues/v2/test_message.py0000666000175000017500000001027013364112606024470 0ustar zuulzuul00000000000000# 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 zaqarclient.queues.v1 import iterator as iterate from zaqarclient.queues.v2 import message from zaqarclient.tests.queues import base from zaqarclient.tests.queues import messages as test_message from zaqarclient.transport import http from zaqarclient.transport import response class TestMessageIterator(base.QueuesTestBase): 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(test_message.QueuesV2MessageUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/v2/test_health.py0000666000175000017500000000147513364112606024320 0ustar zuulzuul00000000000000# Copyright (c) 2016 Catalyst IT Ltd. # # 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 health from zaqarclient.transport import http class QueuesV2HealthHttpUnitTest(health.QueuesV2HealthUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v2' version = 2 python-zaqarclient-1.11.0/tests/unit/queues/transport/0000775000175000017500000000000013364112773023143 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/transport/zmq/0000775000175000017500000000000013364112773023752 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/transport/zmq/__init__.py0000666000175000017500000000000013364112606026046 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/transport/__init__.py0000666000175000017500000000000013364112606025237 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/transport/http/0000775000175000017500000000000013364112773024122 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/transport/http/__init__.py0000666000175000017500000000000013364112606026216 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v1/0000775000175000017500000000000013364112773021435 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v1/test_flavor.py0000666000175000017500000000150313364112606024333 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 flavor from zaqarclient.transport import http class QueuesV1_1FlavorHttpUnitTest(flavor.QueuesV1_1FlavorUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1.1' version = 1.1 python-zaqarclient-1.11.0/tests/unit/queues/v1/test_core.py0000666000175000017500000002326513364112606024003 0ustar zuulzuul00000000000000# 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.queues.v1 import core from zaqarclient.tests import base from zaqarclient.tests.transport import dummy from zaqarclient.transport import errors from zaqarclient.transport import request from zaqarclient.transport import response class TestV1Core(base.TestBase): def setUp(self): super(TestV1Core, self).setUp() self.transport = dummy.DummyTransport(self.conf) def test_queue_create(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.return_value = response.Response(None, None) req = request.Request() core.queue_create(self.transport, req, 'test') self.assertIn('queue_name', req.params) def test_queue_delete(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.return_value = response.Response(None, None) req = request.Request() core.queue_delete(self.transport, req, 'test') self.assertIn('queue_name', req.params) def test_queue_exists(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.return_value = response.Response(None, None) req = request.Request() ret = core.queue_exists(self.transport, req, 'test') self.assertIn('queue_name', req.params) self.assertTrue(ret) def test_queue_exists_not_found(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.side_effect = errors.ResourceNotFound req = request.Request() ret = core.queue_exists(self.transport, req, 'test') self.assertIn('queue_name', req.params) self.assertFalse(ret) def test_get_queue_metadata(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.queue_get_metadata(self.transport, req, 'test') def test_set_queue_metadata(self): update_data = {'some': 'data'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.return_value = response.Response(None, None) req = request.Request() core.queue_exists(self.transport, req, update_data, 'test') self.assertIn('queue_name', req.params) def test_queue_get_stats(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() result = core.queue_get_stats(self.transport, req, 'test') self.assertEqual({}, result) def test_message_post_one(self): messages = {'ttl': 30, 'body': 'Post one!'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_post(self.transport, req, 'test', messages) self.assertIn('queue_name', req.params) self.assertEqual(messages, json.loads(req.content)) def test_message_post_many(self): messages = [{'ttl': 30, 'body': 'Post one!'}, {'ttl': 30, 'body': 'Post two!'}, {'ttl': 30, 'body': 'Post three!'}, ] with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_post(self.transport, req, 'test', messages) self.assertIn('queue_name', req.params) self.assertEqual(messages, json.loads(req.content)) def test_message_list(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_list(self.transport, req, 'test') self.assertIn('queue_name', req.params) def test_message_list_kwargs(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_list(self.transport, req, 'test', marker='supermarket', echo=False, limit=10) self.assertIn('queue_name', req.params) self.assertIn('limit', req.params) self.assertIn('echo', req.params) self.assertIn('marker', req.params) def test_message_get_many(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() ids = ['a', 'b'] core.message_get_many(self.transport, req, 'test', ids) self.assertIn('queue_name', req.params) self.assertIn('ids', req.params) self.assertEqual(ids, req.params['ids']) def test_message_get(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_get(self.transport, req, 'test', 'message_id') def test_message_delete(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp req = request.Request() core.message_delete(self.transport, req, 'test', 'message_id') def test_message_delete_many(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp ids = ['a', 'b'] req = request.Request() core.message_delete_many(self.transport, req, 'test', ids=ids) self.assertIn('queue_name', req.params) self.assertIn('ids', req.params) self.assertEqual(ids, req.params['ids']) # ADMIN API def test_pool_create(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp req = request.Request() core.pool_create(self.transport, req, 'test_pool', {'uri': 'sqlite://', 'weight': 0}) def test_pool_get(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp req = request.Request() core.pool_get(self.transport, req, 'test_pool') def test_pool_delete(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp req = request.Request() core.pool_delete(self.transport, req, 'test_pool') def test_health(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp req = request.Request() core.health(self.transport, req) class TestV1_1Core(TestV1Core): def test_message_pop(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, '{}') send_method.return_value = resp req = request.Request() core.message_pop(self.transport, req, 'test', count=5) self.assertIn('queue_name', req.params) self.assertIn('pop', req.params) self.assertEqual(5, req.params['pop']) python-zaqarclient-1.11.0/tests/unit/queues/v1/test_pool.py0000666000175000017500000000146313364112606024020 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 pool from zaqarclient.transport import http class QueuesV1PoolHttpUnitTest(pool.QueuesV1PoolUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1' version = 1 python-zaqarclient-1.11.0/tests/unit/queues/v1/test_queues.py0000666000175000017500000000201613364112606024351 0ustar zuulzuul00000000000000# 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 QueuesV1QueueHttpUnitTest(queues.QueuesV1QueueUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1' version = 1 class QueuesV1_1QueueHttpUnitTest(queues.QueuesV1_1QueueUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1.1' version = 1.1 def test_queue_exists(self): pass python-zaqarclient-1.11.0/tests/unit/queues/v1/test_claims.py0000666000175000017500000000173713364112606024323 0ustar zuulzuul00000000000000# Copyright (c) Rackspace Hosting. # # 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 claims from zaqarclient.transport import http class QueuesV1ClaimsHttpUnitTest(claims.QueueV1ClaimUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1' version = 1 class QueuesV1_1ClaimsHttpUnitTest(claims.QueueV1_1ClaimUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1.1' version = 1.1 python-zaqarclient-1.11.0/tests/unit/queues/v1/__init__.py0000666000175000017500000000000013364112606023531 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/v1/test_client.py0000666000175000017500000000351113364112606024321 0ustar zuulzuul00000000000000# 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 = [1, 1.1] @ddt.ddt class TestClient(base.TestBase): @ddt.data(*VERSIONS) def test_transport(self, version): cli = client.Client('http://example.com', version, {"auth_opts": {'backend': 'noauth'}}) self.assertIsNotNone(cli.transport()) @ddt.data(*VERSIONS) def test_health_ok(self, version): cli = client.Client('http://example.com', version, {"auth_opts": {'backend': 'noauth'}}) 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, {"auth_opts": {'backend': 'noauth'}}) 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()) python-zaqarclient-1.11.0/tests/unit/queues/v1/test_message.py0000666000175000017500000001054713364112606024476 0ustar zuulzuul00000000000000# 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 zaqarclient.queues.v1 import iterator as iterate from zaqarclient.queues.v1 import message from zaqarclient.tests.queues import base from zaqarclient.tests.queues import messages as test_message from zaqarclient.transport import http from zaqarclient.transport import response class TestMessageIterator(base.QueuesTestBase): def test_no_next_iteration(self): messages = {'links': [], 'messages': [{ 'href': '/v1/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(1, len(iterated)) def test_stream(self): messages = {'links': [], 'messages': [{ 'href': '/v1/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': "/v1/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(2, len(iterated)) def test_iterator_respect_paging(self): messages = {'links': [], 'messages': [{ 'href': '/v1/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': "/v1/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(1, len(iterated)) class QueuesV1MessageHttpUnitTest(test_message.QueuesV1MessageUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1' version = 1 class QueuesV1_1MessageHttpUnitTest(test_message.QueuesV1MessageUnitTest): transport_cls = http.HttpTransport url = 'http://127.0.0.1:8888/v1.1' version = 1.1 python-zaqarclient-1.11.0/tests/unit/queues/__init__.py0000666000175000017500000000000013364112606023203 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/queues/test_client.py0000666000175000017500000000243513364112606023777 0ustar zuulzuul00000000000000# 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 zaqarclient from zaqarclient import errors from zaqarclient.queues import client from zaqarclient.tests import base class TestClient(base.TestBase): def test_get_instance(self): version = list(client._CLIENTS.keys())[0] cli = client.Client('http://example.com', version, {}) self.assertIsInstance(cli, client._CLIENTS[version]) def test_version_failure(self): self.assertRaises(errors.ZaqarError, client.Client, 'http://example.org', -1, {}) def test_module_version(self): self.assertTrue(hasattr(zaqarclient, '__version__')) python-zaqarclient-1.11.0/tests/unit/auth/0000775000175000017500000000000013364112773020541 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/auth/test_base.py0000666000175000017500000000200013364112606023051 0ustar zuulzuul00000000000000# 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 auth from zaqarclient.tests import base class TestBaseAuth(base.TestBase): def test_get_backend(self): try: auth.get_backend(options=self.conf) except KeyError: self.fail("Test failed") def test_get_non_existing_backend(self): try: auth.get_backend('not_existing') self.fail("Test failed") except KeyError: pass python-zaqarclient-1.11.0/tests/unit/auth/__init__.py0000666000175000017500000000000013364112606022635 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/auth/test_keystone.py0000666000175000017500000000377513364112606024024 0ustar zuulzuul00000000000000# 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 mock from keystoneauth1 import session from zaqarclient import auth from zaqarclient.tests import base from zaqarclient.transport import request class TestKeystoneAuth(base.TestBase): def setUp(self): super(TestKeystoneAuth, self).setUp() self.auth = auth.get_backend(options=self.conf) @mock.patch('keystoneauth1.session.Session.get_token', return_value='fake-token') def test_no_token(self, fake_session): test_endpoint = 'http://example.org:8888' keystone_session = session.Session() with mock.patch.object(self.auth, '_get_endpoint') as get_endpoint: with mock.patch.object(self.auth, '_get_keystone_session') as get_session: get_endpoint.return_value = test_endpoint get_session.return_value = keystone_session req = self.auth.authenticate(1, request.Request()) self.assertEqual(test_endpoint, req.endpoint) self.assertIn('X-Auth-Token', req.headers) self.assertIn(req.headers['X-Auth-Token'], 'fake-token') def test_with_token(self): self.auth.conf.update({"auth_token": "test-token"}) req = request.Request(endpoint='http://example.org:8888') req = self.auth.authenticate(1, req) self.assertIn('X-Auth-Token', req.headers) self.assertIn(req.headers['X-Auth-Token'], 'test-token') python-zaqarclient-1.11.0/tests/unit/openstack/0000775000175000017500000000000013364112773021567 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/openstack/common/0000775000175000017500000000000013364112773023057 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/openstack/common/__init__.py0000666000175000017500000000000013364112606025153 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/transport/0000775000175000017500000000000013364112773021634 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/transport/test_ws.py0000666000175000017500000000476313364112606023705 0ustar zuulzuul00000000000000# 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 import base from zaqarclient.transport import request from zaqarclient.transport import ws class TestWsTransport(base.TestBase): def setUp(self): super(TestWsTransport, self).setUp() os_opts = { 'os_auth_token': 'FAKE_TOKEN', 'os_auth_url': 'http://127.0.0.0:5000/v3', 'os_project_id': 'admin', 'os_service_type': 'messaging-websocket', } auth_opts = {'backend': 'keystone', 'options': os_opts} self.options = {'auth_opts': auth_opts} self.endpoint = 'ws://127.0.0.1:9000' @mock.patch.object(ws.WebsocketTransport, "_create_connection") def test_make_client(self, ws_create_connection): ws_create_connection.return_value.recv.return_value = json.dumps({ "headers": { "status": 200 } }) transport = ws.WebsocketTransport(self.options) req = request.Request(self.endpoint) transport.send(req) ws_create_connection.assert_called_with("ws://127.0.0.1:9000") @mock.patch.object(ws.WebsocketTransport, "recv") @mock.patch.object(ws.WebsocketTransport, "_create_connection") def test_recv(self, ws_create_connection, recv_mock): send_ack = { "headers": { "status": 200 } } recv_mock.side_effect = [send_ack, send_ack, send_ack, { "body": { "payload": "foo" } }, send_ack] transport = ws.WebsocketTransport(self.options) req = request.Request(self.endpoint) transport.send(req) count = 0 while True: count += 1 data = transport.recv() if 'body' in data: self.assertEqual(data['body']['payload'], 'foo') break if count >= 4: self.fail('Failed to receive expected message.') python-zaqarclient-1.11.0/tests/unit/transport/test_api.py0000666000175000017500000000270313364112606024015 0ustar zuulzuul00000000000000# 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.tests import base from zaqarclient.tests.transport import api as tapi class TestApi(base.TestBase): def setUp(self): super(TestApi, self).setUp() self.api = tapi.FakeApi() def test_valid_params(self): self.assertTrue(self.api.validate('test_operation', {'name': 'Sauron'})) def test_invalid_params(self): self.assertFalse(self.api.validate('test_operation', {'name': 'Sauron', 'lastname': 'From Mordor'})) def test_missing_params(self): self.assertFalse(self.api.validate('test_operation', {})) def test_invalid_operation(self): self.assertRaises(errors.InvalidOperation, self.api.validate, 'super_secret_op', {}) python-zaqarclient-1.11.0/tests/unit/transport/test_http.py0000666000175000017500000001065313364112606024226 0ustar zuulzuul00000000000000# 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 mock import requests as prequest from requests.packages.urllib3 import response from zaqarclient.tests import base from zaqarclient.tests.transport import api from zaqarclient.transport import http from zaqarclient.transport import request class TestHttpTransport(base.TestBase): """Tests for the HTTP transport.""" def setUp(self): super(TestHttpTransport, self).setUp() self.api = api.FakeApi() self.transport = http.HttpTransport(self.conf) @mock.patch.object(prequest.packages.urllib3.response.HTTPResponse, 'stream') def test_basic_send(self, mock_stream): params = {'name': 'Test', 'address': 'Outer space'} req = request.Request('http://example.org/', operation='test_operation', params=params) with mock.patch.object(self.transport.client, 'request', autospec=True) as request_method: resp = prequest.Response() raw = response.HTTPResponse() resp.raw = raw request_method.return_value = resp # NOTE(flaper87): Bypass the API # loading step by setting the _api # attribute req._api = self.api self.transport.send(req) final_url = 'http://example.org/v1/test/Test' final_params = {'address': 'Outer space'} final_headers = {'content-type': 'application/json'} request_method.assert_called_with('GET', url=final_url, params=final_params, headers=final_headers, data=None, verify=True) @mock.patch.object(prequest.packages.urllib3.response.HTTPResponse, 'stream') def test_send_without_api(self, mock_stream): params = {'name': 'Test', 'address': 'Outer space'} req = request.Request('http://example.org/', operation='test_operation', params=params) with mock.patch.object(self.transport.client, 'request', autospec=True) as request_method: resp = prequest.Response() raw = response.HTTPResponse() resp.raw = raw request_method.return_value = resp self.transport.send(req) final_url = 'http://example.org/' final_headers = {'content-type': 'application/json'} request_method.assert_called_with('GET', url=final_url, params=params, headers=final_headers, data=None, verify=True) @mock.patch.object(prequest.packages.urllib3.response.HTTPResponse, 'stream') def test_error_handling(self, mock_stream): params = {'name': 'Opportunity', 'address': 'NASA'} req = request.Request('http://example.org/', operation='test_operation', params=params) with mock.patch.object(self.transport.client, 'request', autospec=True) as request_method: exception_iterator = self.transport.http_to_zaqar.items() for response_code, exception in exception_iterator: resp = prequest.Response() raw = response.HTTPResponse() resp.raw = raw resp.status_code = response_code request_method.return_value = resp self.assertRaises(exception, lambda: self.transport.send(req)) python-zaqarclient-1.11.0/tests/unit/transport/__init__.py0000666000175000017500000000000013364112606023730 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/transport/test_request.py0000666000175000017500000000471413364112606024740 0ustar zuulzuul00000000000000# Copyright (c) 2013 Rackspace, Inc. # 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 from zaqarclient.queues.v1 import api as api_v1 from zaqarclient.queues.v2 import api as api_v2 from zaqarclient.tests import base from zaqarclient.transport import request class TestRequest(base.TestBase): def test_request_project_id(self): auth_opts = { 'options': { 'os_project_id': 'my-project' } } auth_opts.update({'backend': 'noauth'}) req = request.prepare_request(auth_opts) self.assertEqual('my-project', req.headers['X-Project-Id']) def test_prepare_request(self): auth_opts = self.conf.get('auth_opts', {}) req = request.prepare_request(auth_opts) self.assertIsInstance(req, request.Request) self.assertIsNone(req.content) def test_prepare_request_with_data(self): auth_opts = self.conf.get('auth_opts', {}) data = {"data": "tons of GBs"} req = request.prepare_request(auth_opts, data=data) self.assertIsInstance(req, request.Request) self.assertEqual(json.dumps(data), req.content) def test_request_with_right_version(self): auth_opts = self.conf.get('auth_opts', {}) api_version = 1 req = request.prepare_request(auth_opts, api=api_version) self.assertIsInstance(req.api, api_v1.V1) api_version = 1.0 req = request.prepare_request(auth_opts, api=api_version) self.assertIsInstance(req.api, api_v1.V1) api_version = 1.1 req = request.prepare_request(auth_opts, api=api_version) self.assertIsInstance(req.api, api_v1.V1_1) api_version = 2 req = request.prepare_request(auth_opts, api=api_version) self.assertIsInstance(req.api, api_v2.V2) api_version = 2.0 req = request.prepare_request(auth_opts, api=api_version) self.assertIsInstance(req.api, api_v2.V2) python-zaqarclient-1.11.0/tests/unit/common/0000775000175000017500000000000013364112773021070 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/common/test_http.py0000666000175000017500000000236513364112606023463 0ustar zuulzuul00000000000000# 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.common import http from zaqarclient.tests import base class TestCommonHttp(base.TestBase): def setUp(self): super(TestCommonHttp, self).setUp() self.client = http.Client() def test_data_serialization(self): data = {'some': 'data'} for method in ['post', 'put', 'patch']: with mock.patch.object(self.client.session, method, autospec=True) as request_method: request_method.return_value = True getattr(self.client, method)("url", data=data) request_method.assert_called_with('url', data=json.dumps(data)) python-zaqarclient-1.11.0/tests/unit/common/__init__.py0000666000175000017500000000000013364112606023164 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/__init__.py0000666000175000017500000000000013364112606021674 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/cli/0000775000175000017500000000000013364112773020347 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/cli/v1/0000775000175000017500000000000013364112773020675 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/cli/v1/test_queues.py0000666000175000017500000000446313364112606023621 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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.cli import fakes from zaqarclient.queues.v1 import cli as v1_cli from zaqarclient.queues.v1 import iterator from zaqarclient.queues.v1 import queues as v1_api_queues class TestQueues(fakes.TestMessaging): def setUp(self): super(TestQueues, self).setUp() class TestV1ListQueues(TestQueues): def setUp(self): super(TestV1ListQueues, self).setUp() queues_list = iterator._Iterator(self, [{'name': 'fake_queue'}], 'queues', v1_api_queues.create_object(self)) self.app.client_manager.messaging.queues.return_value = queues_list # Command to test self.cmd = v1_cli.ListQueues(self.app, None) def test_queues_list(self): arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Check that columns are correct expected_columns = ('Name',) self.assertEqual(expected_columns, columns) # Check that data is correct expected_data = [('fake_queue',)] self.assertEqual(expected_data, list(data)) class TestV1CreateQueue(TestQueues): def setUp(self): super(TestV1CreateQueue, self).setUp() # Command to test self.cmd = v1_cli.CreateQueue(self.app, None) def test_queue_create(self): arglist = ['fake_queue'] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.messaging_client.queue.assert_called_with('fake_queue', force_create=True) python-zaqarclient-1.11.0/tests/unit/cli/v1/__init__.py0000666000175000017500000000000013364112606022771 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/unit/cli/fakes.py0000666000175000017500000000213313364112606022006 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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 from osc_lib.tests import utils class TestMessaging(utils.TestCommand): def setUp(self): super(TestMessaging, self).setUp() self.messaging_client = mock.MagicMock() # TODO(flwang): It would be nice if we can figure out a better way to # get the mocked request and transport. req_trans = (mock.MagicMock(), mock.MagicMock()) self.messaging_client._request_and_transport.return_value = req_trans self.app.client_manager.messaging = self.messaging_client python-zaqarclient-1.11.0/tests/unit/cli/__init__.py0000666000175000017500000000000013364112606022443 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/__init__.py0000666000175000017500000000000013364112606020715 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/0000775000175000017500000000000013364112773020763 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/0000775000175000017500000000000013364112773022272 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/v2/0000775000175000017500000000000013364112773022621 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/v2/test_subscription.py0000666000175000017500000000154113364112606026754 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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 subscriptions from zaqarclient.transport import http class QueuesV2SubscriptionHttpFunctionalTest( subscriptions.QueuesV2SubscriptionFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v2/test_flavor.py0000666000175000017500000000147313364112606025525 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 flavor from zaqarclient.transport import http class QueuesV2FlavorHttpFunctionalTest(flavor.QueuesV2FlavorFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v2/test_pool.py0000666000175000017500000000146313364112606025204 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 pool from zaqarclient.transport import http class QueuesV2PoolHttpFunctionalTest(pool.QueuesV2PoolFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v2/test_queues.py0000666000175000017500000000147113364112606025541 0ustar zuulzuul00000000000000# 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 version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v2/test_claims.py0000666000175000017500000000147513364112606025506 0ustar zuulzuul00000000000000# Copyright (c) 2014 Rackspace Hosting. # # 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 claims from zaqarclient.transport import http class QueuesV2ClaimHttpFunctionalTest(claims.QueuesV2ClaimFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v2/__init__.py0000666000175000017500000000000013364112606024715 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/v2/test_health.py0000666000175000017500000000150713364112606025477 0ustar zuulzuul00000000000000# Copyright (c) 2016 Catalyst IT Ltd. # # 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 health from zaqarclient.transport import http class QueuesV2HealthHttpFunctionalTest( health.QueuesV2HealthFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 2 python-zaqarclient-1.11.0/tests/functional/queues/v1/0000775000175000017500000000000013364112773022620 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/v1/test_flavor.py0000666000175000017500000000151113364112606025515 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 flavor from zaqarclient.transport import http class QueuesV1_1FlavorHttpFunctionalTest( flavor.QueuesV1_1FlavorFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1.1 python-zaqarclient-1.11.0/tests/functional/queues/v1/test_pool.py0000666000175000017500000000147113364112606025202 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 pool from zaqarclient.transport import http class QueuesV1_1PoolHttpFunctionalTest(pool.QueuesV1_1PoolFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1.1 python-zaqarclient-1.11.0/tests/functional/queues/v1/test_queues.py0000666000175000017500000000173513364112606025543 0ustar zuulzuul00000000000000# 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 QueuesV1QueueHttpFunctionalTest(queues.QueuesV1QueueFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1 class QueuesV1_1QueueHttpFunctionalTest(queues.QueuesV1_1QueueFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1.1 python-zaqarclient-1.11.0/tests/functional/queues/v1/test_claims.py0000666000175000017500000000174213364112606025502 0ustar zuulzuul00000000000000# Copyright (c) 2014 Rackspace Hosting. # # 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 claims from zaqarclient.transport import http class QueuesV1ClaimHttpFunctionalTest(claims.QueuesV1ClaimFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1 class QueuesV1_1ClaimHttpFunctionalTest(claims.QueuesV1_1ClaimFunctionalTest): is_functional = True transport_cls = http.HttpTransport version = 1.1 python-zaqarclient-1.11.0/tests/functional/queues/v1/__init__.py0000666000175000017500000000000013364112606024714 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/queues/__init__.py0000666000175000017500000000000013364112606024366 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/tests/functional/__init__.py0000666000175000017500000000000013364112606023057 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/requirements.txt0000666000175000017500000000101513364112606020735 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 six>=1.10.0 # MIT stevedore>=1.20.0 # Apache-2.0 jsonschema<3.0.0,>=2.6.0 # MIT # Oslo Packages oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 keystoneauth1>=3.4.0 # Apache-2.0 osc-lib>=1.8.0 # Apache-2.0 python-zaqarclient-1.11.0/HACKING.rst0000666000175000017500000002050113364112605017247 0ustar zuulzuul00000000000000Zaqar Style Commandments ======================== - Step 1: Read http://www.python.org/dev/peps/pep-0008/ - Step 2: Read http://www.python.org/dev/peps/pep-0008/ again - Step 3: Read on **Table of Contents** .. contents:: :local: :depth: 2 :backlinks: none General ------- - Optimize for readability; whitespace is your friend. - Put two newlines between top-level code (funcs, classes, etc.) - Put one newline between methods in classes and anywhere else. - Use blank lines to group related logic. - Never write ``except:`` (use ``except Exception:`` instead, at the very least). - All classes must inherit from ``object`` (explicitly). - Use single-quotes for strings unless the string contains a single-quote. - Use the double-quote character for blockquotes (``"""``, not ``'''``) - USE_ALL_CAPS_FOR_GLOBAL_CONSTANTS Comments -------- - In general use comments as "memory pegs" for those coming after you up the trail. - Guide the reader though long functions with a comments introducing different sections of the code. - Choose clean, descriptive names for functions and variables to make them self-documenting. - Include your name with TODOs as in ``# TODO(termie): blah blah...``. - Add ``# NOTE(termie): blah blah...`` comments to clarify your intent, or to explain a tricky algorithm, when it isn't obvious from just reading the code. Identifiers ----------- - Do not give anything the same name as a built-in or reserved word. - Don't use single characters in identifiers except in trivial loop variables and mathematical algorithms. - Avoid abbreviations, especially if they are ambiguous or their meaning would not be immediately clear to the casual reader or newcomer. Wrapping -------- Wrap long lines by using Python's implied line continuation inside parentheses, brackets and braces. Make sure to indent the continued line appropriately. The preferred place to break around a binary operator is after the operator, not before it. Example:: class Rectangle(Blob): def __init__(self, width, height, color='black', emphasis=None, highlight=0): # More indentation included to distinguish this from the rest. if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong' or highlight > 100): raise ValueError('sorry, you lose') if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) msg = ('this is a very long string that goes on and on and on and' 'on and on and on...') super(Rectangle, self).__init__(width, height, color, emphasis, highlight) Imports ------- - Only modules may be imported - Do not make relative imports - Order your imports by the full module path - Classes and functions may be hoisted into a package namespace, via __init__ files, with some discretion. - Organize your imports according to the template given below Template:: {{stdlib imports in human alphabetical order}} \n {{third-party lib imports in human alphabetical order}} \n {{zaqar imports in human alphabetical order}} \n \n {{begin your code}} Human Alphabetical Order Examples --------------------------------- Example:: import logging import time import unittest import eventlet import zaqar.common from zaqar import test import zaqar.transport More Import Examples -------------------- **INCORRECT** :: import zaqar.transport.wsgi as wsgi **CORRECT** :: from zaqar.transport import wsgi Docstrings ---------- Docstrings are required for all functions and methods. Docstrings should ONLY use triple-double-quotes (``"""``) Single-line docstrings should NEVER have extraneous whitespace between enclosing triple-double-quotes. **INCORRECT** :: """ There is some whitespace between the enclosing quotes :( """ **CORRECT** :: """There is no whitespace between the enclosing quotes :)""" Docstrings should document default values for named arguments if they're not None Docstrings that span more than one line should look like this: Example:: """Single-line summary, right after the opening triple-double-quote. If you are going to describe parameters and return values, use Sphinx; the appropriate syntax is as follows. :param foo: the foo parameter :param bar: (Default True) the bar parameter :param foo_long_bar: the foo parameter description is very long so we have to split it in multiple lines in order to keey things ordered :returns: return_type -- description of the return value :returns: description of the return value :raises: AttributeError, KeyError """ **DO NOT** leave an extra newline before the closing triple-double-quote. Dictionaries/Lists ------------------ If a dictionary (dict) or list object is longer than 80 characters, its items should be split with newlines. Embedded iterables should have their items indented. Additionally, the last item in the dictionary should have a trailing comma. This increases readability and simplifies future diffs. Example:: my_dictionary = { "image": { "name": "Just a Snapshot", "size": 2749573, "properties": { "user_id": 12, "arch": "x86_64", }, "things": [ "thing_one", "thing_two", ], "status": "ACTIVE", }, } Calling Methods --------------- Calls to methods 80 characters or longer should format each argument with newlines. This is not a requirement, but a guideline:: unnecessarily_long_function_name('string one', 'string two', kwarg1=constants.ACTIVE, kwarg2=['a', 'b', 'c']) Rather than constructing parameters inline, it is better to break things up:: list_of_strings = [ 'what_a_long_string', 'not as long', ] dict_of_numbers = { 'one': 1, 'two': 2, 'twenty four': 24, } object_one.call_a_method('string three', 'string four', kwarg1=list_of_strings, kwarg2=dict_of_numbers) Internationalization (i18n) Strings ----------------------------------- In order to support multiple languages, we have a mechanism to support automatic translations of exception and log strings. Example:: msg = _("An error occurred") If you have a variable to place within the string, first internationalize the template string then do the replacement. Example:: msg = _("Missing parameter: %s") % ("flavor",) LOG.error(msg) If you have multiple variables to place in the string, use keyword parameters. This helps our translators reorder parameters when needed. Example:: msg = _("The server with id %(s_id)s has no key %(m_key)s") LOG.error(msg % {"s_id": "1234", "m_key": "imageId"}) An important exception to this rule is with regards to exceptions: exceptions should NOT be marked as translatable. See `No Exceptions i18n`_ for more details. .. _No Exceptions i18n: https://trello.com/card/exceptions-should-not-be-marked-as-translatable/511403287d138cd6200078e0/243 Creating Unit Tests ------------------- For every any change, unit tests should be created that both test and (implicitly) document the usage of said feature. If submitting a patch for a bug that had no unit test, a new passing unit test should be added. If a submitted bug fix does have a unit test, be sure to add a new one that fails without the patch and passes with the patch. NOTE: 100% coverage is required openstack-common ---------------- A number of modules from openstack-common are imported into the project. These modules are "incubating" in openstack-common and are kept in sync with the help of openstack-common's update.py script. See: https://wiki.openstack.org/wiki/CommonLibrary#Incubation The copy of the code should never be directly modified here. Please always update openstack-common first and then run the script to copy the changes across. Logging ------- Use __name__ as the name of your logger and name your module-level logger objects 'LOG':: LOG = logging.getLogger(__name__) python-zaqarclient-1.11.0/zaqarclient/0000775000175000017500000000000013364112773017774 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/0000775000175000017500000000000013364112773021303 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/v2/0000775000175000017500000000000013364112773021632 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/v2/api.py0000666000175000017500000000540413364112606022755 0ustar zuulzuul00000000000000# Copyright (c) 2015 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.queues.v1 import api class V2(api.V1_1): label = 'v2' schema = api.V1_1.schema.copy() V2.schema.update({ 'queue_purge': { 'ref': 'queues/{queue_name}/purge', 'method': 'POST', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'signed_url_create': { 'ref': 'queues/{queue_name}/share', 'method': 'POST', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} }, }, 'subscription_create': { 'ref': 'queues/{queue_name}/subscriptions', 'method': 'POST', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} }, }, 'subscription_get': { 'ref': 'queues/{queue_name}/subscriptions/{subscription_id}', 'method': 'GET', 'required': ['queue_name', 'subscription_id'], 'properties': { 'queue_name': {'type': 'string'}, 'subscription_id': {'type': 'string'} }, }, 'subscription_update': { 'ref': 'queues/{queue_name}/subscriptions/{subscription_id}', 'method': 'PATCH', 'required': ['queue_name', 'subscription_id'], 'properties': { 'queue_name': {'type': 'string'}, 'subscription_id': {'type': 'string'} } }, 'subscription_delete': { 'ref': 'queues/{queue_name}/subscriptions/{subscription_id}', 'method': 'DELETE', 'required': ['queue_name', 'subscription_id'], 'properties': { 'queue_name': {'type': 'string'}, 'subscription_id': {'type': 'string'} } }, 'subscription_list': { 'ref': 'queues/{queue_name}/subscriptions', 'method': 'GET', 'properties': { 'marker': {'type': 'string'}, 'limit': {'type': 'integer'}, 'detailed': {'type': 'boolean'} } }, 'ping': { 'ref': 'ping', 'method': 'GET', }, 'health': { 'ref': 'health', 'method': 'GET', }, 'homedoc': { 'ref': '', 'method': 'GET', }, }) python-zaqarclient-1.11.0/zaqarclient/queues/v2/pool.py0000666000175000017500000000122313364112606023150 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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.queues.v1 import pool class Pool(pool.Pool): pass python-zaqarclient-1.11.0/zaqarclient/queues/v2/message.py0000666000175000017500000000400713364112606023626 0ustar zuulzuul00000000000000# 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.queues.v1 import message from zaqarclient.queues.v2 import core class Message(message.Message): def __init__(self, queue, ttl, age, body, href=None, id=None, claim_id=None, claim_count=0, checksum=None): self.queue = queue self.href = href self.ttl = ttl self.age = age self.body = body self.claim_count = claim_count self.checksum = checksum # NOTE(flaper87): Is this really # necessary? Should this be returned # by Zaqar? # The url has two forms depending on if it has been claimed. # /v1/queues/worker-jobs/messages/5c6939a8?claim_id=63c9a592 # or # /v1/queues/worker-jobs/messages/5c6939a8 if id is None: self.id = href.split('/')[-1] if '?' in self.id: self.id = self.id.split('?')[0] else: self.id = id def __repr__(self): return ''.format(id=self.id, ttl=self.ttl) @property def claim_id(self): if '=' in self.href: return self.href.split('=')[-1] def delete(self): req, trans = self.queue.client._request_and_transport() core.message_delete(trans, req, self.queue._name, self.id, self.claim_id) def create_object(parent): return lambda args: Message(parent, **args) python-zaqarclient-1.11.0/zaqarclient/queues/v2/queues.py0000666000175000017500000000761613364112606023522 0ustar zuulzuul00000000000000# 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.queues.v1 import queues from zaqarclient.queues.v2 import claim as claim_api from zaqarclient.queues.v2 import core from zaqarclient.queues.v2 import message class Queue(queues.Queue): message_module = message def signed_url(self, paths=None, ttl_seconds=None, methods=None): req, trans = self.client._request_and_transport() return core.signed_url_create(trans, req, self._name, paths=paths, ttl_seconds=ttl_seconds, methods=methods) def subscriptions(self, detailed=False, marker=None, limit=20): return self.client.subscriptions(queue_name=self._name, detailed=detailed, marker=marker, limit=limit) def metadata(self, new_meta=None, force_reload=False): """Get metadata and return it :param new_meta: A dictionary containing an updated metadata object. If present the queue metadata will be updated in remote server. If the new_meta is empty, the metadata object will be cleared. :type new_meta: `dict` :param force_reload: Whether to ignored the cached metadata and reload it from the server. :type force_reload: `bool` :returns: The queue metadata. """ req, trans = self.client._request_and_transport() # TODO(flaper87): Cache with timeout if new_meta is None and self._metadata and not force_reload: return self._metadata else: self._metadata = core.queue_get(trans, req, self._name) if new_meta is not None: temp_metadata = self._metadata.copy() changes = [] for key, value in new_meta.items(): # If key exists, replace it's value. if self._metadata.get(key, None) is not None: changes.append({'op': 'replace', 'path': '/metadata/%s' % key, 'value': value}) temp_metadata.pop(key) # If not, add the new key. else: changes.append({'op': 'add', 'path': '/metadata/%s' % key, 'value': value}) # For the keys which are not included in the new metadata, remove # them. for key, value in temp_metadata.items(): changes.append({'op': 'remove', 'path': '/metadata/%s' % key}) self._metadata = core.queue_update(trans, req, self._name, metadata=changes) return self._metadata def purge(self, resource_types=None): req, trans = self.client._request_and_transport() core.queue_purge(trans, req, self._name, resource_types=resource_types) def claim(self, id=None, ttl=None, grace=None, limit=None): return claim_api.Claim(self, id=id, ttl=ttl, grace=grace, limit=limit) def create_object(parent): return lambda args: Queue(parent, args["name"], href=args.get("href"), metadata=args.get("metadata"), auto_create=False) python-zaqarclient-1.11.0/zaqarclient/queues/v2/cli.py0000666000175000017500000006566513364112606022772 0ustar zuulzuul00000000000000# Copyright 2015 NEC Corporation. All rights reserved. # # 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 os from osc_lib.command import command from osc_lib import utils from oslo_log import log as logging from zaqarclient._i18n import _ from zaqarclient.queues.v1 import cli def _get_client(obj, parsed_args): obj.log.debug("take_action(%s)" % parsed_args) return obj.app.client_manager.messaging class CreateQueue(cli.CreateQueue): """Create a queue""" pass class OldCreateQueue(cli.OldCreateQueue): """Create a queue""" pass class DeleteQueue(cli.DeleteQueue): """Delete a queue""" pass class OldDeleteQueue(cli.OldDeleteQueue): """Delete a queue""" pass class ListQueues(cli.ListQueues): """List available queues""" pass class OldListQueues(cli.OldListQueues): """List available queues""" pass class GetQueueStats(cli.GetQueueStats): """Get queue stats""" pass class OldGetQueueStats(cli.OldGetQueueStats): """Get queue stats""" pass class SetQueueMetadata(command.Command): """Set queue metadata""" _description = _("Set queue metadata") log = logging.getLogger(__name__ + ".SetQueueMetadata") def get_parser(self, prog_name): parser = super(SetQueueMetadata, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "queue_metadata", metavar="", help="Queue metadata, All the metadata of " "the queue will be replaced by queue_metadata") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue_metadata = parsed_args.queue_metadata if (client.api_version == 1 and not client.queue(queue_name, auto_create=False).exists()): raise RuntimeError("Queue(%s) does not exist." % queue_name) try: valid_metadata = json.loads(queue_metadata) except ValueError: raise RuntimeError("Queue metadata(%s) is not a valid json." % queue_metadata) client.queue(queue_name, auto_create=False).\ metadata(new_meta=valid_metadata) class OldSetQueueMetadata(cli.OldSetQueueMetadata): """Set queue metadata""" pass class GetQueueMetadata(cli.GetQueueMetadata): """Get queue metadata""" pass class OldGetQueueMetadata(cli.OldGetQueueMetadata): """Get queue metadata""" pass class PostMessages(command.Command): """Post messages for a given queue""" _description = _("Post messages for a given queue") log = logging.getLogger(__name__ + ".PostMessages") def get_parser(self, prog_name): parser = super(PostMessages, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "messages", type=json.loads, metavar="", help="Messages to be posted.") parser.add_argument( "--client-id", metavar="", default=os.environ.get("OS_MESSAGE_CLIENT_ID"), help="A UUID for each client instance.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) if not parsed_args.client_id: raise AttributeError("<--client-id> option is missing and " "environment variable OS_MESSAGE_CLIENT_ID " "is not set. Please at least either pass in " "the client id or set the environment " "variable") else: client.client_uuid = parsed_args.client_id queue = client.queue(parsed_args.queue_name) queue.post(parsed_args.messages) class OldPostMessages(PostMessages): """Post messages for a given queue""" _description = _("Post messages for a given queue") # TODO(wanghao): Remove this class and ``message post`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging message post" ' 'instead.')) return super(OldPostMessages, self).take_action(parsed_args) class ListMessages(command.Lister): """List all messages for a given queue""" _description = _("List all messages for a given queue") log = logging.getLogger(__name__ + ".ListMessages") def get_parser(self, prog_name): parser = super(ListMessages, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--message-ids", metavar="", help="List of messages' ids to retrieve") parser.add_argument( "--limit", metavar="", type=int, help="Maximum number of messages to get") parser.add_argument( "--echo", action="store_true", help="Whether to get this client's own messages") parser.add_argument( "--include-claimed", action="store_true", help="Whether to include claimed messages") parser.add_argument( "--include-delayed", action="store_true", help="Whether to include delayed messages") parser.add_argument( "--client-id", metavar="", default=os.environ.get("OS_MESSAGE_CLIENT_ID"), help="A UUID for each client instance.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) if not parsed_args.client_id: raise AttributeError("<--client-id> option is missing and " "environment variable OS_MESSAGE_CLIENT_ID " "is not set. Please at least either pass in " "the client id or set the environment " "variable") else: client.client_uuid = parsed_args.client_id kwargs = {} if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit if parsed_args.echo is not None: kwargs["echo"] = parsed_args.echo if parsed_args.include_claimed is not None: kwargs["include_claimed"] = parsed_args.include_claimed if parsed_args.include_delayed is not None: kwargs["include_delayed"] = parsed_args.include_delayed queue = client.queue(parsed_args.queue_name) if parsed_args.message_ids: messages = queue.messages(parsed_args.message_ids.split(','), **kwargs) else: messages = queue.messages(**kwargs) columns = ("ID", "Body", "TTL", "Age", "Claim ID", "Checksum") return (columns, (utils.get_item_properties(s, columns) for s in messages)) class OldListMessages(ListMessages): """List all messages for a given queue""" _description = _("List all messages for a given queue") # TODO(wanghao): Remove this class and ``message list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging message list" ' 'instead.')) return super(OldListMessages, self).take_action(parsed_args) class PurgeQueue(command.Command): """Purge a queue""" _description = _("Purge a queue") log = logging.getLogger(__name__ + ".PurgeQueue") def get_parser(self, prog_name): parser = super(PurgeQueue, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--resource_types", metavar="", action='append', choices=['messages', 'subscriptions'], help="Resource types want to be purged.") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name client.queue(queue_name).purge( resource_types=parsed_args.resource_types) class OldPurgeQueue(PurgeQueue): """Purge a queue""" _description = _("Purge a queue") # TODO(wanghao): Remove this class and ``queue purge`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue purge" ' 'instead.')) return super(OldPurgeQueue, self).take_action(parsed_args) class CreatePool(cli.CreatePool): """Create a pool""" pass class OldCreatePool(cli.OldCreatePool): """Create a pool""" pass class ShowPool(cli.ShowPool): """Display pool details""" pass class OldShowPool(cli.OldShowPool): """Display pool details""" pass class UpdatePool(cli.UpdatePool): """Update a pool attribute""" pass class OldUpdatePool(cli.OldUpdatePool): """Update a pool attribute""" pass class DeletePool(cli.DeletePool): """Delete a pool""" pass class OldDeletePool(cli.OldDeletePool): """Delete a pool""" pass class ListPools(cli.ListPools): """List available Pools""" pass class OldListPools(cli.OldListPools): """List available Pools""" pass class DeleteFlavor(cli.DeleteFlavor): """Delete a flavor""" pass class ShowFlavor(cli.ShowFlavor): """Display flavor details""" pass class UpdateFlavor(cli.UpdateFlavor): """Update a flavor's attributes""" pass class CreateFlavor(cli.CreateFlavor): """Create a pool flavor""" def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {} if parsed_args.capabilities != {}: raise AttributeError("<--capabilities> option is only\ available in client api version < 2") data = client.flavor(parsed_args.flavor_name, pool_group=parsed_args.pool_group, **kwargs) columns = ('Name', 'Pool Group', 'Capabilities') return columns, utils.get_item_properties(data, columns) class ListFlavors(cli.ListFlavors): """List available flavors""" pass class CreateSubscription(command.ShowOne): """Create a subscription for queue""" _description = _("Create a subscription for queue") log = logging.getLogger(__name__ + ".CreateSubscription") def get_parser(self, prog_name): parser = super(CreateSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "subscriber", metavar="", help="Subscriber which will be notified") parser.add_argument( "ttl", metavar="", type=int, help="Time to live of the subscription in seconds") parser.add_argument( "--options", type=json.loads, default={}, metavar="", help="Metadata of the subscription in JSON format") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {'options': parsed_args.options} if parsed_args.subscriber: kwargs['subscriber'] = parsed_args.subscriber if parsed_args.subscriber: kwargs['ttl'] = parsed_args.ttl data = client.subscription(parsed_args.queue_name, **kwargs) if not data: raise RuntimeError('Failed to create subscription for (%s).' % parsed_args.subscriber) columns = ('ID', 'Subscriber', 'TTL', 'Options') return columns, utils.get_item_properties(data, columns) class OldCreateSubscription(CreateSubscription): """Create a subscription for queue""" _description = _("Create a subscription for queue") # TODO(wanghao): Remove this class and ``subscription create`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription create" ' 'instead.')) return super(OldCreateSubscription, self).take_action(parsed_args) class UpdateSubscription(command.ShowOne): """Update a subscription""" _description = _("Update a subscription") log = logging.getLogger(__name__ + ".UpdateSubscription") def get_parser(self, prog_name): parser = super(UpdateSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) parser.add_argument( "--subscriber", metavar="", help="Subscriber which will be notified") parser.add_argument( "--ttl", metavar="", type=int, help="Time to live of the subscription in seconds") parser.add_argument( "--options", type=json.loads, default={}, metavar="", help="Metadata of the subscription in JSON format") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) data = {'subscriber': parsed_args.subscriber, 'ttl': parsed_args.ttl, 'options': parsed_args.options} kwargs = {'id': parsed_args.subscription_id} subscription = client.subscription(parsed_args.queue_name, kwargs, auto_create=False) subscription.update(data) columns = ('ID', 'Subscriber', 'TTL', 'Options') return columns, utils.get_item_properties(data, columns) class OldUpdateSubscription(UpdateSubscription): """Update a subscription""" _description = _("Update a subscription") # TODO(wanghao): Remove this class and ``subscription update`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription update" ' 'instead.')) return super(OldUpdateSubscription, self).take_action(parsed_args) class DeleteSubscription(command.Command): """Delete a subscription""" _description = _("Delete a subscription") log = logging.getLogger(__name__ + ".DeleteSubscription") def get_parser(self, prog_name): parser = super(DeleteSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue for the subscription") parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) client.subscription(parsed_args.queue_name, id=parsed_args.subscription_id, auto_create=False).delete() class OldDeleteSubscription(DeleteSubscription): """Delete a subscription""" _description = _("Delete a subscription") # TODO(wanghao): Remove this class and ``subscription delete`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription delete" ' 'instead.')) return super(OldDeleteSubscription, self).take_action(parsed_args) class ShowSubscription(command.ShowOne): """Display subscription details""" _description = _("Display subscription details") log = logging.getLogger(__name__ + ".ShowSubscription") def get_parser(self, prog_name): parser = super(ShowSubscription, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to" ) parser.add_argument( "subscription_id", metavar="", help="ID of the subscription" ) return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {'id': parsed_args.subscription_id} pool_data = client.subscription(parsed_args.queue_name, **kwargs) columns = ('ID', 'Subscriber', 'TTL', 'Age', 'Confirmed', 'Options') return columns, utils.get_dict_properties(pool_data.__dict__, columns) class OldShowSubscription(ShowSubscription): """Display subscription details""" _description = _("Display subscription details") # TODO(wanghao): Remove this class and ``subscription show`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription show" ' 'instead.')) return super(OldShowSubscription, self).take_action(parsed_args) class ListSubscriptions(command.Lister): """List available subscriptions""" _description = _("List available subscriptions") log = logging.getLogger(__name__ + ".ListSubscriptions") def get_parser(self, prog_name): parser = super(ListSubscriptions, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to subscribe to") parser.add_argument( "--marker", metavar="", help="Subscription's paging marker, " "the ID of the last subscription of the previous page") parser.add_argument( "--limit", metavar="", help="Page size limit, default value is 20") return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {'queue_name': parsed_args.queue_name} if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit data = client.subscriptions(**kwargs) columns = ('ID', 'Subscriber', 'TTL', 'Age', 'Confirmed', 'Options') return (columns, (utils.get_item_properties(s, columns) for s in data)) class OldListSubscriptions(ListSubscriptions): """List available subscriptions""" _description = _("List available subscriptions") # TODO(wanghao): Remove this class and ``subscription list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging subscription list" ' 'instead.')) return super(OldListSubscriptions, self).take_action(parsed_args) class CreateClaim(cli.CreateClaim): """Create claim and return a list of claimed messages""" def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} if parsed_args.ttl is not None: kwargs["ttl"] = parsed_args.ttl if parsed_args.grace is not None: kwargs["grace"] = parsed_args.grace if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit queue = client.queue(parsed_args.queue_name, auto_create=False) keys = ("claim_id", "id", "ttl", "age", 'body', "checksum") columns = ("Claim_ID", "Message_ID", "TTL", "Age", "Messages", "Checksum") data = queue.claim(**kwargs) return (columns, (utils.get_item_properties(s, keys) for s in data)) class OldCreateClaim(cli.OldCreateClaim): """Create claim and return a list of claimed messages""" pass class QueryClaim(cli.QueryClaim): """Display claim details""" pass class OldQueryClaim(cli.OldQueryClaim): """Display claim details""" pass class RenewClaim(cli.RenewClaim): """Renew a claim""" pass class OldRenewClaim(cli.OldRenewClaim): """Renew a claim""" pass class ReleaseClaim(cli.ReleaseClaim): """Delete a claim""" pass class OldReleaseClaim(cli.OldReleaseClaim): """Delete a claim""" pass class CreateSignedUrl(command.ShowOne): """Create a pre-signed url""" _description = _("Create a pre-signed url") log = logging.getLogger(__name__ + ".CreateSignedUrl") def get_parser(self, prog_name): parser = super(CreateSignedUrl, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "--paths", metavar="", default="messages", help="Allowed paths in a comma-separated list. " "Options: messages, subscriptions, claims") parser.add_argument( "--ttl-seconds", metavar="", type=int, help="Length of time (in seconds) until the signature expires") parser.add_argument( "--methods", metavar="", default="GET", help="HTTP methods to allow as a comma-separated list. " "Options: GET, HEAD, OPTIONS, POST, PUT, DELETE") return parser allowed_paths = ("messages", "subscriptions", "claims") def take_action(self, parsed_args): client = self.app.client_manager.messaging queue = client.queue(parsed_args.queue_name, auto_create=False) paths = parsed_args.paths.split(',') if not all([p in self.allowed_paths for p in paths]): print("Invalid path supplied! Received {}. " "Valid paths are: messages, subscriptions, " "claims".format(','.join(paths))) kwargs = { 'methods': parsed_args.methods.split(','), 'paths': paths, } if parsed_args.ttl_seconds: kwargs['ttl_seconds'] = parsed_args.ttl_seconds data = queue.signed_url(**kwargs) fields = ('Paths', 'Methods', 'Expires', 'Signature', 'Project ID') return fields, ( ','.join(data['paths']), ','.join(data['methods']), data['expires'], data['signature'], data['project'] ) class OldCreateSignedUrl(CreateSignedUrl): """Create a pre-signed url""" _description = _("Create a pre-signed url") # TODO(wanghao): Remove this class and ``queue signed url`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue signed url" ' 'instead.')) return super(OldCreateSignedUrl, self).take_action(parsed_args) class Ping(command.ShowOne): """Check if Zaqar server is alive or not""" _description = _("Check if Zaqar server is alive or not") log = logging.getLogger(__name__ + ".Ping") def take_action(self, parsed_args): client = _get_client(self, parsed_args) columns = ('Pingable', ) return columns, utils.get_dict_properties({'pingable': client.ping()}, columns) class Health(command.Command): """Display detailed health status of Zaqar server""" _description = _("Display detailed health status of Zaqar server") log = logging.getLogger(__name__ + ".Health") def take_action(self, parsed_args): client = _get_client(self, parsed_args) health = client.health() print(json.dumps(health, indent=4, sort_keys=True)) class HomeDoc(command.Command): """Display the resource doc of Zaqar server""" _description = _("Display detailed resource doc of Zaqar server") log = logging.getLogger(__name__ + ".HomeDoc") def take_action(self, parsed_args): client = _get_client(self, parsed_args) homedoc = client.homedoc() print(json.dumps(homedoc, indent=4, sort_keys=True)) python-zaqarclient-1.11.0/zaqarclient/queues/v2/flavor.py0000666000175000017500000000123313364112606023471 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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.queues.v1 import flavor class Flavor(flavor.Flavor): pass python-zaqarclient-1.11.0/zaqarclient/queues/v2/__init__.py0000666000175000017500000000000013364112606023726 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/v2/core.py0000666000175000017500000002513113364112606023133 0ustar zuulzuul00000000000000# 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. """ import datetime import json from oslo_utils import timeutils 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_get = core.message_get message_list = core.message_list message_post = core.message_post message_delete = core.message_delete message_delete_many = core.message_delete_many pool_get = core.pool_get pool_create = core.pool_create pool_delete = core.pool_delete pool_update = core.pool_update pool_list = core.pool_list flavor_get = core.flavor_get flavor_create = core.flavor_create flavor_delete = core.flavor_delete flavor_update = core.flavor_update flavor_list = core.flavor_list claim_create = core.claim_create claim_get = core.claim_get claim_update = core.claim_update claim_delete = core.claim_delete def queue_update(transport, request, name, metadata, callback=None): """Updates a queue's metadata using PATCH for API v2 :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 name: Queue reference name. :type name: `six.text_type` :param metadata: Queue's metadata object. :type metadata: `list` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'queue_update' request.params['queue_name'] = name request.content = json.dumps(metadata) resp = transport.send(request) return resp.deserialized_content def queue_purge(transport, request, name, resource_types=None): """Purge resources under a queue :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 name: Queue reference name. :type name: `six.text_type` :param resource_types: Resource types will be purged :type resource_types: `list` """ request.operation = 'queue_purge' request.params['queue_name'] = name if resource_types: request.content = json.dumps({'resource_types': resource_types}) resp = transport.send(request) return resp.deserialized_content def signed_url_create(transport, request, queue_name, paths=None, ttl_seconds=None, project_id=None, methods=None): """Creates a signed URL given a queue 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 queue_name: name of Queue for the URL to access :type name: `six.text_type` :param paths: Allowed actions. Options: messages, subscriptions, claims :type name: list :param ttl_seconds: Seconds the URL will be valid for, default 86400 :type name: int :param project_id: defaults to None :type name: `six.text_type` :param methods: HTTP methods to allow, defaults to ["GET"] :type name: `list` """ request.operation = 'signed_url_create' request.params['queue_name'] = queue_name body = {} if ttl_seconds is not None: expiry = (timeutils.utcnow() + datetime.timedelta(seconds=ttl_seconds)) body['expires'] = expiry.isoformat() if project_id is not None: body['project_id'] = project_id if paths is not None: body['paths'] = paths if methods is not None: body['methods'] = methods request.content = json.dumps(body) resp = transport.send(request) return resp.deserialized_content def subscription_create(transport, request, queue_name, subscription_data): """Creates a new subscription against the `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param subscription_data: Subscription's properties, i.e: subscriber, ttl, options. :type subscription_data: `dict` """ request.operation = 'subscription_create' request.params['queue_name'] = queue_name request.content = json.dumps(subscription_data) resp = transport.send(request) return resp.deserialized_content def subscription_get(transport, request, queue_name, subscription_id): """Gets a particular subscription data :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param subscription_id: ID of subscription. :type subscription_id: `six.text_type` """ request.operation = 'subscription_get' request.params['queue_name'] = queue_name request.params['subscription_id'] = subscription_id resp = transport.send(request) return resp.deserialized_content def subscription_update(transport, request, queue_name, subscription_id, subscription_data): """Updates the subscription :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param subscription_id: ID of subscription. :type subscription_id: `six.text_type` :param subscription_data: Subscription's properties, i.e: subscriber, ttl, options. :type subscription_data: `dict` """ request.operation = 'subscription_update' request.params['queue_name'] = queue_name request.params['subscription_id'] = subscription_id request.content = json.dumps(subscription_data) resp = transport.send(request) return resp.deserialized_content def subscription_delete(transport, request, queue_name, subscription_id): """Deletes the subscription :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param subscription_id: ID of subscription. :type subscription_id: `six.text_type` """ request.operation = 'subscription_delete' request.params['queue_name'] = queue_name request.params['subscription_id'] = subscription_id transport.send(request) def subscription_list(transport, request, queue_name, **kwargs): """Gets a list of subscriptions :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param kwargs: Optional arguments for this operation. - marker: Where to start getting subscriptions from. - limit: Maximum number of subscriptions to get. """ request.operation = 'subscription_list' request.params['queue_name'] = queue_name request.params.update(kwargs) resp = transport.send(request) if not resp.content: return {'links': [], 'subscriptions': []} return resp.deserialized_content def ping(transport, request, callback=None): """Check the health of web head for load balancing :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 callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'ping' try: transport.send(request) return True except Exception: return False def health(transport, request, callback=None): """Get detailed health status of Zaqar server :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 callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'health' resp = transport.send(request) return resp.deserialized_content def homedoc(transport, request, callback=None): """Get the detailed resource doc of Zaqar server :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 callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'homedoc' resp = transport.send(request) return resp.deserialized_content python-zaqarclient-1.11.0/zaqarclient/queues/v2/client.py0000666000175000017500000000675313364112606023472 0ustar zuulzuul00000000000000# 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 oslo_utils import uuidutils from zaqarclient.common import decorators from zaqarclient.queues.v1 import client from zaqarclient.queues.v1 import iterator from zaqarclient.queues.v2 import core from zaqarclient.queues.v2 import queues from zaqarclient.queues.v2 import subscription 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 conf: CONF object. :type conf: `oslo_config.cfg.CONF` """ queues_module = queues def __init__(self, url=None, version=2, conf=None, session=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', uuidutils.generate_uuid(dashed=False)) self.session = session def queue(self, ref, **kwargs): """Returns a queue instance :param ref: Queue's reference id. :type ref: `six.text_type` :returns: A queue instance :rtype: `queues.Queue` """ return queues.Queue(self, ref, **kwargs) @decorators.version(min_version=2) def subscription(self, queue_name, **kwargs): """Returns a subscription instance :param queue_name: Name of the queue to subscribe to. :type queue_name: `six.text_type` :returns: A subscription instance :rtype: `subscription.Subscription` """ return subscription.Subscription(self, queue_name, **kwargs) @decorators.version(min_version=2) def subscriptions(self, queue_name, **params): """Gets a list of subscriptions from the server :param params: Filters to use for getting subscriptions :type params: dict. :returns: A list of subscriptions :rtype: `list` """ req, trans = self._request_and_transport() subscription_list = core.subscription_list(trans, req, queue_name, **params) return iterator._Iterator(self, subscription_list, 'subscriptions', subscription.create_object(self)) def ping(self): """Gets the health status of Zaqar server.""" req, trans = self._request_and_transport() return core.ping(trans, req) @decorators.version(min_version=1.1) def health(self): """Gets the detailed health status of Zaqar server.""" req, trans = self._request_and_transport() return core.health(trans, req) @decorators.version(min_version=1.1) def homedoc(self): """Get the detailed resource doc of Zaqar server""" req, trans = self._request_and_transport() return core.homedoc(trans, req) python-zaqarclient-1.11.0/zaqarclient/queues/v2/subscription.py0000666000175000017500000000632213364112606024730 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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.queues.v2 import core class Subscription(object): def __init__(self, client, queue_name, subscriber=None, ttl=60, id=None, auto_create=True, **kwargs): self.client = client self.id = id self.queue_name = queue_name self.subscriber = subscriber self.ttl = ttl self.options = kwargs.get('options', {}) self.age = kwargs.get('age') self.confirmed = kwargs.get('confirmed') if auto_create: self.ensure_exists() def ensure_exists(self): """Ensures subscription exists This method is not race safe, the subscription could've been deleted right after it was called. """ req, trans = self.client._request_and_transport() if not self.id and self.subscriber: subscription_data = {'subscriber': self.subscriber, 'ttl': self.ttl, 'options': self.options } subscription = core.subscription_create(trans, req, self.queue_name, subscription_data) if subscription and 'subscription_id' in subscription: self.id = subscription['subscription_id'] if self.id: sub = core.subscription_get(trans, req, self.queue_name, self.id) self.subscriber = sub.get('subscriber') self.ttl = sub.get('ttl') self.options = sub.get('options') self.age = sub.get('age') self.confirmed = sub.get('confirmed') def update(self, subscription_data): req, trans = self.client._request_and_transport() core.subscription_update(trans, req, self.queue_name, self.id, subscription_data) for key, value in subscription_data.items(): setattr(self, key, value) def delete(self): req, trans = self.client._request_and_transport() core.subscription_delete(trans, req, self.queue_name, self.id) def create_object(parent): return lambda kwargs: Subscription(parent, kwargs.pop('source'), subscriber=kwargs.pop('subscriber'), ttl=kwargs.pop('ttl'), id=kwargs.pop('id'), age=kwargs.pop('age'), confirmed=kwargs.pop('confirmed'), auto_create=False, **kwargs) python-zaqarclient-1.11.0/zaqarclient/queues/v2/claim.py0000666000175000017500000000327013364112606023270 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from zaqarclient.queues.v1 import claim from zaqarclient.queues.v1 import iterator as iterate from zaqarclient.queues.v2 import core from zaqarclient.queues.v2 import message class Claim(claim.Claim): def _create(self): req, trans = self._queue.client._request_and_transport() msgs = core.claim_create(trans, req, self._queue._name, ttl=self._ttl, grace=self._grace, limit=self._limit) # extract the id from the first message if msgs is not None: if self._queue.client.api_version >= 1.1: msgs = msgs['messages'] self.id = msgs[0]['href'].split('=')[-1] self._message_iter = iterate._Iterator(self._queue.client, msgs or [], 'messages', message.create_object( self._queue )) python-zaqarclient-1.11.0/zaqarclient/queues/cli.py0000666000175000017500000000507513364112606022430 0ustar zuulzuul00000000000000# Copyright 2014 OpenStack Foundation # # 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. """OpenStackClient plugin for Messaging service.""" from osc_lib import utils from oslo_log import log as logging LOG = logging.getLogger(__name__) DEFAULT_QUEUES_API_VERSION = '2' API_VERSION_OPTION = 'os_queues_api_version' API_NAME = "messaging" API_VERSIONS = { "1": "zaqarclient.queues.v1.client.Client", "1.1": "zaqarclient.queues.v1.client.Client", "2": "zaqarclient.queues.v2.client.Client", } _MESSAGING_ENDPOINT = None def make_client(instance): """Returns an queues service client.""" global _MESSAGING_ENDPOINT version = instance._api_version[API_NAME] try: version = int(version) except ValueError: version = float(version) queues_client = utils.get_client_class( API_NAME, version, API_VERSIONS) # TODO(wangxiyuan): Use public attributes instead of private attributes. if not _MESSAGING_ENDPOINT: _MESSAGING_ENDPOINT = instance.get_endpoint_for_service_type( API_NAME, region_name=instance._region_name, interface=instance._interface ) auth_params = instance.get_configuration()['auth'] auth_params.update({ "auth_token": instance.auth.get_token(instance.session), "insecure": instance._insecure, "cacert": instance._cacert, "region_name": instance._region_name }) conf = { "auth_opts": {'options': auth_params} } LOG.debug('Instantiating queues service client: %s', queues_client) return queues_client( _MESSAGING_ENDPOINT, version, conf ) def build_option_parser(parser): """Hook to add global options.""" parser.add_argument( '--os-queues-api-version', metavar='', default=utils.env( 'OS_QUEUES_API_VERSION', default=DEFAULT_QUEUES_API_VERSION), help=('Queues API version, default=' + DEFAULT_QUEUES_API_VERSION + ' (Env: OS_QUEUES_API_VERSION)')) return parser python-zaqarclient-1.11.0/zaqarclient/queues/v1/0000775000175000017500000000000013364112773021631 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/v1/api.py0000666000175000017500000002246713364112606022764 0ustar zuulzuul00000000000000# 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.transport import api class V1(api.Api): label = 'v1' schema = { 'queue_list': { 'ref': 'queues', 'method': 'GET', 'properties': { 'marker': {'type': 'string'}, 'limit': {'type': 'integer'}, 'detailed': {'type': 'boolean'} } }, 'queue_create': { 'ref': 'queues/{queue_name}', 'method': 'PUT', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} }, }, 'queue_exists': { 'ref': 'queues/{queue_name}', 'method': 'HEAD', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'queue_delete': { 'ref': 'queues/{queue_name}', 'method': 'DELETE', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'queue_set_metadata': { 'ref': 'queues/{queue_name}/metadata', 'method': 'PUT', 'required': ['queue_name'], 'properties': { # NOTE(flaper87): Metadata is part # of the request content. No need to # add it here. 'queue_name': {'type': 'string'}, } }, 'queue_get_metadata': { 'ref': 'queues/{queue_name}/metadata', 'method': 'GET', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'queue_get_stats': { 'ref': 'queues/{queue_name}/stats', 'method': 'GET', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'message_list': { 'ref': 'queues/{queue_name}/messages', 'method': 'GET', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'}, 'marker': {'type': 'string'}, 'limit': {'type': 'integer'}, 'echo': {'type': 'boolean'}, 'include_claimed': {'type': 'boolean'}, } }, 'message_post': { 'ref': 'queues/{queue_name}/messages', 'method': 'POST', 'required': ['queue_name', 'message_id'], 'properties': { 'queue_name': {'type': 'string'}, 'claim_id': {'type': 'string'}, } }, 'message_get': { 'ref': 'queues/{queue_name}/messages/{message_id}', 'method': 'GET', 'required': ['queue_name', 'message_id'], 'properties': { 'queue_name': {'type': 'string'}, 'message_id': {'type': 'string'}, 'claim_id': {'type': 'string'}, } }, 'message_get_many': { 'ref': 'queues/{queue_name}/messages', 'method': 'GET', 'required': ['queue_name', 'ids'], 'properties': { 'queue_name': {'type': 'string'}, 'ids': {'type': 'string'}, 'claim_id': {'type': 'string'}, } }, 'message_delete': { 'ref': 'queues/{queue_name}/messages/{message_id}', 'method': 'DELETE', 'required': ['queue_name', 'message_id'], 'properties': { 'queue_name': {'type': 'string'}, 'message_id': {'type': 'string'}, 'claim_id': {'type': 'string'}, } }, 'message_delete_many': { 'ref': 'queues/{queue_name}/messages', 'method': 'DELETE', 'required': ['queue_name', 'ids'], 'properties': { 'queue_name': {'type': 'string'}, 'ids': {'type': 'string'}, } }, 'pool_create': { 'ref': 'pools/{pool_name}', 'method': 'PUT', 'required': ['pool_name'], 'properties': { 'pool_name': {'type': 'string'}, } }, 'pool_get': { 'ref': 'pools/{pool_name}', 'method': 'GET', 'required': ['pool_name'], 'properties': { 'pool_name': {'type': 'string'}, } }, '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', 'required': ['pool_name'], 'properties': { 'pool_name': {'type': 'string'}, } }, 'flavor_create': { 'ref': 'flavors/{flavor_name}', 'method': 'PUT', 'required': ['flavor_name'], 'properties': { 'flavor_name': {'type': 'string'}, } }, 'flavor_get': { 'ref': 'flavors/{flavor_name}', 'method': 'GET', 'required': ['flavor_name'], 'properties': { 'flavor_name': {'type': 'string'}, } }, 'flavor_delete': { 'ref': 'flavors/{flavor_name}', 'method': 'DELETE', 'required': ['flavor_name'], 'properties': { 'flavor_name': {'type': 'string'}, } }, 'claim_create': { 'ref': 'queues/{queue_name}/claims', 'method': 'POST', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'}, 'limit': {'type': 'integer'}, 'grace': {'type': 'integer'} } }, 'claim_get': { 'ref': 'queues/{queue_name}/claims/{claim_id}', 'method': 'GET', 'required': ['queue_name', 'claim_id'], 'properties': { 'queue_name': {'type': 'string'}, 'claim_id': {'type': 'string'} } }, 'claim_update': { 'ref': 'queues/{queue_name}/claims/{claim_id}', 'method': 'PATCH', 'required': ['queue_name', 'claim_id'], 'properties': { 'queue_name': {'type': 'string'}, 'claim_id': {'type': 'string'} } }, 'claim_delete': { 'ref': 'queues/{queue_name}/claims/{claim_id}', 'method': 'DELETE', 'required': ['queue_name', 'claim_id'], 'properties': { 'queue_name': {'type': 'string'}, 'claim_id': {'type': 'string'} } }, 'health': { 'admin': True, 'ref': 'health', 'method': 'GET', }, } class V1_1(V1): label = 'v1.1' schema = V1.schema.copy() V1_1.schema.update({ 'queue_get': { 'ref': 'queues/{queue_name}', 'method': 'GET', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'queue_update': { 'ref': 'queues/{queue_name}', 'method': 'PATCH', 'required': ['queue_name'], 'properties': { 'queue_name': {'type': 'string'} } }, 'message_pop': { 'ref': 'queues/{queue_name}/messages', 'method': 'DELETE', 'required': ['queue_name', 'pop'], 'properties': { 'queue_name': {'type': 'string'}, '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'] python-zaqarclient-1.11.0/zaqarclient/queues/v1/pool.py0000666000175000017500000000500613364112606023152 0ustar zuulzuul00000000000000# Copyright (c) 2014 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.queues.v1 import core class Pool(object): def __init__(self, client, name, weight=None, uri=None, group=None, auto_create=True, **kwargs): self.client = client self.uri = uri self.name = name self.weight = weight self.group = group self.options = kwargs.get("options", {}) if auto_create: self.ensure_exists() def ensure_exists(self): """Ensures pool exists This method is not race safe, the pool could've been deleted right after it was called. """ req, trans = self.client._request_and_transport() # As of now on PUT, zaqar server updates pool if it is already # exists else it will create a new one. The zaqar client should # maitain symmetry with zaqar server. # TBD(mdnadeem): Have to change this code when zaqar server # behaviour change for PUT operation. data = {'uri': self.uri, 'weight': self.weight, 'options': self.options} if self.client.api_version >= 1.1 and self.group: data['group'] = self.group req, trans = self.client._request_and_transport() 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 get(self): req, trans = self.client._request_and_transport() return core.pool_get(trans, req, self.name, callback=None) def create_object(parent): return lambda kwargs: Pool(parent, kwargs.pop('name'), auto_create=False, **kwargs) python-zaqarclient-1.11.0/zaqarclient/queues/v1/message.py0000666000175000017500000000423413364112606023627 0ustar zuulzuul00000000000000# 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. """Implements a message controller that understands Zaqar messages.""" from zaqarclient.queues.v1 import core class Message(object): """A handler for Zaqar server Message resources. Attributes are only downloaded once - at creation time. """ def __init__(self, queue, ttl, age, body, href=None, id=None, claim_id=None, claim_count=0, checksum=None): self.queue = queue self.href = href self.ttl = ttl self.age = age self.body = body self.claim_count = claim_count self.checksum = checksum # NOTE(flaper87): Is this really # necessary? Should this be returned # by Zaqar? # The url has two forms depending on if it has been claimed. # /v1/queues/worker-jobs/messages/5c6939a8?claim_id=63c9a592 # or # /v1/queues/worker-jobs/messages/5c6939a8 if id is None: self._id = href.split('/')[-1] if '?' in self._id: self._id = self._id.split('?')[0] else: self._id = id def __repr__(self): return ''.format(id=self._id, ttl=self.ttl) @property def claim_id(self): if '=' in self.href: return self.href.split('=')[-1] def delete(self): req, trans = self.queue.client._request_and_transport() core.message_delete(trans, req, self.queue._name, self._id, self.claim_id) def create_object(parent): return lambda args: Message(parent, **args) python-zaqarclient-1.11.0/zaqarclient/queues/v1/queues.py0000666000175000017500000002163313364112606023514 0ustar zuulzuul00000000000000# 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 re from zaqarclient._i18n import _ # noqa from zaqarclient import errors from zaqarclient.queues.v1 import claim as claim_api from zaqarclient.queues.v1 import core from zaqarclient.queues.v1 import iterator from zaqarclient.queues.v1 import message # NOTE(wanghao): This is copied from Zaqar server side, so if server have # updated it someday, we should update it here to keep consistent. QUEUE_NAME_REGEX = re.compile('^[a-zA-Z0-9_\-]+$') class Queue(object): message_module = message def __init__(self, client, name, href=None, metadata=None, auto_create=True, force_create=False): """Initialize queue object :param client: The client object of Zaqar. :type client: `object` :param name: Name of the queue. :type name: `six.string_type` :param href : Hypertext Reference. :type href: `six.string_type` :param metadata : A metadata object of the queue. :type metadata: `dict` :param auto_create: If create the queue automatically in database. :type auto_create: `boolean` :param force_create: If create the queue and skip the API version check, which is useful for command line interface. :type force_create: `boolean` :returns: The queue object. """ self.client = client if name == "": raise ValueError(_('Queue name does not have a value')) if not QUEUE_NAME_REGEX.match(str(name)): raise ValueError(_('The queue name may only contain ASCII ' 'letters, digits, underscores and dashes.')) # NOTE(flaper87) Queue Info self._name = name self._metadata = metadata self._href = href # NOTE(flwang): If force_create is True, then even though auto_create # is not True, the queue should be created anyway. if auto_create or force_create: self.ensure_exists(force_create=force_create) @property def name(self): return self._name @property def href(self): return self._href @property def metadata_dict(self): return dict(self.metadata()) def exists(self): """Checks if the queue exists.""" req, trans = self.client._request_and_transport() if self.client.api_version >= 1.1: raise errors.InvalidOperation("Unavailable on versions >= 1.1") else: return core.queue_exists(trans, req, self._name) def ensure_exists(self, force_create=False): """Ensures a queue exists This method is not race safe, the queue could've been deleted right after it was called. """ req, trans = self.client._request_and_transport() if force_create or self.client.api_version < 1.1: core.queue_create(trans, req, self._name) def metadata(self, new_meta=None, force_reload=False): """Get metadata and return it :param new_meta: A dictionary containing an updated metadata object. If present the queue metadata will be updated in remote server. If the new_meta is empty, the metadata object will be cleared. :type new_meta: `dict` :param force_reload: Whether to ignored the cached metadata and reload it from the server. :type force_reload: `bool` :returns: The queue metadata. """ req, trans = self.client._request_and_transport() # NOTE(jeffrey4l): Ensure that metadata is cleared when the new_meta # is an empty dict. if new_meta is not None: if self.client.api_version == 1.1: raise RuntimeError("V1.1 doesn't support to set the queue's " "metadata. Please use V1.0 or V2.") core.queue_set_metadata(trans, req, self._name, new_meta) self._metadata = new_meta # TODO(flaper87): Cache with timeout if self._metadata and not force_reload: return self._metadata if self.client.api_version >= 1.1: self._metadata = core.queue_get(trans, req, self._name) else: self._metadata = core.queue_get_metadata(trans, req, self._name) return self._metadata @property def stats(self): req, trans = self.client._request_and_transport() return core.queue_get_stats(trans, req, self._name) def delete(self): req, trans = self.client._request_and_transport() core.queue_delete(trans, req, self._name) # Messages API def post(self, messages): """Posts one or more messages to this queue :param messages: One or more messages to post :type messages: `list` or `dict` :returns: A dict with the result of this operation. :rtype: `dict` """ if not isinstance(messages, list): messages = [messages] if self.client.api_version >= 1.1: messages = {'messages': messages} req, trans = self.client._request_and_transport() # TODO(flaper87): Return a list of messages return core.message_post(trans, req, self._name, messages) 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() msg = core.message_get(trans, req, self._name, message_id) return self.message_module.Message(self, **msg) def messages(self, *messages, **params): """Gets a list of messages from the server This method returns a list of messages, it can be used to retrieve a set of messages by id or to walk through the active messages by using the collection endpoint. The `messages` and `params` params are mutually exclusive and the former has the priority. :param messages: List of messages' ids to retrieve. :type messages: *args of `six.string_type` :param params: Filters to use for getting messages :type params: **kwargs dict. :returns: List of messages :rtype: `list` """ req, trans = self.client._request_and_transport() # TODO(flaper87): Return a MessageIterator. # This iterator should handle limits, pagination # and messages deserialization. if messages: msgs = core.message_get_many(trans, req, self._name, messages) else: # NOTE(flaper87): It's safe to access messages # directly. If something wrong happens, the core # API will raise the right exceptions. msgs = core.message_list(trans, req, self._name, **params) return iterator._Iterator(self.client, msgs, 'messages', self.message_module.create_object(self)) def delete_messages(self, *messages): """Deletes a set of messages from the server :param messages: List of messages' ids to delete. :type messages: *args of `six.string_type` """ req, trans = self.client._request_and_transport() return core.message_delete_many(trans, req, self._name, set(messages)) def pop(self, count=1): """Pop `count` messages from the server :param count: Number of messages to pop. :type count: int :returns: List of messages :rtype: `list` """ req, trans = self.client._request_and_transport() msgs = core.message_pop(trans, req, self._name, count=count) return iterator._Iterator(self.client, msgs, 'messages', self.message_module.create_object(self)) def claim(self, id=None, ttl=None, grace=None, limit=None): return claim_api.Claim(self, id=id, ttl=ttl, grace=grace, limit=limit) def create_object(parent): return lambda args: Queue(parent, args["name"], auto_create=False) python-zaqarclient-1.11.0/zaqarclient/queues/v1/cli.py0000666000175000017500000010244013364112606022750 0ustar zuulzuul00000000000000# Copyright 2014 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 from osc_lib.command import command from osc_lib import utils from oslo_log import log as logging from zaqarclient._i18n import _ from zaqarclient.transport import errors def _get_client(obj, parsed_args): obj.log.debug("take_action(%s)" % parsed_args) return obj.app.client_manager.messaging class CreateQueue(command.ShowOne): """Create a queue""" _description = _("Create a queue") log = logging.getLogger(__name__ + ".CreateQueue") def get_parser(self, prog_name): parser = super(CreateQueue, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name data = client.queue(queue_name, force_create=True) columns = ('Name',) return columns, utils.get_item_properties(data, columns) class OldCreateQueue(CreateQueue): """Create a queue""" _description = _("Create a queue") # TODO(wanghao): Remove this class and ``queue create`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue create" instead.')) return super(OldCreateQueue, self).take_action(parsed_args) class DeleteQueue(command.Command): """Delete a queue""" _description = _("Delete a queue") log = logging.getLogger(__name__ + ".DeleteQueue") def get_parser(self, prog_name): parser = super(DeleteQueue, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name client.queue(queue_name).delete() class OldDeleteQueue(DeleteQueue): """Delete a queue""" _description = _("Delete a queue") # TODO(wanghao): Remove this class and ``queue delete`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue delete" instead.')) return super(OldDeleteQueue, self).take_action(parsed_args) class ListQueues(command.Lister): """List available queues""" _description = _("List available queues") log = logging.getLogger(__name__ + ".ListQueues") def get_parser(self, prog_name): parser = super(ListQueues, self).get_parser(prog_name) parser.add_argument( "--marker", metavar="", help="Queue's paging marker") parser.add_argument( "--limit", metavar="", help="Page size limit") parser.add_argument( "--detailed", action="store_true", help="If show detailed information of queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} columns = ["Name"] if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit if parsed_args.detailed is not None and parsed_args.detailed: kwargs["detailed"] = parsed_args.detailed columns.extend(["Metadata_Dict", "Href"]) data = client.queues(**kwargs) columns = tuple(columns) return (columns, (utils.get_item_properties(s, columns) for s in data)) class OldListQueues(ListQueues): """List available queues""" _description = _("List available queues") # TODO(wanghao): Remove this class and ``queue list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue list" instead.')) return super(OldListQueues, self).take_action(parsed_args) class CheckQueueExistence(command.ShowOne): """Check queue existence""" _description = _("Check queue existence") log = logging.getLogger(__name__ + ".CheckQueueExistence") def get_parser(self, prog_name): parser = super(CheckQueueExistence, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue = client.queue(queue_name, auto_create=False) columns = ('Exists',) data = dict(exists=queue.exists()) return columns, utils.get_dict_properties(data, columns) class OldQueueExistence(CheckQueueExistence): """Check queue existence""" _description = _("Check queue existence") # TODO(wanghao): Remove this class and ``queue exists`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue exists" instead.')) return super(OldQueueExistence, self).take_action(parsed_args) class SetQueueMetadata(command.Command): """Set queue metadata""" _description = _("Set queue metadata") log = logging.getLogger(__name__ + ".SetQueueMetadata") def get_parser(self, prog_name): parser = super(SetQueueMetadata, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") parser.add_argument( "queue_metadata", metavar="", help="Queue metadata") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue_metadata = parsed_args.queue_metadata if (client.api_version == 1 and not client.queue(queue_name, auto_create=False).exists()): raise RuntimeError("Queue(%s) does not exist." % queue_name) try: valid_metadata = json.loads(queue_metadata) except ValueError: raise RuntimeError("Queue metadata(%s) is not a valid json." % queue_metadata) client.queue(queue_name, auto_create=False).\ metadata(new_meta=valid_metadata) class OldSetQueueMetadata(SetQueueMetadata): """Set queue metadata""" _description = _("Set queue metadata") # TODO(wanghao): Remove this class and ``queue set metadata`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue set metadata" ' 'instead.')) return super(OldSetQueueMetadata, self).take_action(parsed_args) class GetQueueMetadata(command.ShowOne): """Get queue metadata""" _description = _("Get queue metadata") log = logging.getLogger(__name__ + ".GetQueueMetadata") def get_parser(self, prog_name): parser = super(GetQueueMetadata, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue = client.queue(queue_name, auto_create=False) if client.api_version == 1 and not queue.exists(): raise RuntimeError("Queue(%s) does not exist." % queue_name) columns = ("Metadata",) data = dict(metadata=queue.metadata()) return columns, utils.get_dict_properties(data, columns) class OldGetQueueMetadata(GetQueueMetadata): """Get queue metadata""" _description = _("Get queue metadata") # TODO(wanghao): Remove this class and ``queue get metadata`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue get metadata" ' 'instead.')) return super(OldGetQueueMetadata, self).take_action(parsed_args) class GetQueueStats(command.ShowOne): """Get queue stats""" _description = _("Get queue stats") log = logging.getLogger(__name__ + ".GetQueueStats") def get_parser(self, prog_name): parser = super(GetQueueStats, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue_name = parsed_args.queue_name queue = client.queue(queue_name, auto_create=False) try: stats = queue.stats except errors.ResourceNotFound: raise RuntimeError('Queue(%s) does not exist.' % queue_name) columns = ("Stats",) data = dict(stats=stats) return columns, utils.get_dict_properties(data, columns) class OldGetQueueStats(GetQueueStats): """Get queue stats""" _description = _("Get queue stats") # TODO(wanghao): Remove this class and ``queue stats`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging queue stats" ' 'instead.')) return super(OldGetQueueStats, self).take_action(parsed_args) class CreatePool(command.ShowOne): """Create a pool""" _description = _("Create a pool") log = logging.getLogger(__name__ + ".CreatePool") def get_parser(self, prog_name): parser = super(CreatePool, self).get_parser(prog_name) parser.add_argument( "pool_name", metavar="", help="Name of the pool") parser.add_argument( "pool_uri", metavar="", help="Storage engine URI") parser.add_argument( "pool_weight", type=int, metavar="", help="weight of the pool") parser.add_argument( "--pool_group", metavar="", help="Group of the pool") parser.add_argument( "--pool_options", type=json.loads, default={}, metavar="", help="An optional request component " "related to storage-specific options") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kw_arg = { 'uri': parsed_args.pool_uri, 'weight': parsed_args.pool_weight, 'options': parsed_args.pool_options } if parsed_args.pool_group: kw_arg.update({'group': parsed_args.pool_group}) data = client.pool(parsed_args.pool_name, **kw_arg) if not data: raise RuntimeError('Failed to create pool(%s).' % parsed_args.pool_name) columns = ('Name', 'Weight', 'URI', 'Group', 'Options') return columns, utils.get_item_properties(data, columns) class OldCreatePool(CreatePool): """Create a pool""" _description = _("Create a pool") # TODO(wanghao): Remove this class and ``pool create`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging pool create" ' 'instead.')) return super(OldCreatePool, self).take_action(parsed_args) class ShowPool(command.ShowOne): """Display pool details""" _description = _("Display pool details") log = logging.getLogger(__name__ + ".ShowPool") def get_parser(self, prog_name): parser = super(ShowPool, self).get_parser(prog_name) parser.add_argument( "pool_name", metavar="", help="Pool to display (name)", ) return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) pool_data = client.pool(parsed_args.pool_name, auto_create=False).get() columns = ('Name', 'Weight', 'URI', 'Group', 'Options') return columns, utils.get_dict_properties(pool_data, columns) class OldShowPool(ShowPool): """Display pool details""" _description = _("Display pool details") # TODO(wanghao): Remove this class and ``pool show`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging pool show" ' 'instead.')) return super(OldShowPool, self).take_action(parsed_args) class UpdatePool(command.ShowOne): """Update a pool attribute""" _description = _("Update a pool attribute") log = logging.getLogger(__name__+".UpdatePool") def get_parser(self, prog_name): parser = super(UpdatePool, self).get_parser(prog_name) parser.add_argument( "pool_name", metavar="", help="Name of the pool") parser.add_argument( "--pool_uri", metavar="", help="Storage engine URI") parser.add_argument( "--pool_weight", type=int, metavar="", help="Weight of the pool") parser.add_argument( "--pool_group", metavar="", help="Group of the pool") parser.add_argument( "--pool_options", type=json.loads, metavar="", help="An optional request component " "related to storage-specific options") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kw_arg = {} if parsed_args.pool_uri: kw_arg["uri"] = parsed_args.pool_uri if parsed_args.pool_weight: kw_arg["weight"] = parsed_args.pool_weight if parsed_args.pool_group: kw_arg["group"] = parsed_args.pool_group if parsed_args.pool_options: kw_arg["options"] = parsed_args.pool_options pool_obj = client.pool(parsed_args.pool_name, auto_create=False) pool_obj.update(kw_arg) pool_data = pool_obj.get() columns = ('Name', 'Weight', 'URI', 'Group', 'Options') return columns, utils.get_dict_properties(pool_data, columns) class OldUpdatePool(UpdatePool): """Update a pool attribute""" _description = _("Update a pool attribute") # TODO(wanghao): Remove this class and ``pool update`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging pool update" ' 'instead.')) return super(OldUpdatePool, self).take_action(parsed_args) class DeletePool(command.Command): """Delete a pool""" _description = _("Delete a pool") log = logging.getLogger(__name__ + ".DeletePool") def get_parser(self, prog_name): parser = super(DeletePool, self).get_parser(prog_name) parser.add_argument( "pool_name", metavar="", help="Name of the pool") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) pool_name = parsed_args.pool_name client.pool(pool_name, auto_create=False).delete() class OldDeletePool(DeletePool): """Delete a pool""" _description = _("Delete a pool") # TODO(wanghao): Remove this class and ``pool delete`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging pool delete" ' 'instead.')) return super(OldDeletePool, self).take_action(parsed_args) class ListPools(command.Lister): """List available Pools""" _description = _("List available Pools") log = logging.getLogger(__name__ + ".ListPools") def get_parser(self, prog_name): parser = super(ListPools, self).get_parser(prog_name) parser.add_argument( "--marker", metavar="", help="Pool's paging marker") parser.add_argument( "--limit", metavar="", help="Page size limit") parser.add_argument( "--detailed", action="store_true", help="Detailed output") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} columns = ["Name", "Weight", "URI", "Group"] if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit if parsed_args.detailed is not None and parsed_args.detailed: kwargs["detailed"] = parsed_args.detailed columns.append("Options") data = client.pools(**kwargs) columns = tuple(columns) return (columns, (utils.get_item_properties(s, columns) for s in data)) class OldListPools(ListPools): """List available Pools""" _description = _("List available Pools") # TODO(wanghao): Remove this class and ``pool list`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging pool list" ' 'instead.')) return super(OldListPools, self).take_action(parsed_args) class UpdateFlavor(command.ShowOne): """Update a flavor's attributes""" _description = _("Update a flavor's attributes") log = logging.getLogger(__name__+".UpdateFlavor") def get_parser(self, prog_name): parser = super(UpdateFlavor, self).get_parser(prog_name) parser.add_argument( "flavor_name", metavar="", help="Name of the flavor") parser.add_argument( "--pool_group", metavar="", help="Pool group the flavor sits on") parser.add_argument( "--capabilities", metavar="", type=json.loads, help="Describes flavor-specific capabilities.") return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {} if parsed_args.pool_group: kwargs['pool'] = parsed_args.pool_group if parsed_args.capabilities: kwargs['capabilities'] = json.loads(parsed_args.capabilities) flavor = client.flavor(parsed_args.flavor_name, auto_create=False) columns = ('Name', 'Pool', 'Capabilities') flavor.update(kwargs) flavor_data = flavor.get() return columns, utils.get_dict_properties(flavor_data, columns) class CreateFlavor(command.ShowOne): """Create a pool flavor""" _description = _("Create a pool flavor") log = logging.getLogger(__name__ + ".CreateFlavor") def get_parser(self, prog_name): parser = super(CreateFlavor, self).get_parser(prog_name) parser.add_argument( "flavor_name", metavar="", help="Name of the flavor") parser.add_argument( "pool_group", metavar="", help="Pool group for flavor") parser.add_argument( "--capabilities", metavar="", type=json.loads, default={}, help="Describes flavor-specific capabilities, " "This option is only available in client api version < 2 .") return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {'capabilities': parsed_args.capabilities} data = client.flavor(parsed_args.flavor_name, pool_group=parsed_args.pool_group, **kwargs) columns = ('Name', 'Pool Group', 'Capabilities') return columns, utils.get_item_properties(data, columns) class DeleteFlavor(command.Command): """Delete a pool flavor""" _description = _("Delete a pool flavor") log = logging.getLogger(__name__ + ".DeleteFlavor") def get_parser(self, prog_name): parser = super(DeleteFlavor, self).get_parser(prog_name) parser.add_argument( "flavor_name", metavar="", help="Name of the flavor") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) flavor_name = parsed_args.flavor_name client.flavor(flavor_name).delete() class ShowFlavor(command.ShowOne): """Display pool flavor details""" _description = _("Display pool flavor details") log = logging.getLogger(__name__ + ".ShowFlavor") def get_parser(self, prog_name): parser = super(ShowFlavor, self).get_parser(prog_name) parser.add_argument( "flavor_name", metavar="", help="Flavor to display (name)", ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) client = self.app.client_manager.messaging flavor_data = client.flavor(parsed_args.flavor_name, auto_create=False).get() columns = ('Name', 'Pool Group', 'Capabilities') return columns, utils.get_dict_properties(flavor_data, columns) class ListFlavors(command.Lister): """List available pool flavors""" _description = _("List available pool flavors") log = logging.getLogger(__name__ + ".ListFlavors") def get_parser(self, prog_name): parser = super(ListFlavors, self).get_parser(prog_name) parser.add_argument( "--marker", metavar="", help="Flavor's paging marker") parser.add_argument( "--limit", metavar="", help="Page size limit") parser.add_argument( "--detailed", action="store_true", help="If show detailed capabilities of flavor") return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.messaging kwargs = {'detailed': parsed_args.detailed} if parsed_args.marker is not None: kwargs["marker"] = parsed_args.marker if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit data = client.flavors(**kwargs) columns = ("Name", 'Pool') if parsed_args.detailed: columns = ("Name", 'Pool', 'Capabilities') return (columns, (utils.get_item_properties(s, columns) for s in data)) class CreateClaim(command.Lister): """Create claim and return a list of claimed messages""" _description = _("Create claim and return a list of claimed messages") log = logging.getLogger(__name__ + ".CreateClaim") def get_parser(self, prog_name): parser = super(CreateClaim, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the queue to be claim") parser.add_argument( "--ttl", metavar="", type=int, default=300, help="Time to live in seconds for claim") parser.add_argument( "--grace", metavar="", type=int, default=60, help="The message grace period in seconds") parser.add_argument( "--limit", metavar="", type=int, default=10, help="Claims a set of messages, up to limit") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) kwargs = {} if parsed_args.ttl is not None: kwargs["ttl"] = parsed_args.ttl if parsed_args.grace is not None: kwargs["grace"] = parsed_args.grace if parsed_args.limit is not None: kwargs["limit"] = parsed_args.limit queue = client.queue(parsed_args.queue_name, auto_create=False) keys = ("claim_id", "_id", "ttl", "age", 'body') columns = ("Claim_ID", "Message_ID", "TTL", "Age", "Messages") data = queue.claim(**kwargs) return (columns, (utils.get_item_properties(s, keys) for s in data)) class OldCreateClaim(CreateClaim): """Create claim and return a list of claimed messages""" _description = _("Create claim and return a list of claimed messages") # TODO(wanghao): Remove this class and ``claim create`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging claim create" ' 'instead.')) return super(OldCreateClaim, self).take_action(parsed_args) class QueryClaim(command.Lister): """Display claim details""" _description = _("Display claim details") log = logging.getLogger(__name__ + ".QueryClaim") def get_parser(self, prog_name): parser = super(QueryClaim, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the claimed queue") parser.add_argument( "claim_id", metavar="", help="ID of the claim") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue = client.queue(parsed_args.queue_name, auto_create=False) keys = ("_id", "age", "ttl", "body") columns = ("Message_ID", "Age", "TTL", "Message") data = queue.claim(id=parsed_args.claim_id) return (columns, (utils.get_item_properties(s, keys) for s in data)) class OldQueryClaim(QueryClaim): """Display claim details""" _description = _("Display claim details") # TODO(wanghao): Remove this class and ``claim query`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging claim query" ' 'instead.')) return super(OldQueryClaim, self).take_action(parsed_args) class RenewClaim(command.Lister): """Renew a claim""" _description = _("Renew a claim") log = logging.getLogger(__name__ + ".RenewClaim") def get_parser(self, prog_name): parser = super(RenewClaim, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the claimed queue") parser.add_argument( "claim_id", metavar="", help="Claim ID") parser.add_argument( "--ttl", metavar="", type=int, help="Time to live in seconds for claim") parser.add_argument( "--grace", metavar="", type=int, help="The message grace period in seconds") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue = client.queue(parsed_args.queue_name, auto_create=False) kwargs = {} if parsed_args.ttl is not None: kwargs["ttl"] = parsed_args.ttl if parsed_args.grace is not None: kwargs["grace"] = parsed_args.grace claim_obj = queue.claim(id=parsed_args.claim_id) claim_obj.update(**kwargs) data = claim_obj keys = ("_id", "age", "ttl", "body") columns = ("Message_ID", "Age", "TTL", "Message") return (columns, (utils.get_item_properties(s, keys) for s in data)) class OldRenewClaim(RenewClaim): """Renew a claim""" _description = _("Renew a claim") # TODO(wanghao): Remove this class and ``claim renew`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging claim renew" ' 'instead.')) return super(OldRenewClaim, self).take_action(parsed_args) class ReleaseClaim(command.Command): """Delete a claim""" _description = _("Delete a claim") log = logging.getLogger(__name__ + ".ReleaseClaim") def get_parser(self, prog_name): parser = super(ReleaseClaim, self).get_parser(prog_name) parser.add_argument( "queue_name", metavar="", help="Name of the claimed queue") parser.add_argument( "claim_id", metavar="", help="Claim ID to delete") return parser def take_action(self, parsed_args): client = _get_client(self, parsed_args) queue = client.queue(parsed_args.queue_name, auto_create=False) queue.claim(id=parsed_args.claim_id).delete() class OldReleaseClaim(ReleaseClaim): """Delete a claim""" _description = _("Delete a claim") # TODO(wanghao): Remove this class and ``claim release`` command # after Queen. # This notifies cliff to not display the help for this command deprecated = True log = logging.getLogger('deprecated') def take_action(self, parsed_args): self.log.warning(_('This command has been deprecated. ' 'Please use "messaging claim release" ' 'instead.')) return super(OldReleaseClaim, self).take_action(parsed_args) python-zaqarclient-1.11.0/zaqarclient/queues/v1/iterator.py0000666000175000017500000000712513364112606024036 0ustar zuulzuul00000000000000# Copyright (c) 2014 Rackspace # # 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. class _Iterator(object): """Base Iterator This iterator is not meant to be used outside the scope of this package. The iterator gets a dictionary as returned by a listing endpoint. Subclasses of this base class determine the key to iterate over, as well as the means of creating the objects contained within. If there are no objects left to return, the iterator will try to load more by following the `next` rel link type. The iterator raises a StopIteration exception if the server doesn't return more objects after a `next-page` call. :param client: The client instance used by the queue :type client: `v1.Client` :param listing_response: Response returned by the listing call :type listing_response: Dict """ def __init__(self, client, listing_response, iter_key, create_function): self._client = client self._iter_key = iter_key self._create_function = create_function self._links = [] self._stream = False self._listing_response = listing_response # NOTE(flaper87): Simple hack to # re-use the iterator for get_many_messages # and message listing. if isinstance(listing_response, dict): self._links = listing_response.get('links', []) self._listing_response = listing_response[self._iter_key] def __iter__(self): return self def get_iterables(self, iterables): self._links = iterables['links'] self._listing_response = iterables[self._iter_key] def stream(self, enabled=True): """Make this `_Iterator` a stream iterator. Since `_Iterator`'s default is to *not* stream, this method's default value is to *stream* data from the server. That is, unless explicitly specified this method will enable make this iterator a stream iterator. :param enabled: Whether streaming should be enabled or not. :type enabled: bool """ self._stream = enabled return self def _next_page(self): for link in self._links: if link['rel'] == 'next': # NOTE(flaper87): We already have the # ref for the next set of messages, lets # just follow it. iterables = self._client.follow(link['href']) # NOTE(flaper87): Since we're using # `.follow`, the empty result will # be None. Consider making the API # return an empty dict for consistency. if iterables: self.get_iterables(iterables) return raise StopIteration def __next__(self): try: args = self._listing_response.pop(0) except IndexError: if not self._stream: raise StopIteration self._next_page() return self.next() return self._create_function(args) # NOTE(flaper87): Py2K support next = __next__ python-zaqarclient-1.11.0/zaqarclient/queues/v1/flavor.py0000666000175000017500000000462613364112606023501 0ustar zuulzuul00000000000000# Copyright (c) 2014 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.queues.v1 import core class Flavor(object): def __init__(self, client, name, pool_group=None, auto_create=True, **kwargs): self.client = client self.name = name self.pool_group = pool_group self.capabilities = kwargs.get('capabilities', {}) if auto_create: self.ensure_exists() def ensure_exists(self): """Ensures pool exists This method is not race safe, the pool could've been deleted right after it was called. """ req, trans = self.client._request_and_transport() # As of now on PUT, zaqar server updates flavor if it is already # exists else it will create a new one. The zaqar client should # maitain symmetry with zaqar server. # TBD(mdnadeem): Have to change this code when zaqar server # behaviour change for PUT operation. data = {'pool_group': self.pool_group} if self.client.api_version <= 1.1: data['capabilities'] = self.capabilities req, trans = self.client._request_and_transport() 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 get(self): req, trans = self.client._request_and_transport() return core.flavor_get(trans, req, self.name, callback=None) def create_object(parent): return lambda kwargs: Flavor(parent, kwargs.pop('name'), auto_create=False, **kwargs) python-zaqarclient-1.11.0/zaqarclient/queues/v1/__init__.py0000666000175000017500000000000013364112606023725 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/v1/core.py0000666000175000017500000005221713364112606023137 0ustar zuulzuul00000000000000# 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' v1. 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. """ import json import zaqarclient.transport.errors as errors def _common_queue_ops(operation, transport, request, name, callback=None): """Function for common operation This is a lower level call to get a single instance of queue. :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 name: Queue reference name. :type name: `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = operation request.params['queue_name'] = name resp = transport.send(request) return resp.deserialized_content def queue_create(transport, request, name, metadata=None, callback=None): """Creates a queue :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 name: Queue reference name. :type name: `six.text_type` :param metadata: Queue's metadata object. (>=v1.1) :type metadata: `dict` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'queue_create' request.params['queue_name'] = name request.content = metadata and json.dumps(metadata) resp = transport.send(request) return resp.deserialized_content def queue_update(transport, request, name, metadata, callback=None): """Updates a queue's metadata using PATCH. API v1.1+ only :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 name: Queue reference name. :type name: `six.text_type` :param metadata: Queue's metadata object. (>=v1.1) :type metadata: `dict` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'queue_update' request.params['queue_name'] = name request.content = json.dumps(metadata) resp = transport.send(request) return resp.deserialized_content def queue_exists(transport, request, name, callback=None): """Checks if the queue exists.""" try: _common_queue_ops('queue_exists', transport, request, name, callback=callback) return True except errors.ResourceNotFound: return False def queue_get(transport, request, name, callback=None): """Retrieve a queue.""" return _common_queue_ops('queue_get', transport, request, name, callback=callback) def queue_get_metadata(transport, request, name, callback=None): """Gets queue metadata.""" return _common_queue_ops('queue_get_metadata', transport, request, name, callback=callback) def queue_set_metadata(transport, request, name, metadata, callback=None): """Sets queue metadata.""" request.operation = 'queue_set_metadata' request.params['queue_name'] = name request.content = json.dumps(metadata) transport.send(request) def queue_get_stats(transport, request, name): return _common_queue_ops('queue_get_stats', transport, request, name) def queue_delete(transport, request, name, callback=None): """Deletes queue.""" return _common_queue_ops('queue_delete', transport, request, name, callback=callback) def queue_list(transport, request, callback=None, **kwargs): """Gets a list of queues :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 callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. :param kwargs: Optional arguments for this operation. - marker: Where to start getting queues from. - limit: Maximum number of queues to get. """ request.operation = 'queue_list' request.params.update(kwargs) resp = transport.send(request) if not resp.content: return {'links': [], 'queues': []} return resp.deserialized_content def message_list(transport, request, queue_name, callback=None, **kwargs): """Gets a list of messages in queue `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. :param kwargs: Optional arguments for this operation. - marker: Where to start getting messages from. - limit: Maximum number of messages to get. - echo: Whether to get our own messages. - include_claimed: Whether to include claimed messages. """ request.operation = 'message_list' request.params['queue_name'] = queue_name # NOTE(flaper87): Assume passed params # are accepted by the API, if not, the # API itself will raise an error. request.params.update(kwargs) resp = transport.send(request) if not resp.content: # NOTE(flaper87): We could also return None # or an empty dict, however, we're giving # more value to a consistent API here by # returning a compliant dict with empty # `links` and `messages` return {'links': [], 'messages': []} return resp.deserialized_content def message_post(transport, request, queue_name, messages, callback=None): """Post messages to `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param messages: One or more messages to post. :param messages: `list` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_post' request.params['queue_name'] = queue_name request.content = json.dumps(messages) resp = transport.send(request) return resp.deserialized_content def message_get(transport, request, queue_name, message_id, callback=None): """Gets one message from the queue by id :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param message_id: Message reference. :param message_id: `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_get' request.params['queue_name'] = queue_name request.params['message_id'] = message_id resp = transport.send(request) return resp.deserialized_content def message_get_many(transport, request, queue_name, messages, callback=None): """Gets many messages by id :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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param messages: Messages references. :param messages: list of `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_get_many' request.params['queue_name'] = queue_name request.params['ids'] = messages resp = transport.send(request) return resp.deserialized_content def message_delete(transport, request, queue_name, message_id, claim_id=None, callback=None): """Deletes messages from `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param message_id: Message reference. :param message_id: `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_delete' request.params['queue_name'] = queue_name request.params['message_id'] = message_id if claim_id: request.params['claim_id'] = claim_id transport.send(request) def message_delete_many(transport, request, queue_name, ids, callback=None): """Deletes `ids` messages from `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param ids: Ids of the messages to delete :type ids: List of `six.text_type` :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_delete_many' request.params['queue_name'] = queue_name request.params['ids'] = ids transport.send(request) def message_pop(transport, request, queue_name, count, callback=None): """Pops out `count` messages from `queue_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 queue_name: Queue reference name. :type queue_name: `six.text_type` :param count: Number of messages to pop. :type count: int :param callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'message_delete_many' request.params['queue_name'] = queue_name request.params['pop'] = count resp = transport.send(request) return resp.deserialized_content def claim_create(transport, request, queue_name, **kwargs): """Creates a Claim `claim_id` on the queue `queue_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` """ request.operation = 'claim_create' request.params['queue_name'] = queue_name if 'limit' in kwargs: request.params['limit'] = kwargs.pop('limit') request.content = json.dumps(kwargs) resp = transport.send(request) return resp.deserialized_content def claim_get(transport, request, queue_name, claim_id): """Gets a Claim `claim_id` :param transport: Transport instance to use :type transport: `transport.base.Transport` :param request: Request instance ready to be sent. :type request: `transport.request.Request` """ request.operation = 'claim_get' request.params['queue_name'] = queue_name request.params['claim_id'] = claim_id resp = transport.send(request) return resp.deserialized_content def claim_update(transport, request, queue_name, claim_id, **kwargs): """Updates a Claim `claim_id` :param transport: Transport instance to use :type transport: `transport.base.Transport` :param request: Request instance ready to be sent. :type request: `transport.request.Request` """ request.operation = 'claim_update' request.params['queue_name'] = queue_name request.params['claim_id'] = claim_id request.content = json.dumps(kwargs) resp = transport.send(request) return resp.deserialized_content def claim_delete(transport, request, queue_name, claim_id): """Deletes a Claim `claim_id` :param transport: Transport instance to use :type transport: `transport.base.Transport` :param request: Request instance ready to be sent. :type request: `transport.request.Request` """ request.operation = 'claim_delete' request.params['queue_name'] = queue_name request.params['claim_id'] = claim_id transport.send(request) def pool_get(transport, request, pool_name, callback=None): """Gets pool data :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` """ request.operation = 'pool_get' request.params['pool_name'] = pool_name resp = transport.send(request) return resp.deserialized_content def pool_create(transport, request, pool_name, pool_data): """Creates a pool called `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_create' request.params['pool_name'] = pool_name request.content = json.dumps(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` :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` """ request.operation = 'pool_delete' request.params['pool_name'] = pool_name transport.send(request) def flavor_create(transport, request, name, flavor_data): """Creates a flavor called `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 name: Flavor reference name. :type name: `six.text_type` :param flavor_data: Flavor's properties, i.e: pool, capabilities. :type flavor_data: `dict` """ request.operation = 'flavor_create' request.params['flavor_name'] = name request.content = json.dumps(flavor_data) transport.send(request) def flavor_get(transport, request, flavor_name, callback=None): """Gets flavor data :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` """ request.operation = 'flavor_get' request.params['flavor_name'] = flavor_name resp = transport.send(request) 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` :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 name: Flavor reference name. :type name: `six.text_type` """ request.operation = 'flavor_delete' request.params['flavor_name'] = name transport.send(request) def health(transport, request, callback=None): """Check the health of web head for load balancing :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 callback: Optional callable to use as callback. If specified, this request will be sent asynchronously. (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE) :type callback: Callable object. """ request.operation = 'health' resp = transport.send(request) return resp.deserialized_content python-zaqarclient-1.11.0/zaqarclient/queues/v1/client.py0000666000175000017500000001424313364112606023462 0ustar zuulzuul00000000000000# 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 oslo_utils import uuidutils from zaqarclient.common import decorators from zaqarclient.queues.v1 import core from zaqarclient.queues.v1 import flavor from zaqarclient.queues.v1 import iterator from zaqarclient.queues.v1 import pool from zaqarclient.queues.v1 import queues from zaqarclient import transport from zaqarclient.transport import errors from zaqarclient.transport import request class Client(object): """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 conf: CONF object. :type conf: `oslo_config.cfg.CONF` :param session: keystone session. But it's just place holder, we wont' support it in v1. """ queues_module = queues def __init__(self, url=None, version=1, conf=None, session=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', uuidutils.generate_uuid(dashed=False)) self.session = session def _get_transport(self, request): """Gets a transport and caches its instance This method gets a transport instance based on the request's endpoint and caches that for later use. The transport instance is invalidated whenever a session expires. :param request: The request to use to load the transport instance. :type request: :class:`zaqarclient.transport.request.Request` """ trans = transport.get_transport_for(request, options=self.conf) return (trans or self.transport) def _request_and_transport(self): req = request.prepare_request(self.auth_opts, endpoint=self.api_url, api=self.api_version, session=self.session) req.headers['Client-ID'] = self.client_uuid trans = self._get_transport(req) return req, trans def transport(self): """Gets a transport based the api url and version. :rtype: :class:`zaqarclient.transport.base.Transport` """ return transport.get_transport_for(self.api_url, self.api_version) def queue(self, ref, **kwargs): """Returns a queue instance :param ref: Queue's reference id. :type ref: `six.text_type` :returns: A queue instance :rtype: `queues.Queue` """ return self.queues_module.Queue(self, ref, **kwargs) def queues(self, **params): """Gets a list of queues from the server :returns: A list of queues :rtype: `list` """ req, trans = self._request_and_transport() queue_list = core.queue_list(trans, req, **params) return iterator._Iterator(self, queue_list, 'queues', self.queues_module.create_object(self)) def follow(self, ref): """Follows ref. This method instanciates a new request instance and requests `ref`. It is intended to be used to follow a reference href gotten from `links` sections in responses like queues' lists. :params ref: The reference path. :type ref: `six.text_type` """ req, trans = self._request_and_transport() req.ref = ref return trans.send(req).deserialized_content # ADMIN API def pool(self, ref, **kwargs): """Returns a pool instance :param ref: Pool's reference name. :type ref: `six.text_type` :returns: A pool instance :rtype: `pool.Pool` """ 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: 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 :param ref: Flavor's reference name. :type ref: `six.text_type` :returns: A flavor instance :rtype: `flavor.Flavor` """ 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: 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() try: core.health(trans, req) return True except errors.ServiceUnavailableError: return False python-zaqarclient-1.11.0/zaqarclient/queues/v1/claim.py0000666000175000017500000000764413364112606023300 0ustar zuulzuul00000000000000# Copyright (c) 2014 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. from zaqarclient.queues.v1 import core from zaqarclient.queues.v1 import iterator as iterate from zaqarclient.queues.v1 import message class Claim(object): def __init__(self, queue, id=None, ttl=None, grace=None, limit=None): self._queue = queue self.id = id self._ttl = ttl self._grace = grace self._age = None self._limit = limit self._message_iter = None if id is None: self._create() def __repr__(self): return ''.format(id=self.id, ttl=self.ttl, age=self.age) def _get(self): req, trans = self._queue.client._request_and_transport() claim_res = core.claim_get(trans, req, self._queue._name, self.id) self._age = claim_res['age'] self._ttl = claim_res['ttl'] self._grace = claim_res.get('grace') msgs = claim_res.get('messages', []) self._message_iter = iterate._Iterator(self._queue.client, msgs, 'messages', message.create_object( self._queue )) def _create(self): req, trans = self._queue.client._request_and_transport() msgs = core.claim_create(trans, req, self._queue._name, ttl=self._ttl, grace=self._grace, limit=self._limit) # extract the id from the first message if msgs is not None: if self._queue.client.api_version >= 1.1: msgs = msgs['messages'] self.id = msgs[0]['href'].split('=')[-1] self._message_iter = iterate._Iterator(self._queue.client, msgs or [], 'messages', message.create_object( self._queue )) def __iter__(self): if self._message_iter is None: self._get() return self._message_iter @property def age(self): self._get() return self._age @property def ttl(self): if self._ttl is None: self._get() return self._ttl def delete(self): req, trans = self._queue.client._request_and_transport() core.claim_delete(trans, req, self._queue._name, self.id) def update(self, ttl=None, grace=None): req, trans = self._queue.client._request_and_transport() kwargs = {} if ttl is not None: kwargs['ttl'] = ttl if grace is not None: kwargs['grace'] = grace res = core.claim_update(trans, req, self._queue._name, self.id, **kwargs) # if the update succeeds, update our attributes. if ttl is not None: self._ttl = ttl if grace is not None: self._grace = grace return res python-zaqarclient-1.11.0/zaqarclient/queues/__init__.py0000666000175000017500000000000013364112606023377 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/queues/client.py0000666000175000017500000000662613364112606023142 0ustar zuulzuul00000000000000# 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. """ A `Client` is a high-level abstraction on top of Zaqar features. It exposes the server features with an object-oriented interface, which encourages dot notation and automatic, but lazy, resources allocation. A `Client` allows you to control everything, from public interfaces to admin endpoints. To create a `Client` instance, you supply an url pointing to the server and a version number:: from zaqarclient.queues import client cli = client.Client(\'http://zaqar.example.com:8888/\', version=2) which will load the appropriate client based on the specified version. Optionally, you can also supply a config dictionary:: from zaqarclient.queues import client cli = client.Client(\'http://zaqar.example.com:8888/\', version=2, conf={}) The arguments passed to this function will be passed to the client instances as well. It's recommended to use `Client` instances instead of accessing the lower level API as it has been designed to ease the interaction with the server and it gives enough control for the most common cases. A simple example for accessing an existing queue through a client instance - based on the API v2 - would look like:: from zaqarclient.queues import client cli = client.Client(\'http://zaqar.example.com:8888/\', version=2) queue = cli.queue(\'my_queue\') Through the queue instance will be then possible to access all the features associated with the queue itself like posting messages, getting message and deleting messages. As mentioned previously in this documentation, a client instance allows you to also access admin endpoints, for example:: from zaqarclient.queues import client cli = client.Client(\'http://zaqar.example.com:8888/\', version=2) flavor = cli.flavor(\'tasty\', pool=\'my-pool-group\', auto_create=True) flavor.delete() `Client` uses the lower-level API to access the server, which means anything you can do with this client instance can be done by accessing 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, 2: cv2.Client} def Client(url=None, version=None, conf=None, session=None): # NOTE: Please don't mix use the Client object with different version at # the same time. Because the cache mechanism of queue's metadata will lead # to unexpected response value. # Please see zaqarclient.queues.v1.queues.Queue.metadata and # zaqarclient.queues.v2.queues.Queue.metadata for more detail. try: return _CLIENTS[version](url=url, version=version, conf=conf, session=session) except KeyError: raise errors.ZaqarError('Unknown client version') python-zaqarclient-1.11.0/zaqarclient/errors.py0000666000175000017500000000251113364112606021656 0ustar zuulzuul00000000000000# Copyright 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._i18n import _ # noqa __all__ = ['ZaqarError', 'DriverLoadFailure', 'InvalidOperation'] class ZaqarError(Exception): """Base class for errors.""" class DriverLoadFailure(ZaqarError): """Raised if a transport driver can't be loaded.""" def __init__(self, driver, ex): msg = (_('Failed to load transport driver "%(driver)s": %(error)s') % {'driver': driver, 'error': ex}) super(DriverLoadFailure, self).__init__(msg) self.driver = driver self.ex = ex class InvalidOperation(ZaqarError): """Raised when attempted a non existent operation.""" class UnsupportedVersion(ZaqarError): """Raised if there is no endpoint which supports the requested version.""" python-zaqarclient-1.11.0/zaqarclient/_i18n.py0000666000175000017500000000145013364112606021261 0ustar zuulzuul00000000000000# Copyright 2014 Red Hat, Inc # All Rights .Reserved. # # 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 oslo_i18n import * # noqa _translators = TranslatorFactory(domain='zaqarclient') # The primary translation function using the well-known name "_" _ = _translators.primary python-zaqarclient-1.11.0/zaqarclient/tests/0000775000175000017500000000000013364112773021136 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/queues/0000775000175000017500000000000013364112773022445 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/queues/pool.py0000666000175000017500000001433113364112606023767 0ustar zuulzuul00000000000000# Copyright (c) 2014 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.queues.v1 import iterator from zaqarclient.tests.queues import base from zaqarclient.transport import response class QueuesV1PoolUnitTest(base.QueuesTestBase): def test_pool_create(self): pool_data = {'weight': 10, 'uri': 'sqlite://'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True pool = self.client.pool('test', **pool_data) self.assertEqual('test', pool.name) self.assertEqual(10, pool.weight) def test_pool_get(self): pool_data = {'weight': 10, 'name': 'test', 'uri': 'sqlite://', 'options': {}} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(pool_data)) send_method.return_value = resp # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True pool = self.client.pool('test') pool1 = pool.get() self.assertEqual('test', pool1['name']) self.assertEqual(10, pool1['weight']) 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://', 'options': {}} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) resp_data = response.Response(None, json.dumps(pool_data)) send_method.side_effect = iter([resp_data, resp]) # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True pool = self.client.pool('test', **pool_data) pool.delete() # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. class QueuesV1_1PoolFunctionalTest(base.QueuesTestBase): def test_pool_get(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('FuncTestPool', **pool_data) resp_data = pool.get() self.addCleanup(pool.delete) self.assertEqual('FuncTestPool', resp_data['name']) self.assertEqual(10, resp_data['weight']) self.assertEqual('mongodb://127.0.0.1:27017', resp_data['uri']) def test_pool_create(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('FuncTestPool', **pool_data) self.addCleanup(pool.delete) self.assertEqual('FuncTestPool', pool.name) self.assertEqual(10, pool.weight) def test_pool_update(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('FuncTestPool', **pool_data) self.addCleanup(pool.delete) pool.update({'weight': 20}) self.assertEqual(20, pool.weight) def test_pool_list(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('FuncTestPool', **pool_data) self.addCleanup(pool.delete) pools = self.client.pools() self.assertIsInstance(pools, iterator._Iterator) self.assertEqual(1, len(list(pools))) def test_pool_delete(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('FuncTestPool', **pool_data) pool.delete() class QueuesV2PoolUnitTest(QueuesV1PoolUnitTest): pass class QueuesV2PoolFunctionalTest(QueuesV1_1PoolFunctionalTest): pass python-zaqarclient-1.11.0/zaqarclient/tests/queues/base.py0000666000175000017500000000245313364112606023732 0ustar zuulzuul00000000000000# 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 mock from oslo_utils import netutils from zaqarclient.queues import client from zaqarclient.tests import base from zaqarclient.tests.transport import dummy MY_IP = netutils.get_my_ipv4() class QueuesTestBase(base.TestBase): transport_cls = dummy.DummyTransport url = 'http://%s:8888' % MY_IP version = 1 def setUp(self): super(QueuesTestBase, self).setUp() self.transport = self.transport_cls(self.conf) self.client = client.Client(self.url, self.version, self.conf) mocked_transport = mock.Mock(return_value=self.transport) self.client._get_transport = mocked_transport self.queue = self.client.queue(1, auto_create=False) python-zaqarclient-1.11.0/zaqarclient/tests/queues/queues.py0000666000175000017500000006550213364112606024333 0ustar zuulzuul00000000000000# 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 import errors from zaqarclient.queues import client from zaqarclient.queues.v1 import iterator from zaqarclient.queues.v1 import message from zaqarclient.queues.v2 import subscription from zaqarclient.tests.queues import base from zaqarclient.transport import response class QueuesV1QueueUnitTest(base.QueuesTestBase): def test_queue_metadata(self): test_metadata = {'type': 'Bank Accounts'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(test_metadata)) send_method.return_value = resp metadata = self.queue.metadata(test_metadata) self.assertEqual(test_metadata, metadata) def test_queue_metadata_update(self): test_metadata = {'type': 'Bank Accounts'} new_meta = {'flavor': 'test'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(test_metadata)) send_method.return_value = resp metadata = self.queue.metadata(test_metadata) self.assertEqual(test_metadata, metadata) metadata = self.queue.metadata(new_meta) self.assertEqual(new_meta, metadata) def test_queue_create(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.ensure_exists() # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_queue_valid_name(self): self.assertRaises(ValueError, self.client.queue, "") def test_queue_valid_name_with_pound(self): self.assertRaises(ValueError, self.client.queue, "123#456") def test_queue_valid_name_with_percent(self): self.assertRaises(ValueError, self.client.queue, "123%456") def test_queue_delete(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.delete() # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_queue_exists(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.exists() # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_queue_stats(self): result = { "messages": { "free": 146929, "claimed": 2409, "total": 149338, "oldest": { "href": "/v1/queues/qq/messages/50b68a50d6f5b8c8a7c62b01", "age": 63, "created": "2013-08-12T20:44:55Z" }, "newest": { "href": "/v1/queues/qq/messages/50b68a50d6f5b8c8a7c62b01", "age": 12, "created": "2013-08-12T20:45:46Z" } } } with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(result)) send_method.return_value = resp stats = self.queue.stats self.assertEqual(result, stats) def test_message_post(self): messages = [{'ttl': 30, 'body': 'Post It!'}] result = { "resources": [ "/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01" ], "partial": False } with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(result)) send_method.return_value = resp posted = self.queue.post(messages) self.assertEqual(result, posted) def test_message_list(self): returned = { 'links': [{ 'rel': 'next', 'href': '/v1/queues/fizbit/messages?marker=6244-244224-783' }], 'messages': [{ 'href': '/v1/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 msgs = self.queue.messages(limit=1) self.assertIsInstance(msgs, iterator._Iterator) # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_message_get(self): returned = { 'href': '/v1/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 msgs = self.queue.message('50b68a50d6f5b8c8a7c62b01') self.assertIsInstance(msgs, message.Message) # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_message_get_many(self): returned = [{ 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01', 'ttl': 800, 'age': 790, 'body': {'event': 'ActivateAccount', 'mode': 'active'} }, { 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b02', '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.messages('50b68a50d6f5b8c8a7c62b01', '50b68a50d6f5b8c8a7c62b02') self.assertIsInstance(msg, iterator._Iterator) # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_message_delete_many(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp rst = self.queue.delete_messages('50b68a50d6f5b8c8a7c62b01', '50b68a50d6f5b8c8a7c62b02') self.assertIsNone(rst) # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. class QueuesV1QueueFunctionalTest(base.QueuesTestBase): def test_queue_create_functional(self): queue = self.client.queue("nonono") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) self.assertTrue(queue.exists()) def test_queue_delete_functional(self): queue = self.client.queue("nonono") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) self.assertTrue(queue.exists()) queue.delete() self.assertFalse(queue.exists()) def test_queue_exists_functional(self): queue = self.client.queue("404", auto_create=False) queue._get_transport = mock.Mock(return_value=self.transport) self.assertFalse(queue.exists()) def test_queue_stats_functional(self): messages = [ {'ttl': 60, 'body': 'Post It!'}, {'ttl': 60, 'body': 'Post It!'}, {'ttl': 60, 'body': 'Post It!'}, ] queue = self.client.queue("nonono") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) queue.post(messages) stats = queue.stats self.assertEqual(3, stats["messages"]["free"]) def test_queue_metadata_functional(self): test_metadata = {'type': 'Bank Accounts'} queue = self.client.queue("meta-test") queue.metadata(test_metadata) # NOTE(flaper87): Clear metadata's cache queue._metadata = None metadata = queue.metadata() self.assertEqual(test_metadata['type'], metadata['type']) def test_queue_metadata_reload_functional(self): test_metadata = {'type': 'Bank Accounts'} queue = self.client.queue("meta-test") queue.metadata(test_metadata) # NOTE(flaper87): Overwrite the cached value # but don't clear it. queue._metadata = 'test' metadata = queue.metadata(force_reload=True) self.assertEqual(test_metadata['type'], metadata['type']) def test_message_post_functional(self): messages = [ {'ttl': 60, 'body': 'Post It!'}, {'ttl': 60, 'body': 'Post It!'}, {'ttl': 60, 'body': 'Post It!'}, ] queue = self.client.queue("nonono") queue._get_transport = mock.Mock(return_value=self.transport) result = queue.post(messages) self.assertIn('resources', result) self.assertEqual(3, len(result['resources'])) def test_message_list_functional(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [{'ttl': 60, 'body': 'Post It 1!'}] queue.post(messages) messages = queue.messages() self.assertIsInstance(messages, iterator._Iterator) self.assertGreaterEqual(len(list(messages)), 0) def test_message_list_echo_functional(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, {'ttl': 60, 'body': 'Post It 3!'}, ] queue.post(messages) messages = queue.messages(echo=True) self.assertIsInstance(messages, iterator._Iterator) self.assertGreaterEqual(len(list(messages)), 3) def test_message_get_functional(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, {'ttl': 60, 'body': 'Post It 3!'}, ] res = queue.post(messages)['resources'] msg_id = res[0].split('/')[-1] msg = queue.message(msg_id) self.assertIsInstance(msg, message.Message) self.assertEqual(res[0], msg.href) def test_message_get_many_functional(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, {'ttl': 60, 'body': 'Post It 3!'}, ] res = queue.post(messages)['resources'] msgs_id = [ref.split('/')[-1] for ref in res] messages = queue.messages(*msgs_id) self.assertIsInstance(messages, iterator._Iterator) messages = list(messages) length = len(messages) if length == 3: bodies = set(message.body for message in messages) self.assertEqual( set(['Post It 1!', 'Post It 2!', 'Post It 3!']), bodies) elif length == 1: # FIXME(therve): Old broken behavior, remove it as some point pass else: self.fail("Wrong number of messages: '%d'" % length) def test_message_delete_many_functional(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, ] res = queue.post(messages)['resources'] msgs_id = [ref.split('/')[-1] for ref in res] queue.delete_messages(*msgs_id) messages = queue.messages() self.assertEqual(0, len(list(messages))) class QueuesV1_1QueueUnitTest(QueuesV1QueueUnitTest): def test_message_pop(self): returned = [{ 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01', 'ttl': 800, 'age': 790, 'body': {'event': 'ActivateAccount', 'mode': 'active'} }, { 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b02', '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.pop(count=2) self.assertIsInstance(msg, iterator._Iterator) # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_queue_metadata(self): test_metadata = {'type': 'Bank Accounts'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(test_metadata)) send_method.return_value = resp self.assertRaises(RuntimeError, self.queue.metadata, test_metadata) def test_queue_metadata_update(self): # v1.1 doesn't support set queue metadata pass class QueuesV1_1QueueFunctionalTest(QueuesV1QueueFunctionalTest): def test_queue_create_functional(self): pass def test_queue_exists_functional(self): queue = self.client.queue("404") self.assertRaises(errors.InvalidOperation, queue.exists) def test_queue_delete_functional(self): queue = self.client.queue("nonono") queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, {'ttl': 60, 'body': 'Post It 3!'}, ] queue.post(messages) queue.delete() self.assertEqual(0, len(list(queue.messages(echo=True)))) def test_message_pop(self): queue = self.client.queue("test_queue") self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) messages = [ {'ttl': 60, 'body': 'Post It 1!'}, {'ttl': 60, 'body': 'Post It 2!'}, {'ttl': 60, 'body': 'Post It 2!'}, ] queue.post(messages) messages = queue.pop(count=2) self.assertIsInstance(messages, iterator._Iterator) self.assertEqual(2, len(list(messages))) remaining = queue.messages(echo=True) self.assertEqual(1, len(list(remaining))) def test_queue_metadata_functional(self): # v1.1 doesn't support set queue metadata pass def test_queue_metadata_reload_functional(self): # v1.1 doesn't support set queue metadata pass class QueuesV2QueueUnitTest(QueuesV1_1QueueUnitTest): def test_message_get(self): pass def test_queue_subscriptions(self): result = { "subscriptions": [{ "source": 'test', "id": "1", "subscriber": 'http://trigger.me', "ttl": 3600, "age": 1800, "confirmed": False, "options": {}}, { "source": 'test', "id": "2", "subscriber": 'http://trigger.you', "ttl": 7200, "age": 1800, "confirmed": False, "options": {}}] } with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(result)) send_method.return_value = resp subscriptions = self.queue.subscriptions() subscriber_list = [s.subscriber for s in list(subscriptions)] self.assertIn('http://trigger.me', subscriber_list) self.assertIn('http://trigger.you', subscriber_list) def test_queue_metadata(self): # checked in "test_queue_metadata_update" pass def test_queue_metadata_update(self): test_metadata = {'type': 'Bank Accounts', 'name': 'test1'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(test_metadata)) send_method.return_value = resp # add 'test_metadata' metadata = self.queue.metadata(new_meta=test_metadata) self.assertEqual(test_metadata, metadata) new_metadata_replace = {'type': 'test', 'name': 'test1'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(new_metadata_replace)) send_method.return_value = resp # repalce 'type' metadata = self.queue.metadata( new_meta=new_metadata_replace) expect_metadata = {'type': 'test', "name": 'test1'} self.assertEqual(expect_metadata, metadata) remove_metadata = {'name': 'test1'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(remove_metadata)) send_method.return_value = resp # remove 'type' metadata = self.queue.metadata(new_meta=remove_metadata) expect_metadata = {"name": 'test1'} self.assertEqual(expect_metadata, metadata) def test_queue_purge(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.purge() # NOTE(flwang): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_queue_purge_messages(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.purge(resource_types=['messages']) self.assertEqual({"resource_types": ["messages"]}, json.loads(send_method.call_args[0][0].content)) class QueuesV2QueueFunctionalTest(QueuesV1_1QueueFunctionalTest): def test_signed_url(self): queue = self.client.queue('test_queue') messages = [{'ttl': 300, 'body': 'Post It!'}] queue.post(messages) self.addCleanup(queue.delete) signature = queue.signed_url() opts = { 'paths': signature['paths'], 'expires': signature['expires'], 'methods': signature['methods'], 'signature': signature['signature'], 'os_project_id': signature['project'], } auth_opts = {'backend': 'signed-url', 'options': opts} conf = {'auth_opts': auth_opts} signed_client = client.Client(self.url, self.version, conf) queue = signed_client.queue('test_queue') [message] = list(queue.messages()) self.assertEqual('Post It!', message.body) def test_queue_subscriptions(self): queue_name = 'test_queue' queue = self.client.queue(queue_name, force_create=True) self.addCleanup(queue.delete) queue._get_transport = mock.Mock(return_value=self.transport) subscription.Subscription(self.client, queue_name, subscriber='http://trigger.me') subscription.Subscription(self.client, queue_name, subscriber='http://trigger.you') get_subscriptions = queue.subscriptions() self.assertIsInstance(get_subscriptions, iterator._Iterator) self.assertEqual(2, len(list(get_subscriptions))) def test_queue_metadata_reload_functional(self): test_metadata = {'type': 'Bank Accounts', 'name': 'test1'} queue = self.client.queue("meta-test", force_create=True) self.addCleanup(queue.delete) queue.metadata(new_meta=test_metadata) # NOTE(flaper87): Overwrite the cached value # but don't clear it. queue._metadata = 'test' expect_metadata = {'type': 'Bank Accounts', 'name': 'test1', '_max_messages_post_size': 262144, '_default_message_ttl': 3600, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None} metadata = queue.metadata(force_reload=True) self.assertEqual(expect_metadata, metadata) def test_queue_metadata_functional(self): queue = self.client.queue("meta-test", force_create=True) self.addCleanup(queue.delete) # add two metadatas test_metadata = {'type': 'Bank Accounts', 'name': 'test1'} queue.metadata(new_meta=test_metadata) # NOTE(flaper87): Clear metadata's cache queue._metadata = None metadata = queue.metadata() expect_metadata = {'type': 'Bank Accounts', 'name': 'test1', '_max_messages_post_size': 262144, '_default_message_ttl': 3600, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None} self.assertEqual(expect_metadata, metadata) # replace 'type', '_default_message_ttl' and add a new one 'age' replace_add_metadata = {'type': 'test', 'name': 'test1', 'age': 13, '_default_message_ttl': 1000} queue.metadata(new_meta=replace_add_metadata) queue._metadata = None metadata = queue.metadata() expect_metadata = {'type': 'test', 'name': 'test1', 'age': 13, '_max_messages_post_size': 262144, '_default_message_ttl': 1000, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None} self.assertEqual(expect_metadata, metadata) # replace 'name', remove 'type', '_default_message_ttl' and add a new # one 'fake'. replace_remove_add_metadata = {'name': 'test2', 'age': 13, 'fake': 'test_fake', } queue.metadata(new_meta=replace_remove_add_metadata) queue._metadata = None metadata = queue.metadata() expect_metadata = {'name': 'test2', 'age': 13, 'fake': 'test_fake', '_max_messages_post_size': 262144, '_default_message_ttl': 3600, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None} self.assertEqual(expect_metadata, metadata) # replace 'name' to empty string and add a new empty dict 'empty_dict'. replace_add_metadata = {'name': '', 'age': 13, 'fake': 'test_fake', 'empty_dict': {} } queue.metadata(new_meta=replace_add_metadata) queue._metadata = None metadata = queue.metadata() expect_metadata = {'name': '', 'age': 13, 'fake': 'test_fake', '_max_messages_post_size': 262144, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None, '_default_message_ttl': 3600, 'empty_dict': {}} self.assertEqual(expect_metadata, metadata) # Delete all metadata. remove_all = {} queue.metadata(new_meta=remove_all) queue._metadata = None metadata = queue.metadata() expect_metadata = {'_max_messages_post_size': 262144, '_default_message_ttl': 3600, '_default_message_delay': 0, '_dead_letter_queue': None, '_dead_letter_queue_messages_ttl': None, '_max_claim_count': None} self.assertEqual(expect_metadata, metadata) python-zaqarclient-1.11.0/zaqarclient/tests/queues/claims.py0000666000175000017500000001602613364112606024271 0ustar zuulzuul00000000000000# Copyright (c) 2014 Rackspace Hosting. # # 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 import time from zaqarclient.queues.v1 import claim from zaqarclient.tests.queues import base from zaqarclient.transport import errors from zaqarclient.transport import response class QueueV1ClaimUnitTest(base.QueuesTestBase): def test_claim(self): result = [{ 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01', 'ttl': 800, 'age': 790, 'body': {'event': 'ActivateAccount', 'mode': 'active'} }, { 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b02', '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(result)) send_method.return_value = resp claimed = self.queue.claim(ttl=60, grace=60) # messages doesn't support len() num_tested = 0 for num, msg in enumerate(claimed): num_tested += 1 self.assertEqual(result[num]['href'], msg.href) self.assertEqual(len(result), num_tested) def test_claim_limit(self): def verify_limit(request): self.assertIn('limit', request.params) self.assertEqual(10, request.params['limit']) # NOTE(flaper87): We don't care about the response here, # fake it. return response.Response(None, "{0: [], 'messages': []}") with mock.patch.object(self.transport, 'send', autospec=True) as send_method: send_method.side_effect = verify_limit self.queue.claim(ttl=60, grace=60, limit=10) def test_claim_get_by_id(self): result = { 'href': '/v1/queues/fizbit/messages/50b68a50d6cb01?claim_id=4524', 'age': 790, 'ttl': 800, 'messages': [{ 'href': '/v1/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(result)) send_method.return_value = resp cl = self.queue.claim(id='5245432') # messages doesn't support len() num_tested = 0 for num, msg in enumerate(cl): num_tested += 1 self.assertEqual(result['messages'][num]['href'], msg.href) self.assertEqual(len(result['messages']), num_tested) def test_claim_update(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.claim(id='5245432').update(ttl=444, grace=987) # NOTE(asalkeld): Nothing to assert here, # just checking our way down to the transport # doesn't crash. def test_claim_delete(self): with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp self.queue.claim(id='4225').delete() # NOTE(asalkeld): Nothing to assert here, # just checking our way down to the transport # doesn't crash. class QueuesV1ClaimFunctionalTest(base.QueuesTestBase): def test_message_claim_functional(self): queue = self.client.queue("test_queue") queue._get_transport = mock.Mock(return_value=self.transport) messages = [{'ttl': 60, 'body': 'Post It 1!'}] queue.post(messages) messages = queue.claim(ttl=120, grace=120) self.assertIsInstance(messages, claim.Claim) self.assertGreaterEqual(len(list(messages)), 0) def test_claim_get_functional(self): queue = self.client.queue("test_queue") queue._get_transport = mock.Mock(return_value=self.transport) res = queue.claim(ttl=100, grace=100) claim_id = res.id cl = queue.claim(id=claim_id) self.assertEqual(claim_id, cl.id) def test_claim_create_delete_functional(self): queue = self.client.queue("test_queue") queue._get_transport = mock.Mock(return_value=self.transport) messages = [{'ttl': 60, 'body': 'Post It 1!'}] queue.post(messages) cl = queue.claim(ttl=120, grace=120) claim_id = cl.id cl.delete() self.assertRaises(errors.ResourceNotFound, queue.claim, id=claim_id) def test_claim_age(self): queue = self.client.queue("test_queue") queue._get_transport = mock.Mock(return_value=self.transport) messages = [{'ttl': 60, 'body': 'image.upload'}] queue.post(messages) res = queue.claim(ttl=100, grace=60) self.assertGreaterEqual(res.age, 0) time.sleep(2) self.assertGreaterEqual(res.age, 2) class QueueV1_1ClaimUnitTest(QueueV1ClaimUnitTest): def test_claim(self): result = [{ 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b01', 'ttl': 800, 'age': 790, 'body': {'event': 'ActivateAccount', 'mode': 'active'} }, { 'href': '/v1/queues/fizbit/messages/50b68a50d6f5b8c8a7c62b02', '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': result})) send_method.return_value = resp claimed = self.queue.claim(ttl=60, grace=60) # messages doesn't support len() num_tested = 0 for num, msg in enumerate(claimed): num_tested += 1 self.assertEqual(result[num]['href'], msg.href) self.assertEqual(len(result), num_tested) class QueuesV1_1ClaimFunctionalTest(QueuesV1ClaimFunctionalTest): pass class QueueV2ClaimUnitTest(QueueV1_1ClaimUnitTest): pass class QueuesV2ClaimFunctionalTest(QueuesV1_1ClaimFunctionalTest): pass python-zaqarclient-1.11.0/zaqarclient/tests/queues/flavor.py0000666000175000017500000001524113364112606024310 0ustar zuulzuul00000000000000# Copyright (c) 2014 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.queues.v1 import iterator from zaqarclient.tests.queues import base from zaqarclient.transport import response class QueuesV1_1FlavorUnitTest(base.QueuesTestBase): def test_flavor_create(self): flavor_data = {'pool_group': 'stomach'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) send_method.return_value = resp # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True flavor = self.client.flavor('tasty', **flavor_data) self.assertEqual('tasty', flavor.name) self.assertEqual('stomach', flavor.pool_group) def test_flavor_get(self): flavor_data = {'name': 'test', 'pool_group': 'stomach'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(flavor_data)) send_method.return_value = resp # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True flavor = self.client.flavor('test') flavor1 = flavor.get() self.assertEqual('test', flavor1['name']) self.assertEqual('stomach', flavor1['pool_group']) def test_flavor_update(self): flavor_data = {'pool_group': 'stomach'} updated_data = {'pool_group': '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_group': 'belly'}) self.assertEqual('belly', flavor.pool_group) def test_flavor_list(self): returned = { 'links': [{ 'rel': 'next', 'href': '/v1.1/flavors?marker=6244-244224-783' }], 'flavors': [{ 'name': 'tasty', 'pool_group': '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_group': 'stomach'} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, None) resp_data = response.Response(None, json.dumps(flavor_data)) send_method.side_effect = iter([resp_data, resp]) # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True flavor = self.client.flavor('tasty', **flavor_data) flavor.delete() # NOTE(flaper87): Nothing to assert here, # just checking our way down to the transport # doesn't crash. class QueuesV1_1FlavorFunctionalTest(base.QueuesTestBase): def test_flavor_create(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_group': 'us'} flavor = self.client.flavor('tasty', **flavor_data) self.addCleanup(flavor.delete) self.assertEqual('tasty', flavor.name) self.assertEqual('us', flavor.pool_group) def test_flavor_get(self): pool_data = {'weight': 10, 'group': 'us', 'uri': 'mongodb://127.0.0.1:27017'} pool = self.client.pool('stomach', **pool_data) self.addCleanup(pool.delete) flavor_data = {'pool_group': 'us'} flavor = self.client.flavor('tasty', **flavor_data) resp_data = flavor.get() self.addCleanup(flavor.delete) self.assertEqual('tasty', resp_data['name']) self.assertEqual('us', resp_data['pool_group']) 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_group': 'us'} flavor = self.client.flavor('tasty', **flavor_data) self.addCleanup(flavor.delete) pool.update({'group': 'belly'}) flavor.update({'pool_group': 'belly'}) self.assertEqual('belly', flavor.pool_group) def test_flavor_list(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_group': 'us'} flavor = self.client.flavor("test_flavor", **flavor_data) self.addCleanup(flavor.delete) flavors = self.client.flavors() self.assertIsInstance(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_group': 'us'} flavor = self.client.flavor('tasty', **flavor_data) flavor.delete() class QueuesV2FlavorUnitTest(QueuesV1_1FlavorUnitTest): pass class QueuesV2FlavorFunctionalTest(QueuesV1_1FlavorFunctionalTest): pass python-zaqarclient-1.11.0/zaqarclient/tests/queues/__init__.py0000666000175000017500000000000013364112606024541 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/queues/subscriptions.py0000666000175000017500000002671113364112606025732 0ustar zuulzuul00000000000000# Copyright (c) 2015 Catalyst IT Ltd. # # 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 import base from zaqarclient.transport import errors from zaqarclient.transport import response class QueuesV2SubscriptionUnitTest(base.QueuesTestBase): def test_subscription_create(self): subscription_data = {'subscriber': 'http://trigger.me', 'ttl': 3600} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: create_resp = response.Response(None, '{"subscription_id": "fake_id"}') get_content = ('{"subscriber": "http://trigger.me","ttl": 3600, ' '"id": "fake_id"}') get_resp = response.Response(None, get_content) send_method.side_effect = iter([create_resp, get_resp]) # NOTE(flwang): This will call # ensure exists in the client instance # since auto_create's default is True subscription = self.client.subscription('beijing', **subscription_data) self.assertEqual('http://trigger.me', subscription.subscriber) self.assertEqual(3600, subscription.ttl) self.assertEqual('fake_id', subscription.id) def test_subscription_create_duplicate_throws_conflicterror(self): subscription_data = {'subscriber': 'http://trigger.me', 'ttl': 3600} with mock.patch.object(self.transport.client, 'request', autospec=True) as request_method: class FakeRawResponse(object): def __init__(self): self.text = '' self.headers = {} self.status_code = 409 request_method.return_value = FakeRawResponse() self.assertRaises(errors.ConflictError, self.client.subscription, 'beijing', **subscription_data) def test_subscription_update(self): subscription_data = {'subscriber': 'http://trigger.me', 'ttl': 3600} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: create_resp = response.Response(None, '{"subscription_id": "fake_id"}') get_content = ('{"subscriber": "http://trigger.me","ttl": 3600, ' '"id": "fake_id"}') get_resp = response.Response(None, get_content) update_content = json.dumps({'subscriber': 'fake_subscriber'}) update_resp = response.Response(None, update_content) send_method.side_effect = iter([create_resp, get_resp, update_resp]) # NOTE(flwang): This will call # ensure exists in the client instance # since auto_create's default is True subscription = self.client.subscription('beijing', **subscription_data) subscription.update({'subscriber': 'fake_subscriber'}) self.assertEqual('fake_subscriber', subscription.subscriber) def test_subscription_delete(self): subscription_data = {'subscriber': 'http://trigger.me', 'ttl': 3600} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: create_resp = response.Response(None, '{"subscription_id": "fake_id"}') get_content = ('{"subscriber": "http://trigger.me","ttl": 3600, ' '"id": "fake_id"}') get_resp = response.Response(None, get_content) send_method.side_effect = iter([create_resp, get_resp, None, errors.ResourceNotFound]) # NOTE(flwang): This will call # ensure exists in the client instance # since auto_create's default is True subscription = self.client.subscription('beijing', **subscription_data) self.assertEqual('http://trigger.me', subscription.subscriber) self.assertEqual(3600, subscription.ttl) self.assertEqual('fake_id', subscription.id) subscription.delete() self.assertRaises(errors.ResourceNotFound, self.client.subscription, 'beijing', **{'id': 'fake_id'}) def test_subscription_get(self): subscription_data = {'subscriber': 'http://trigger.me', 'ttl': 3600} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: resp = response.Response(None, json.dumps(subscription_data)) send_method.return_value = resp # NOTE(flaper87): This will call # ensure exists in the client instance # since auto_create's default is True kwargs = {'id': 'fake_id'} subscription = self.client.subscription('test', **kwargs) self.assertEqual('http://trigger.me', subscription.subscriber) self.assertEqual(3600, subscription.ttl) def test_subscription_list(self): subscription_data = {'subscriptions': [{'source': 'beijing', 'id': '568afabb508f153573f6a56f', 'subscriber': 'http://trigger.me', 'ttl': 3600, 'age': 1800, 'confirmed': False, 'options': {}}, {'source': 'beijing', 'id': '568afabb508f153573f6a56x', 'subscriber': 'http://trigger.you', 'ttl': 7200, 'age': 2309, 'confirmed': True, 'options': {'oh stop': 'triggering'}}]} with mock.patch.object(self.transport, 'send', autospec=True) as send_method: list_resp = response.Response(None, json.dumps(subscription_data)) send_method.side_effect = iter([list_resp]) # NOTE(flwang): This will call # ensure exists in the client instance # since auto_create's default is True subscriptions = list(self.client.subscriptions('beijing')) self.assertEqual(2, len(subscriptions)) subscriber_list = [s.subscriber for s in subscriptions] self.assertIn('http://trigger.me', subscriber_list) self.assertIn('http://trigger.you', subscriber_list) # Let's pick one of the subscriptions and check all of its fields for sub in subscriptions: if sub.subscriber == 'http://trigger.you': self.assertEqual('beijing', sub.queue_name) self.assertEqual('568afabb508f153573f6a56x', sub.id) self.assertEqual(7200, sub.ttl) self.assertEqual({'oh stop': 'triggering'}, sub.options) class QueuesV2SubscriptionFunctionalTest(base.QueuesTestBase): def setUp(self): super(QueuesV2SubscriptionFunctionalTest, self).setUp() self.queue_name = 'beijing' queue = self.client.queue(self.queue_name, force_create=True) self.addCleanup(queue.delete) subscription_data_1 = {'subscriber': 'http://trigger.me', 'ttl': 3600} subscription_data_2 = {'subscriber': 'http://trigger.he', 'ttl': 7200, 'options': {'check everything': True}} self.subscription_1 = self.client.subscription(self.queue_name, **subscription_data_1) self.addCleanup(self.subscription_1.delete) self.subscription_2 = self.client.subscription(self.queue_name, **subscription_data_2) self.addCleanup(self.subscription_2.delete) def test_subscription_create(self): self.assertEqual('http://trigger.me', self.subscription_1.subscriber) self.assertEqual(3600, self.subscription_1.ttl) self.assertEqual('http://trigger.he', self.subscription_2.subscriber) self.assertEqual(7200, self.subscription_2.ttl) def test_subscription_create_duplicate(self): subscription_data_2 = {'subscriber': 'http://trigger.he', 'ttl': 7200, 'options': {'check everything': True}} # Now Zaqar support subscription confirm, when users try to recreate a # subscription which is already created and not confirmed, Zaqar will # try to reconfirm this subscription and return 201 instead of 409. new_subscription = self.client.subscription('beijing', **subscription_data_2) self.assertEqual(new_subscription.id, self.subscription_2.id) def test_subscription_update(self): sub = self.client.subscription(self.queue_name, auto_create=False, **{'id': self.subscription_1.id}) data = {'subscriber': 'http://trigger.ok', 'ttl': 1000} sub.update(data) self.assertEqual('http://trigger.ok', sub.subscriber) self.assertEqual(1000, sub.ttl) def test_subscription_delete(self): self.subscription_1.delete() subscription_data = {'id': self.subscription_1.id} self.assertRaises(errors.ResourceNotFound, self.client.subscription, self.queue_name, **subscription_data) def test_subscription_get(self): kwargs = {'id': self.subscription_1.id} subscription_get = self.client.subscription(self.queue_name, **kwargs) self.assertEqual('http://trigger.me', subscription_get.subscriber) self.assertEqual(3600, subscription_get.ttl) def test_subscription_list(self): subscriptions = self.client.subscriptions(self.queue_name) subscriptions = list(subscriptions) self.assertEqual(2, len(subscriptions)) subscriber_list = [s.subscriber for s in subscriptions] self.assertIn('http://trigger.me', subscriber_list) self.assertIn('http://trigger.he', subscriber_list) # Let's pick one of the subscriptions and check all of its fields for sub in subscriptions: if sub.subscriber == 'http://trigger.he': self.assertEqual('beijing', sub.queue_name) self.assertEqual(self.subscription_2.id, sub.id) self.assertEqual(7200, sub.ttl) self.assertEqual({'check everything': True}, sub.options) python-zaqarclient-1.11.0/zaqarclient/tests/queues/messages.py0000666000175000017500000000422413364112606024625 0ustar zuulzuul00000000000000# 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 import base from zaqarclient.transport import response class QueuesV1MessageUnitTest(base.QueuesTestBase): def test_message_delete(self): returned = { 'href': '/v1/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': '/v1/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()) class QueuesV2MessageUnitTest(QueuesV1MessageUnitTest): def test_message_delete_with_claim(self): pass def test_message_delete(self): pass python-zaqarclient-1.11.0/zaqarclient/tests/queues/health.py0000666000175000017500000000337713364112606024273 0ustar zuulzuul00000000000000# Copyright (c) 2016 Catalyst IT Ltd. # # 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 import base from zaqarclient.transport import response class QueuesV2HealthUnitTest(base.QueuesTestBase): def test_health(self): expect_health = {u'catalog_reachable': True, u'redis': {u'operation_status': {}, u'storage_reachable': True} } with mock.patch.object(self.transport, 'send', autospec=True) as send_method: health_content = json.dumps(expect_health) health_resp = response.Response(None, health_content) send_method.side_effect = iter([health_resp]) health = self.client.health() self.assertEqual(expect_health, health) class QueuesV2HealthFunctionalTest(base.QueuesTestBase): def test_ping(self): # NOTE(flwang): If test env is not pingable, then the test should fail self.assertTrue(self.client.ping()) def test_health(self): health = self.client.health() # NOTE(flwang): If everything is ok, then zaqar server will return a # JSON(dict). self.assertIsInstance(health, dict) python-zaqarclient-1.11.0/zaqarclient/tests/base.py0000666000175000017500000000757013364112606022430 0ustar zuulzuul00000000000000# 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 os import fixtures import openstack.config from six.moves import urllib_parse import testtools _USE_AUTHENTICATION = os.environ.get('ZAQARCLIENT_AUTH_FUNCTIONAL', False) _RUN_FUNCTIONAL = os.environ.get('ZAQARCLIENT_TEST_FUNCTIONAL', _USE_AUTHENTICATION) class TestBase(testtools.TestCase): transport_cls = None is_functional = False def setUp(self): super(TestBase, self).setUp() self.conf = { 'auth_opts': { 'backend': 'noauth', 'options': { 'os_project_id': 'my-project' } } } self.useFixture(fixtures.FakeLogger('zaqar')) # NOTE(kgriffs): Don't monkey-patch stdout since it breaks # debugging with pdb. stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) if not _RUN_FUNCTIONAL and self.is_functional: self.skipTest('Functional tests disabled') elif self.is_functional and _USE_AUTHENTICATION: self._setup_auth_params() def _credentials(self, cloud='devstack-admin'): """Retrieves credentials to run functional tests Credentials are either read via os-client-config from the environment or from a config file ('clouds.yaml'). Environment variables override those from the config file. devstack produces a clouds.yaml with two named clouds - one named 'devstack' which has user privs and one named 'devstack-admin' which has admin privs. This function will default to getting the devstack-admin cloud as that is the current expected behavior. """ os_cfg = openstack.config.OpenStackConfig() try: found = os_cfg.get_one_cloud(cloud=cloud) except Exception: found = os_cfg.get_one_cloud() return found def _setup_auth_params(self): self.creds = self._credentials().get_auth_args() parsed_url = urllib_parse.urlparse(self.creds['auth_url']) auth_url = self.creds['auth_url'] if not parsed_url.path or parsed_url.path == '/': auth_url = urllib_parse.urljoin(self.creds['auth_url'], 'v3') if parsed_url.path == '/identity': auth_url = '%s/v3' % auth_url self.conf['auth_opts']['backend'] = 'keystone' options = {'os_username': self.creds['username'], 'os_user_domain_id': self.creds['user_domain_id'], 'os_password': self.creds['password'], 'os_project_name': self.creds['project_name'], 'os_project_id': '', 'os_project_domain_id': self.creds['project_domain_id'], 'os_auth_url': auth_url} self.conf['auth_opts'].setdefault('options', {}).update(options) def config(self, group=None, **kw): """Override some configuration values. The keyword arguments are the names of configuration options to override and their values. If a group argument is supplied, the overrides are applied to the specified configuration option group. """ parent = (group and self.conf.setdefault(group, {}) or self.conf) parent.update(kw) python-zaqarclient-1.11.0/zaqarclient/tests/transport/0000775000175000017500000000000013364112773023172 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/transport/api.py0000666000175000017500000000174513364112606024321 0ustar zuulzuul00000000000000# 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.transport import api class FakeApi(api.Api): label = 'v1' schema = { 'test_operation': { 'ref': 'test/{name}', 'method': 'GET', 'properties': { 'name': {'type': 'string'}, 'address': {'type': 'string'} }, 'additionalProperties': False, 'required': ['name'] } } python-zaqarclient-1.11.0/zaqarclient/tests/transport/dummy.py0000666000175000017500000000130213364112606024670 0ustar zuulzuul00000000000000# 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.transport import base class DummyTransport(base.Transport): def send(self, request): pass python-zaqarclient-1.11.0/zaqarclient/tests/transport/__init__.py0000666000175000017500000000000013364112606025266 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/__init__.py0000666000175000017500000000000013364112606023232 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/mock/0000775000175000017500000000000013364112773022067 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/tests/mock/message.py0000666000175000017500000000153013364112606024061 0ustar zuulzuul00000000000000# 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. """Easy creation of mock Zaqar message replies.""" def message(href='/v1/queues/dgq/messages/w78sdwsqdsib', ttl=0, age=0, body=None): body = body or {} return { 'href': href, 'ttl': ttl, 'age': age, 'body': body } python-zaqarclient-1.11.0/zaqarclient/tests/mock/__init__.py0000666000175000017500000000000013364112606024163 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/auth/0000775000175000017500000000000013364112773020735 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/auth/signed_url.py0000666000175000017500000000255413364112606023445 0ustar zuulzuul00000000000000# Copyright (c) 2016 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.auth import base class SignedURLAuth(base.AuthBackend): """Authenticate using signature. The returned client will only work on one dedicated queue which has been signed. :params conf: A dictionary with the signed URL data: - expires - methods - paths - signature - os_project_id :type conf: `dict` """ def authenticate(self, api_version, request): """Set the necessary headers on the request.""" request.headers['URL-Expires'] = self.conf['expires'] request.headers['URL-Methods'] = ','.join(self.conf['methods']) request.headers['URL-Paths'] = ','.join(self.conf['paths']) request.headers['URL-Signature'] = self.conf['signature'] return request python-zaqarclient-1.11.0/zaqarclient/auth/base.py0000666000175000017500000000253613364112606022224 0ustar zuulzuul00000000000000# 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 abc import six @six.add_metaclass(abc.ABCMeta) class AuthBackend(object): def __init__(self, conf): self.conf = conf @abc.abstractmethod def authenticate(self, api_version, request): """Authenticates the user in the selected backend. Auth backends will have to manipulate the request and prepare it to send the auth information back to Zaqar's instance. :params api_version: Zaqar's API version. :params request: Request Spec instance that can be manipulated by the backend if the authentication succeeds. :returns: The modified request spec. """ class NoAuth(AuthBackend): """No Auth Plugin.""" def authenticate(self, api_version, req): return req python-zaqarclient-1.11.0/zaqarclient/auth/__init__.py0000666000175000017500000000236413364112606023050 0ustar zuulzuul00000000000000# 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.auth import base from zaqarclient.auth import keystone from zaqarclient.auth import signed_url _BACKENDS = { 'noauth': base.NoAuth, 'keystone': keystone.KeystoneAuth, 'signed-url': signed_url.SignedURLAuth, } def get_backend(backend='keystone', options=None): """Loads backend `auth_backend` :params backend: The backend name to load. Default: `keystone` :type backend: `six.string_types` :param options: Options to pass to the Auth backend. Refer to the backend for more info. :type options: `dict` """ if options is None: options = {} backend = _BACKENDS[backend](options) return backend python-zaqarclient-1.11.0/zaqarclient/auth/keystone.py0000666000175000017500000002002413364112606023143 0ustar zuulzuul00000000000000# 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 six.moves.urllib.parse as urlparse from keystoneauth1 import discover from keystoneauth1 import exceptions as ka_exc from keystoneauth1.identity import v2 as v2_auth from keystoneauth1.identity import v3 as v3_auth from keystoneauth1 import session from zaqarclient.auth import base from zaqarclient import errors # NOTE(flaper87): Some of the code below # was brought to you by the very unique # work of ceilometerclient and glanceclient. class KeystoneAuth(base.AuthBackend): """Keystone Auth backend :params conf: A dictionary with Keystone's custom parameters: - os_username - os_password - os_project_id - os_project_name - os_auth_url - os_auth_token - os_region_name - os_service_type - os_endpoint_type :type conf: `dict` """ def _get_keystone_session(self, **kwargs): cacert = kwargs.pop('cacert', None) cert = kwargs.pop('cert', None) key = kwargs.pop('key', None) insecure = kwargs.pop('insecure', False) auth_url = kwargs.pop('auth_url', None) project_id = kwargs.pop('project_id', None) project_name = kwargs.pop('project_name', None) token = kwargs.get('token') if insecure: verify = False else: verify = cacert or True if cert and key: # passing cert and key together is deprecated in favour of the # requests lib form of having the cert and key as a tuple cert = (cert, key) # create the keystone client session ks_session = session.Session(verify=verify, cert=cert) v2_auth_url, v3_auth_url = self._discover_auth_versions(ks_session, auth_url) username = kwargs.pop('username', None) user_id = kwargs.pop('user_id', None) user_domain_name = kwargs.pop('user_domain_name', None) user_domain_id = kwargs.pop('user_domain_id', None) project_domain_name = kwargs.pop('project_domain_name', None) project_domain_id = kwargs.pop('project_domain_id', None) auth = None use_domain = (user_domain_id or user_domain_name or project_domain_id or project_domain_name) use_v3 = v3_auth_url and (use_domain or (not v2_auth_url)) use_v2 = v2_auth_url and not use_domain if use_v3 and token: auth = v3_auth.Token( v3_auth_url, token=token, project_name=project_name, project_id=project_id, project_domain_name=project_domain_name, project_domain_id=project_domain_id) elif use_v2 and token: auth = v2_auth.Token( v2_auth_url, token=token, tenant_id=project_id, tenant_name=project_name) elif use_v3: # The auth_url as v3 specified # e.g. http://no.where:5000/v3 # Keystone will return only v3 as viable option auth = v3_auth.Password( v3_auth_url, username=username, password=kwargs.pop('password', None), user_id=user_id, user_domain_name=user_domain_name, user_domain_id=user_domain_id, project_name=project_name, project_id=project_id, project_domain_name=project_domain_name, project_domain_id=project_domain_id) elif use_v2: # The auth_url as v2 specified # e.g. http://no.where:5000/v2.0 # Keystone will return only v2 as viable option auth = v2_auth.Password( v2_auth_url, username, kwargs.pop('password', None), tenant_id=project_id, tenant_name=project_name) else: raise errors.ZaqarError('Unable to determine the Keystone version ' 'to authenticate with using the given ' 'auth_url.') ks_session.auth = auth return ks_session def _discover_auth_versions(self, session, auth_url): # Discover the API versions the server is supporting based on the # given URL v2_auth_url = None v3_auth_url = None try: ks_discover = discover.Discover(session=session, url=auth_url) v2_auth_url = ks_discover.url_for('2.0') v3_auth_url = ks_discover.url_for('3.0') except ka_exc.DiscoveryFailure: raise except ka_exc.ClientException: # Identity service may not support discovery. In that case, # try to determine version from auth_url url_parts = urlparse.urlparse(auth_url) (scheme, netloc, path, params, query, fragment) = url_parts path = path.lower() if path.startswith('/v3'): v3_auth_url = auth_url elif path.startswith('/v2'): v2_auth_url = auth_url else: raise errors.ZaqarError('Unable to determine the Keystone ' 'version to authenticate with ' 'using the given auth_url.') return v2_auth_url, v3_auth_url def _get_endpoint(self, ks_session, **kwargs): """Get an endpoint using the provided keystone session.""" # Set service specific endpoint types endpoint_type = kwargs.get('endpoint_type') or 'publicURL' service_type = kwargs.get('service_type') or 'messaging' region_name = kwargs.get('region_name') endpoint = ks_session.get_endpoint(service_type=service_type, interface=endpoint_type, region_name=region_name) return endpoint def authenticate(self, api_version, request): """Get an authtenticated client using credentials in the keyword args. :param api_version: the API version to use ('1' or '2') :param request: The request spec instance to modify with the auth information. """ def get_options(k): return self.conf.get(k, self.conf.get("os_%s" % k)) token = get_options('auth_token') if not token or not request.endpoint: ks_kwargs = {} keys = ("username", "password", "project_id", "project_name", "auth_url", "insecure", "cacert", "region_name", "user_domain_name", "user_domain_id", "project_domain_name", "project_domain_id") for k in keys: ks_kwargs.update({k: get_options(k)}) ks_session = (request.session or self._get_keystone_session(**ks_kwargs)) if not token: token = ks_session.get_token() if not request.endpoint: request.endpoint = self._get_endpoint(ks_session, **ks_kwargs) # NOTE(flaper87): Update the request spec # with the final token. request.headers['X-Auth-Token'] = token # NOTE(flwang): We also need to apply the insecure and cacert when # talking with Zaqar server. request.verify = not get_options('insecure') request.cert = get_options('cacert') return request python-zaqarclient-1.11.0/zaqarclient/transport/0000775000175000017500000000000013364112773022030 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/transport/api.py0000666000175000017500000000515313364112606023154 0ustar zuulzuul00000000000000# 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 jsonschema from jsonschema import validators from zaqarclient import errors class Api(object): schema = {} label = None validators = {} def is_supported(self, operation): """Returns `True` if `operation` is supported :param operation: The operation to check on. :type operation: `six.text_type` :rtype: bool """ return operation in self.schema def get_schema(self, operation): """Returns the schema for an operation :param operation: Operation for which params need to be validated. :type operation: `six.text_type` :returns: Operation's schema :rtype: dict :raises: `errors.InvalidOperation` if the operation does not exist """ try: return self.schema[operation] except KeyError: # TODO(flaper87): gettext support msg = '{0} is not a valid operation'.format(operation) raise errors.InvalidOperation(msg) def validate(self, operation, params): """Validates the request data This method relies on jsonschema and exists just as a way for third-party transport to validate the request. It's not recommended to validate every request since they are already validated server side. :param operation: Operation's for which params need to be validated. :type operation: `six.text_type` :param params: Params to validate :type params: dict :returns: True if the schema is valid, False otherwise :raises: `errors.InvalidOperation` if the operation does not exist """ if operation not in self.validators: schema = self.get_schema(operation) self.validators[operation] = validators.Draft4Validator(schema) try: self.validators[operation].validate(params) except jsonschema.ValidationError: # TODO(flaper87): Log error return False return True python-zaqarclient-1.11.0/zaqarclient/transport/errors.py0000666000175000017500000000506413364112606023720 0ustar zuulzuul00000000000000# 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. """ Errors below must be used to translate transport specific errors to Zaqar errors. For example, HTTP 404s should be raised as `ResourceNotFound` """ from zaqarclient import errors __all__ = ['TransportError', 'ResourceNotFound', 'MalformedRequest', 'UnauthorizedError', 'ForbiddenError', 'ServiceUnavailableError', 'InternalServerError', 'ConflictError'] class TransportError(errors.ZaqarError): """Base class for all transport errors.""" code = None def __init__(self, title=None, description=None, text=None): msg = 'Error response from Zaqar. Code: {0}.'.format(self.code) if title: msg += ' Title: {0}.'.format(title) if description: msg += ' Description: {0}.'.format(description) if text: msg += ' Text: {0}.'.format(text) super(TransportError, self).__init__(msg) class ResourceNotFound(TransportError): """Indicates that a resource is missing This error maps to HTTP's 404 """ code = 404 class MalformedRequest(TransportError): """Indicates that a request is malformed This error maps to HTTP's 400 """ code = 400 class UnauthorizedError(TransportError): """Indicates that a request was not authenticated This error maps to HTTP's 401 """ code = 401 class ForbiddenError(TransportError): """Indicates that a request is forbidden to access the particular resource This error maps to HTTP's 403 """ code = 403 class InternalServerError(TransportError): """Indicates that the server encountered an unexpected situation This error maps to HTTP's 500 """ code = 500 class ServiceUnavailableError(TransportError): """Indicates that the server was unable to service the request This error maps to HTTP's 503 """ code = 503 class ConflictError(TransportError): """Indicates that the server was unable to service the request This error maps to HTTP's 409 """ code = 409 python-zaqarclient-1.11.0/zaqarclient/transport/http.py0000666000175000017500000001104613364112606023360 0ustar zuulzuul00000000000000# 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 distutils import version import json from oslo_utils import importutils from zaqarclient.common import http from zaqarclient.transport import base from zaqarclient.transport import response osprofiler_web = importutils.try_import("osprofiler.web") class HttpTransport(base.Transport): def __init__(self, options): super(HttpTransport, self).__init__(options) self.client = http.Client() def _prepare(self, request): if not request.api: return request.endpoint, 'GET', request # TODO(flaper87): Validate if the user # explicitly wants so. Validation must # happen before any other operation here. # request.validate() schema = {} ref_params = {} ref = request.ref if request.operation: schema = request.api.get_schema(request.operation) ref = ref or schema.get('ref', '') # FIXME(flaper87): We expect the endpoint # to have the API version label already, # however in a follow-your-nose implementation # it should be the other way around. ref = ref.lstrip('/' + request.api.label) for param in list(request.params.keys()): if '{{{0}}}'.format(param) in ref: value = request.params.pop(param) # NOTE(flaper87): Zaqar API parses # sequences encoded as '1,2,3,4'. Let's # encode lists, tuples and sets before # sending them to the server. if isinstance(value, (list, tuple, set)): value = ','.join(value) ref_params[param] = value url = '{0}/{1}/{2}'.format(request.endpoint.rstrip('/'), request.api.label, ref.format(**ref_params)) return url, schema.get('method', 'GET'), request def send(self, request): url, method, request = self._prepare(request) # NOTE(flape87): Do not modify # request's headers directly. headers = request.headers.copy() if (request.operation == 'queue_update' and (version.LooseVersion(request.api.label) >= version.LooseVersion('v2'))): headers['content-type'] = \ 'application/openstack-messaging-v2.0-json-patch' else: headers['content-type'] = 'application/json' if osprofiler_web: headers.update(osprofiler_web.get_trace_id_headers()) if request.verify: if request.cert: verify = request.cert else: verify = True else: verify = False resp = self.client.request(method, url=url, params=request.params, headers=headers, data=request.content, verify=verify) if resp.status_code in self.http_to_zaqar: kwargs = {} try: error_body = json.loads(resp.text) kwargs['title'] = error_body['title'] kwargs['description'] = error_body['description'] except Exception: # TODO(flaper87): Log this exception # but don't stop raising the corresponding # exception # Note(Eva-i): most of the error responses from Zaqar have # dict with title and description in their bodies. If it's not # the case, let's just show body text. kwargs['text'] = resp.text raise self.http_to_zaqar[resp.status_code](**kwargs) # NOTE(flaper87): This reads the whole content # and will consume any attempt of streaming. return response.Response(request, resp.text, headers=resp.headers, status_code=resp.status_code) python-zaqarclient-1.11.0/zaqarclient/transport/base.py0000666000175000017500000000244713364112606023320 0ustar zuulzuul00000000000000# 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 abc import six from zaqarclient.transport import errors @six.add_metaclass(abc.ABCMeta) class Transport(object): # common HTTP codes used by multiple transports http_to_zaqar = { 400: errors.MalformedRequest, 401: errors.UnauthorizedError, 403: errors.ForbiddenError, 404: errors.ResourceNotFound, 409: errors.ConflictError, 500: errors.InternalServerError, 503: errors.ServiceUnavailableError } def __init__(self, options): self.options = options @abc.abstractmethod def send(self, request): """Returns the response. :returns: The final response :rtype: `zaqarclient.transport.response.Response` """ python-zaqarclient-1.11.0/zaqarclient/transport/request.py0000666000175000017500000001121713364112606024071 0ustar zuulzuul00000000000000# Copyright (c) 2013 Rackspace, Inc. # 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 from stevedore import driver from zaqarclient import auth from zaqarclient import errors def prepare_request(auth_opts=None, data=None, **kwargs): """Prepares a request This method takes care of authentication and all other steps in the preparation chain. The request returned by this call is ready to be sent to the server. :param auth_opts: Auth parameters :type auth_opts: `dict` :param data: Optional data to send along with the request. If data is not None, it'll be serialized. :type data: Any primitive type that is json-serializable. :param kwargs: Anything accepted by `Request` :returns: A `Request` instance ready to be sent. :rtype: `Request` """ req = Request(**kwargs) auth_backend = auth.get_backend(**(auth_opts or {})) req = auth_backend.authenticate(kwargs.get('api'), req) option = auth_opts.get('options', {}) # TODO(wangxiyuan): To keep backwards compatibility, we leave # "os_project_id" here. Remove it in the next release. project_id = option.get('os_project_id', option.get('project_id')) # Let's add project id header, only if it will have non-empty value. if project_id: req.headers['X-Project-Id'] = project_id # In case of noauth backend and no specified project id, the default # project id will be added as header. if ('X-Project-Id' not in req.headers and auth_opts.get("backend") == "noauth"): req.headers['X-Project-Id'] = "fake_project_id_for_noauth" if data is not None: req.content = json.dumps(data) return req class Request(object): """General data for a Zaqar request The idea is to be declarative i.e. specify *what* is desired. It's up to the respective transport to turn this into a layer-specific request. *NOTE:* This implementation is not definitive and may change. :param endpoint: Server's endpoint :type endpoint: str :param operation: Operation to issue on the endpoint, i.e: - get_queues - get_messages :type operation: str :param content: Request's body. Default: None :type content: str :param params: Query string params. Default: None :type params: dict :param headers: Request headers. Default: None :type headers: dict :param api: Api entry point. i.e: 'queues.v1' :type api: `six.text_type`. :param verify: If verify the SSL cert :type verify: bool :param cert: certificate of SSL :type cert: `six.text_type` :param session: Keystone session :type session: keystone session object """ def __init__(self, endpoint='', operation='', ref='', content=None, params=None, headers=None, api=None, verify=True, cert=None, session=None): self._api = None # ensure that some values like "v1.0" could work as "v1" self._api_mod = None if api and int(api) == api: self._api_mod = 'queues.v' + str(int(api)) elif api: self._api_mod = 'queues.v' + str(api) self.endpoint = endpoint self.operation = operation self.ref = ref self.content = content self.params = params or {} self.headers = headers or {} self.verify = verify self.cert = cert self.session = session @property def api(self): if not self._api and self._api_mod: try: namespace = 'zaqarclient.api' mgr = driver.DriverManager(namespace, self._api_mod, invoke_on_load=True) self._api = mgr.driver except RuntimeError as ex: raise errors.DriverLoadFailure(self._api_mod, ex) return self._api def validate(self): """Validation shortcut Refer to `transport.api.Api.validate` for more information about this method. """ return self.api.validate(params=self.params, content=self.content) python-zaqarclient-1.11.0/zaqarclient/transport/ws.py0000666000175000017500000001146713364112606023041 0ustar zuulzuul00000000000000# Copyright 2016 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 from oslo_log import log as logging from oslo_utils import importutils from oslo_utils import uuidutils from zaqarclient.transport import base from zaqarclient.transport import request from zaqarclient.transport import response websocket = importutils.try_import('websocket') LOG = logging.getLogger(__name__) class WebsocketTransport(base.Transport): """Zaqar websocket transport. *NOTE:* Zaqar's websocket interface does not yet appear to work well with parameters. Until it does the websocket transport may not integrate with all of zaqarclients higherlevel request. Even so... websockets today is still quite usable and use of the transport via lower level API's in zaqarclient work quite nicely. Example: conf = { 'auth_opts': { 'backend': 'keystone', 'options': { 'os_auth_token': ks.auth_token, 'os_project_id': CONF.zaqar.project_id } } } endpoint = 'ws://172.19.0.3:9000' with transport.get_transport_for(endpoint, options=conf) as ws: req = request.Request(endpoint, 'queue_create', content=json.dumps({'queue_name': 'foo'})) resp = ws.send(req) """ def __init__(self, options): super(WebsocketTransport, self).__init__(options) option = options['auth_opts']['options'] # TODO(wangxiyuan): To keep backwards compatibility, we leave # "os_project_id" here. Remove it in the next release. self._project_id = option.get('os_project_id', option.get('project_id')) self._token = options['auth_opts']['options']['os_auth_token'] self._websocket_client_id = None self._ws = None def _init_client(self, endpoint): """Initialize a websocket transport client. :param endpoint: The websocket endpoint. Example: ws://127.0.0.1:9000/. Required. :type endpoint: string """ self._websocket_client_id = uuidutils.generate_uuid() LOG.debug('Instantiating messaging websocket client: %s', endpoint) self._ws = self._create_connection(endpoint) auth_req = request.Request(endpoint, 'authenticate', headers={'X-Auth-Token': self._token}) self.send(auth_req) def _create_connection(self, endpoint): return websocket.create_connection(endpoint) def send(self, request): if not self._ws: self._init_client(request.endpoint) headers = request.headers.copy() headers.update({ 'Client-ID': self._websocket_client_id, 'X-Project-ID': self._project_id }) msg = {'action': request.operation, 'headers': headers} if request.content: msg['body'] = json.loads(request.content) # NOTE(dprince): Zaqar websockets do not yet seem to support params?! # Users of this protocol will need to send everything in the body. if request.params: LOG.warning('Websocket transport does not yet support params.') self._ws.send(json.dumps(msg)) ret = self.recv() resp = response.Response(request, json.dumps(ret.get('body', '')), headers=ret['headers'], status_code=int(ret['headers']['status'])) if resp.status_code in self.http_to_zaqar: kwargs = {} try: error_body = json.loads(resp.content) kwargs['title'] = 'Websocket Transport Error' kwargs['description'] = error_body['error'] except Exception: kwargs['text'] = resp.content raise self.http_to_zaqar[resp.status_code](**kwargs) return resp def recv(self): return json.loads(self._ws.recv()) def cleanup(self): if self._ws: self._ws.close() self._ws = None def __enter__(self): """Return self to allow usage as a context manager""" return self def __exit__(self, *exc): """Call cleanup when exiting the context manager""" self.cleanup() python-zaqarclient-1.11.0/zaqarclient/transport/__init__.py0000666000175000017500000000426613364112606024146 0ustar zuulzuul00000000000000# 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 six from six.moves.urllib import parse from stevedore import driver from zaqarclient import errors as _errors def get_transport(transport='http', version=1, options=None): """Gets a transport and returns it. :param transport: Transport name. Default: http :type transport: `six.string_types` :param version: Version of the target transport. Default: 1 :type version: int :returns: A `Transport` instance. :rtype: `zaqarclient.transport.Transport` """ entry_point = '{0}.v{1}'.format(transport, version) try: namespace = 'zaqarclient.transport' mgr = driver.DriverManager(namespace, entry_point, invoke_on_load=True, invoke_args=[options]) except RuntimeError as ex: raise _errors.DriverLoadFailure(entry_point, ex) return mgr.driver def get_transport_for(url_or_request, version=1, options=None): """Gets a transport for a given url. An example transport URL might be:: zmq://example.org:8888/v1/ :param url_or_request: a transport URL :type url_or_request: `six.string_types` or `zaqarclient.transport.request.Request` :param version: Version of the target transport. :type version: int :returns: A `Transport` instance. :rtype: `zaqarclient.transport.Transport` """ url = url_or_request if not isinstance(url_or_request, six.string_types): url = url_or_request.endpoint parsed = parse.urlparse(url) return get_transport(parsed.scheme, version, options) python-zaqarclient-1.11.0/zaqarclient/transport/response.py0000666000175000017500000000347013364112606024241 0ustar zuulzuul00000000000000# 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 class Response(object): """Common response class for Zaqarclient. All `zaqarclient.transport.base.Transport` implementations will return this to the higher level API which will then build an object out of it. :param request: The request sent to the server. :type: `zaqarclient.transport.request.Request` :param content: Response's content :type: `six.string_types` :param headers: Optional headers returned in the response. :type: dict :param status_code: Optional status_code returned in the response. :type: `int` """ __slots__ = ('request', 'content', 'headers', 'status_code', '_deserialized') def __init__(self, request, content, headers=None, status_code=None): self.request = request self.content = content self.headers = headers or {} self.status_code = status_code self._deserialized = None @property def deserialized_content(self): try: if not self._deserialized and self.content: self._deserialized = json.loads(self.content) return self._deserialized except ValueError as ex: print("Response is not a JSON object.", ex) return None python-zaqarclient-1.11.0/zaqarclient/version.py0000666000175000017500000000244513364112606022035 0ustar zuulzuul00000000000000# Copyright (c) 2013 Red Hat, Inc. # Copyright 2012 OpenStack LLC # # 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 pbr.version import pkg_resources version_info = pbr.version.VersionInfo('python-zaqarclient') try: # First, try to get our version out of PKG-INFO. If we're installed, # this'll let us find our version without pulling in pbr. After all, if # we're installed on a system, we're not in a Git-managed source tree, so # pbr doesn't really buy us anything. version_string = pkg_resources.get_provider( pkg_resources.Requirement.parse('python-zaqarclient')).version except pkg_resources.DistributionNotFound: # No PKG-INFO? We're probably running from a checkout, then. Let pbr do # its thing to figure out a version number. version_string = str(version_info) python-zaqarclient-1.11.0/zaqarclient/common/0000775000175000017500000000000013364112773021264 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/common/http.py0000666000175000017500000000364513364112606022622 0ustar zuulzuul00000000000000# 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 requests class Client(object): def __init__(self, *args, **kwargs): self.session = requests.session(*args, **kwargs) def request(self, *args, **kwargs): """Raw request.""" return self.session.request(*args, **kwargs) def get(self, *args, **kwargs): """Does http GET.""" return self.session.get(*args, **kwargs) def head(self, *args, **kwargs): """Does http HEAD.""" return self.session.head(*args, **kwargs) def option(self, *args, **kwargs): """Does http OPTION.""" return self.session.option(*args, **kwargs) def post(self, *args, **kwargs): """Does http POST.""" if "data" in kwargs: kwargs['data'] = json.dumps(kwargs["data"]) return self.session.post(*args, **kwargs) def put(self, *args, **kwargs): """Does http PUT.""" if "data" in kwargs: kwargs['data'] = json.dumps(kwargs["data"]) return self.session.put(*args, **kwargs) def delete(self, *args, **kwargs): """Does http DELETE.""" return self.session.delete(*args, **kwargs) def patch(self, *args, **kwargs): """Does http PATCH.""" if "data" in kwargs: kwargs['data'] = json.dumps(kwargs["data"]) return self.session.patch(*args, **kwargs) python-zaqarclient-1.11.0/zaqarclient/common/decorators.py0000666000175000017500000000420013364112606023774 0ustar zuulzuul00000000000000# 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 functools from zaqarclient import errors def version(min_version, max_version=None): min_version = float(min_version) max_version = max_version and float(max_version) error_msg = ('Method %(name)s is supported from version %(min)s ' 'to %(max)s') def method(meth): @functools.wraps(meth) def wrapper(self, *args, **kwargs): if (self.api_version < min_version or (max_version and self.api_version > max_version)): msg = error_msg % dict(name=str(meth), min=min_version, max=max_version or 'latest') raise errors.UnsupportedVersion(msg) return meth(self, *args, **kwargs) return wrapper return method def lazy_property(write=False, delete=True): """Creates a lazy property. :param write: Whether this property is "writable" :param delete: Whether this property can be deleted. """ def wrapper(fn): attr_name = '_lazy_' + fn.__name__ def getter(self): if not hasattr(self, attr_name): setattr(self, attr_name, fn(self)) return getattr(self, attr_name) def setter(self, value): setattr(self, attr_name, value) def deleter(self): delattr(self, attr_name) return property(fget=getter, fset=write and setter, fdel=delete and deleter, doc=fn.__doc__) return wrapper python-zaqarclient-1.11.0/zaqarclient/common/__init__.py0000666000175000017500000000000013364112606023360 0ustar zuulzuul00000000000000python-zaqarclient-1.11.0/zaqarclient/__init__.py0000666000175000017500000000126413364112606022105 0ustar zuulzuul00000000000000# Copyright 2017 Huawei, Inc. All rights reserved. # # 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 version __version__ = version.version_string python-zaqarclient-1.11.0/python_zaqarclient.egg-info/0000775000175000017500000000000013364112773023067 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/python_zaqarclient.egg-info/requires.txt0000664000175000017500000000026513364112773025472 0ustar zuulzuul00000000000000pbr!=2.1.0,>=2.0.0 requests>=2.14.2 six>=1.10.0 stevedore>=1.20.0 jsonschema<3.0.0,>=2.6.0 oslo.i18n>=3.15.3 oslo.log>=3.36.0 oslo.utils>=3.33.0 keystoneauth1>=3.4.0 osc-lib>=1.8.0 python-zaqarclient-1.11.0/python_zaqarclient.egg-info/entry_points.txt0000664000175000017500000001243313364112773026370 0ustar zuulzuul00000000000000[openstack.cli.extension] messaging = zaqarclient.queues.cli [openstack.messaging.v1] claim_create = zaqarclient.queues.v1.cli:CreateClaim claim_query = zaqarclient.queues.v1.cli:QueryClaim claim_release = zaqarclient.queues.v1.cli:ReleaseClaim claim_renew = zaqarclient.queues.v1.cli:RenewClaim messaging_flavor_create = zaqarclient.queues.v1.cli:CreateFlavor messaging_flavor_delete = zaqarclient.queues.v1.cli:DeleteFlavor messaging_flavor_list = zaqarclient.queues.v1.cli:ListFlavors messaging_flavor_show = zaqarclient.queues.v1.cli:ShowFlavor messaging_flavor_update = zaqarclient.queues.v1.cli:UpdateFlavor pool_create = zaqarclient.queues.v1.cli:CreatePool pool_delete = zaqarclient.queues.v1.cli:DeletePool pool_list = zaqarclient.queues.v1.cli:ListPools pool_show = zaqarclient.queues.v1.cli:ShowPool pool_update = zaqarclient.queues.v1.cli:UpdatePool queue_create = zaqarclient.queues.v1.cli:CreateQueue queue_delete = zaqarclient.queues.v1.cli:DeleteQueue queue_exists = zaqarclient.queues.v1.cli:CheckQueueExistence queue_get_metadata = zaqarclient.queues.v1.cli:GetQueueMetadata queue_list = zaqarclient.queues.v1.cli:ListQueues queue_set_metadata = zaqarclient.queues.v1.cli:SetQueueMetadata queue_stats = zaqarclient.queues.v1.cli:GetQueueStats [openstack.messaging.v2] claim_create = zaqarclient.queues.v2.cli:OldCreateClaim claim_query = zaqarclient.queues.v2.cli:OldQueryClaim claim_release = zaqarclient.queues.v2.cli:OldReleaseClaim claim_renew = zaqarclient.queues.v2.cli:OldRenewClaim message_list = zaqarclient.queues.v2.cli:OldListMessages message_post = zaqarclient.queues.v2.cli:OldPostMessages messaging_claim_create = zaqarclient.queues.v2.cli:CreateClaim messaging_claim_query = zaqarclient.queues.v2.cli:QueryClaim messaging_claim_release = zaqarclient.queues.v2.cli:ReleaseClaim messaging_claim_renew = zaqarclient.queues.v2.cli:RenewClaim messaging_flavor_create = zaqarclient.queues.v2.cli:CreateFlavor messaging_flavor_delete = zaqarclient.queues.v2.cli:DeleteFlavor messaging_flavor_list = zaqarclient.queues.v2.cli:ListFlavors messaging_flavor_show = zaqarclient.queues.v2.cli:ShowFlavor messaging_flavor_update = zaqarclient.queues.v2.cli:UpdateFlavor messaging_health = zaqarclient.queues.v2.cli:Health messaging_homedoc = zaqarclient.queues.v2.cli:HomeDoc messaging_message_list = zaqarclient.queues.v2.cli:ListMessages messaging_message_post = zaqarclient.queues.v2.cli:PostMessages messaging_ping = zaqarclient.queues.v2.cli:Ping messaging_pool_create = zaqarclient.queues.v2.cli:CreatePool messaging_pool_delete = zaqarclient.queues.v2.cli:DeletePool messaging_pool_list = zaqarclient.queues.v2.cli:ListPools messaging_pool_show = zaqarclient.queues.v2.cli:ShowPool messaging_pool_update = zaqarclient.queues.v2.cli:UpdatePool messaging_queue_create = zaqarclient.queues.v2.cli:CreateQueue messaging_queue_delete = zaqarclient.queues.v2.cli:DeleteQueue messaging_queue_get_metadata = zaqarclient.queues.v2.cli:GetQueueMetadata messaging_queue_list = zaqarclient.queues.v2.cli:ListQueues messaging_queue_purge = zaqarclient.queues.v2.cli:PurgeQueue messaging_queue_set_metadata = zaqarclient.queues.v2.cli:SetQueueMetadata messaging_queue_signed_url = zaqarclient.queues.v2.cli:CreateSignedUrl messaging_queue_stats = zaqarclient.queues.v2.cli:GetQueueStats messaging_subscription_create = zaqarclient.queues.v2.cli:CreateSubscription messaging_subscription_delete = zaqarclient.queues.v2.cli:DeleteSubscription messaging_subscription_list = zaqarclient.queues.v2.cli:ListSubscriptions messaging_subscription_show = zaqarclient.queues.v2.cli:ShowSubscription messaging_subscription_update = zaqarclient.queues.v2.cli:UpdateSubscription pool_create = zaqarclient.queues.v2.cli:OldCreatePool pool_delete = zaqarclient.queues.v2.cli:OldDeletePool pool_list = zaqarclient.queues.v2.cli:OldListPools pool_show = zaqarclient.queues.v2.cli:OldShowPool pool_update = zaqarclient.queues.v2.cli:OldUpdatePool queue_create = zaqarclient.queues.v2.cli:OldCreateQueue queue_delete = zaqarclient.queues.v2.cli:OldDeleteQueue queue_get_metadata = zaqarclient.queues.v2.cli:OldGetQueueMetadata queue_list = zaqarclient.queues.v2.cli:OldListQueues queue_purge = zaqarclient.queues.v2.cli:OldPurgeQueue queue_set_metadata = zaqarclient.queues.v2.cli:OldSetQueueMetadata queue_signed_url = zaqarclient.queues.v2.cli:OldCreateSignedUrl queue_stats = zaqarclient.queues.v2.cli:OldGetQueueStats subscription_create = zaqarclient.queues.v2.cli:OldCreateSubscription subscription_delete = zaqarclient.queues.v2.cli:OldDeleteSubscription subscription_list = zaqarclient.queues.v2.cli:OldListSubscriptions subscription_show = zaqarclient.queues.v2.cli:OldShowSubscription subscription_update = zaqarclient.queues.v2.cli:OldUpdateSubscription [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 [zaqarclient.transport] http.v1 = zaqarclient.transport.http:HttpTransport http.v1.1 = zaqarclient.transport.http:HttpTransport http.v2 = zaqarclient.transport.http:HttpTransport https.v1 = zaqarclient.transport.http:HttpTransport https.v1.1 = zaqarclient.transport.http:HttpTransport https.v2 = zaqarclient.transport.http:HttpTransport ws.v1 = zaqarclient.transport.ws:WebsocketTransport ws.v1.1 = zaqarclient.transport.ws:WebsocketTransport ws.v2 = zaqarclient.transport.ws:WebsocketTransport python-zaqarclient-1.11.0/python_zaqarclient.egg-info/pbr.json0000664000175000017500000000005613364112773024546 0ustar zuulzuul00000000000000{"git_version": "13e90a0", "is_release": true}python-zaqarclient-1.11.0/python_zaqarclient.egg-info/SOURCES.txt0000664000175000017500000001313513364112773024756 0ustar zuulzuul00000000000000.stestr.conf .zuul.yaml AUTHORS ChangeLog HACKING.rst LICENSE README.rst lower-constraints.txt requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/README.md doc/requirements.txt doc/source/client.rst doc/source/command-line.rst doc/source/conf.py doc/source/index.rst doc/source/command/claim.rst doc/source/command/flavor.rst doc/source/command/health.rst doc/source/command/ping.rst doc/source/command/pool.rst doc/source/command/queue.rst doc/source/command/subscription.rst examples/claims.py examples/keystone_auth.py examples/keystone_session_auth.py examples/management.py examples/signed_url_auth.py examples/simple.py playbooks/zaqarclient-dsvm-functional/post.yaml playbooks/zaqarclient-dsvm-functional/run.yaml python_zaqarclient.egg-info/PKG-INFO python_zaqarclient.egg-info/SOURCES.txt python_zaqarclient.egg-info/dependency_links.txt python_zaqarclient.egg-info/entry_points.txt python_zaqarclient.egg-info/not-zip-safe python_zaqarclient.egg-info/pbr.json python_zaqarclient.egg-info/requires.txt python_zaqarclient.egg-info/top_level.txt releasenotes/notes/add-validation-for-queue-name-6e417870cc257308.yaml releasenotes/notes/consistent-command-format-82df852b384bd284.yaml releasenotes/notes/keystoneclient-to-keystoneauth-85c5f098bd023030.yaml releasenotes/notes/remove_os_prefix-14fc4a97527dee81.yaml releasenotes/notes/support-SSL-and-insecure-9b2bbec12b76bf7f.yaml releasenotes/notes/support-detailed-queue-list-0335b3ebde115bfd.yaml releasenotes/notes/support-doc-f12538ac5f35a282.yaml releasenotes/notes/support-osprofiler-41af30da3bee5ed0.yaml releasenotes/notes/support-post-list-messages-cc224643840a1242.yaml releasenotes/notes/support-session-c3f81233e03dacc8.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/ocata.rst releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/rocky.rst releasenotes/source/unreleased.rst tests/__init__.py tests/functional/__init__.py tests/functional/queues/__init__.py tests/functional/queues/v1/__init__.py tests/functional/queues/v1/test_claims.py tests/functional/queues/v1/test_flavor.py tests/functional/queues/v1/test_pool.py tests/functional/queues/v1/test_queues.py tests/functional/queues/v2/__init__.py tests/functional/queues/v2/test_claims.py tests/functional/queues/v2/test_flavor.py tests/functional/queues/v2/test_health.py tests/functional/queues/v2/test_pool.py tests/functional/queues/v2/test_queues.py tests/functional/queues/v2/test_subscription.py tests/unit/__init__.py tests/unit/auth/__init__.py tests/unit/auth/test_base.py tests/unit/auth/test_keystone.py tests/unit/cli/__init__.py tests/unit/cli/fakes.py tests/unit/cli/v1/__init__.py tests/unit/cli/v1/test_queues.py tests/unit/common/__init__.py tests/unit/common/test_http.py tests/unit/openstack/common/__init__.py tests/unit/queues/__init__.py tests/unit/queues/test_client.py tests/unit/queues/transport/__init__.py tests/unit/queues/transport/http/__init__.py tests/unit/queues/transport/zmq/__init__.py tests/unit/queues/v1/__init__.py tests/unit/queues/v1/test_claims.py tests/unit/queues/v1/test_client.py tests/unit/queues/v1/test_core.py tests/unit/queues/v1/test_flavor.py tests/unit/queues/v1/test_message.py tests/unit/queues/v1/test_pool.py tests/unit/queues/v1/test_queues.py tests/unit/queues/v2/__init__.py tests/unit/queues/v2/test_claims.py tests/unit/queues/v2/test_client.py tests/unit/queues/v2/test_core.py tests/unit/queues/v2/test_flavor.py tests/unit/queues/v2/test_health.py tests/unit/queues/v2/test_message.py tests/unit/queues/v2/test_pool.py tests/unit/queues/v2/test_queues.py tests/unit/queues/v2/test_subscription.py tests/unit/transport/__init__.py tests/unit/transport/test_api.py tests/unit/transport/test_http.py tests/unit/transport/test_request.py tests/unit/transport/test_ws.py zaqarclient/__init__.py zaqarclient/_i18n.py zaqarclient/errors.py zaqarclient/version.py zaqarclient/auth/__init__.py zaqarclient/auth/base.py zaqarclient/auth/keystone.py zaqarclient/auth/signed_url.py zaqarclient/common/__init__.py zaqarclient/common/decorators.py zaqarclient/common/http.py zaqarclient/queues/__init__.py zaqarclient/queues/cli.py zaqarclient/queues/client.py zaqarclient/queues/v1/__init__.py zaqarclient/queues/v1/api.py zaqarclient/queues/v1/claim.py zaqarclient/queues/v1/cli.py zaqarclient/queues/v1/client.py zaqarclient/queues/v1/core.py zaqarclient/queues/v1/flavor.py zaqarclient/queues/v1/iterator.py zaqarclient/queues/v1/message.py zaqarclient/queues/v1/pool.py zaqarclient/queues/v1/queues.py zaqarclient/queues/v2/__init__.py zaqarclient/queues/v2/api.py zaqarclient/queues/v2/claim.py zaqarclient/queues/v2/cli.py zaqarclient/queues/v2/client.py zaqarclient/queues/v2/core.py zaqarclient/queues/v2/flavor.py zaqarclient/queues/v2/message.py zaqarclient/queues/v2/pool.py zaqarclient/queues/v2/queues.py zaqarclient/queues/v2/subscription.py zaqarclient/tests/__init__.py zaqarclient/tests/base.py zaqarclient/tests/mock/__init__.py zaqarclient/tests/mock/message.py zaqarclient/tests/queues/__init__.py zaqarclient/tests/queues/base.py zaqarclient/tests/queues/claims.py zaqarclient/tests/queues/flavor.py zaqarclient/tests/queues/health.py zaqarclient/tests/queues/messages.py zaqarclient/tests/queues/pool.py zaqarclient/tests/queues/queues.py zaqarclient/tests/queues/subscriptions.py zaqarclient/tests/transport/__init__.py zaqarclient/tests/transport/api.py zaqarclient/tests/transport/dummy.py zaqarclient/transport/__init__.py zaqarclient/transport/api.py zaqarclient/transport/base.py zaqarclient/transport/errors.py zaqarclient/transport/http.py zaqarclient/transport/request.py zaqarclient/transport/response.py zaqarclient/transport/ws.pypython-zaqarclient-1.11.0/python_zaqarclient.egg-info/dependency_links.txt0000664000175000017500000000000113364112773027135 0ustar zuulzuul00000000000000 python-zaqarclient-1.11.0/python_zaqarclient.egg-info/top_level.txt0000664000175000017500000000001413364112773025614 0ustar zuulzuul00000000000000zaqarclient python-zaqarclient-1.11.0/python_zaqarclient.egg-info/not-zip-safe0000664000175000017500000000000113364112773025315 0ustar zuulzuul00000000000000 python-zaqarclient-1.11.0/python_zaqarclient.egg-info/PKG-INFO0000664000175000017500000001122113364112773024161 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-zaqarclient Version: 1.11.0 Summary: Client Library for OpenStack Zaqar Messaging API Home-page: https://docs.openstack.org/python-zaqarclient/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/tc/badges/python-zaqarclient.svg :target: http://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python Zaqar Client =================== .. image:: https://img.shields.io/pypi/v/python-zaqarclient.svg :target: https://pypi.org/project/python-zaqarclient/ :alt: Latest Version :Wiki: `Zaqar Wiki`_ :Launchpad: `Zaqar Launchpad`_ :Review: `Code Review`_ :Design: `Client Wiki`_ :IRC: #openstack-zaqar @ freenode Welcome to the `Zaqar`_ Python Client project! Installation ------------ The latest stable release can be installed from PyPI:: pip install --upgrade python-zaqarclient For the adventurous, you may also install the latest code directly from git .openstack.org:: pip install git+https://git.openstack.org/openstack/python-zaqarclient.git What's in the box ----------------- By installing python-zaqarclient you get programmatic access to the Zaqar v1.0 API library. Plus, it installs a plugin to python-openstackclient that allows you to perform simple queue operations. How to use ========== Python client ------------- Details about design, features, usage and workflow can be found in the `Python Client Wiki`_. .. _Python Client Wiki: https://wiki.openstack.org/wiki/Zaqar/PythonClient Command line interface ---------------------- Zaqar bases its client implementation in the `OpenStack Client`_. It can be installed and configured by following the instructions in *Getting Started* and *Configuration* in the `OpenStack Client Readme`_ respectively. The CLI currently allows creation, removal and listing of queues. Some examples are:: $ openstack queue list --limit 3 $ openstack queue create myqueue $ openstack queue delete myqueue .. _`OpenStack Client`: https://git.openstack.org/cgit/openstack/python-openstackclient .. _`OpenStack Client Readme`: https://git.openstack.org/cgit/openstack/python-openstackclient/tree/README.rst Contributing ============ Be sure to reference the `HACKING`_ file for details on coding style. You may also wish to read through Zaqar's `Contributor Guide`_ before contributing your first patch. .. _Zaqar: https://git.openstack.org/cgit/openstack/zaqar .. _HACKING: https://git.openstack.org/cgit/openstack/python-zaqarclient/tree/HACKING.rst .. _Zaqar Wiki: https://wiki.openstack.org/wiki/Zaqar .. _Contributor Guide: https://wiki.openstack.org/wiki/Zaqar#Contributor_Guide .. _Zaqar Launchpad: https://launchpad.net/zaqar .. _Code Review: https://review.openstack.org/#/q/status:open+project:openstack/python-zaqarclient,n,z .. _Client Wiki: https://wiki.openstack.org/wiki/Python_Zaqar_Client * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Bugs`_ - issue tracking * `Source`_ .. _PyPi: https://pypi.org/project/python-zaqarclient .. _Bugs: https://bugs.launchpad.net/python-zaqarclient .. _Source: https://git.openstack.org/cgit/openstack/python-zaqarclient Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 python-zaqarclient-1.11.0/examples/0000775000175000017500000000000013364112773017275 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/examples/signed_url_auth.py0000666000175000017500000000337113364112606023024 0ustar zuulzuul00000000000000# Copyright 2016 Catalyst IT Ltd # # 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.queues.v2 import client URL = 'http://localhost:8888' def create_post_delete(queue_name, messages): """Presigned queue example Creates a queue, posts messages to it and finally deletes it with ``signed-url`` auth strategy enabled on Zaqar server side. :params queue_name: The name of the queue :type queue_name: `six.text_type` :params messages: Messages to post. :type messages: list """ conf = {'auth_opts': {'backend': 'signed-url', 'options': {'signature': '', 'expires': '', 'methods': ['GET', 'PATCH', 'POST', 'PUT'], 'paths': ['/v2/queues/beijing/claims'], 'os_project_id': '2887aabf368046a3bb0070f1c0413470'} } } cli = client.Client(URL, conf=conf) queue = cli.queue(queue_name) queue.post(messages) for msg in queue.messages(echo=True): print(msg.body) msg.delete() if __name__ == '__main__': messages = [{'body': {'id': idx}, 'ttl': 360} for idx in range(20)] create_post_delete('beijing', messages) python-zaqarclient-1.11.0/examples/simple.py0000666000175000017500000000314213364112606021135 0ustar zuulzuul00000000000000# Copyright 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. # NOTE(flaper87): Client should be moved to # an upper package. It's version agnostic. from zaqarclient.queues.v2 import client URL = 'http://localhost:8888' def create_post_delete(queue_name, messages): """Simple example Creates a queue, posts messages to it and finally deletes it. :params queue_name: The name of the queue :type queue_name: `six.text_type` :params messages: Messages to post. :type messages: list """ # Note: credential information should be provided # using `conf` keyword argument if authentication # is enabled at server side. Please refer to # keystone_auth.py for more information. cli = client.Client(URL, version=2) queue = cli.queue(queue_name) queue.post(messages) for msg in queue.messages(echo=True): print(msg.body) msg.delete() queue.delete() if __name__ == '__main__': messages = [{'body': {'id': idx}, 'ttl': 360} for idx in range(20)] create_post_delete('my_queue', messages) python-zaqarclient-1.11.0/examples/keystone_session_auth.py0000666000175000017500000000336613364112606024301 0ustar zuulzuul00000000000000# Copyright 2016 Catalyst IT Ltd. # # 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 keystoneauth1.identity.generic import password from keystoneauth1 import session from zaqarclient.queues.v2 import client def create_post_delete(queue_name, messages): """Auth example Creates a queue, posts messages to it and finally deletes it with keystone auth strategy enabled on Zaqar server side. :params queue_name: The name of the queue :type queue_name: `six.text_type` :params messages: Messages to post. :type messages: list """ auth = password.Password( "http://127.0.0.1/identity_v2_admin", username="admin", password="passw0rd", user_domain_name='default', project_name='admin', project_domain_name='default') keystone_session = session.Session(verify=False, cert=None, auth=auth) cli = client.Client(session=keystone_session) queue = cli.queue(queue_name) queue.post(messages) for msg in queue.messages(echo=True): print(msg.body) msg.delete() queue.delete() if __name__ == '__main__': messages = [{'body': {'id': idx}, 'ttl': 360} for idx in range(20)] create_post_delete('my_queue', messages) python-zaqarclient-1.11.0/examples/claims.py0000666000175000017500000000273413364112605021121 0ustar zuulzuul00000000000000# Copyright (c) 2014 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 time from zaqarclient.queues.v2 import client URL = 'http://localhost:8888' # Note: credential information should be provided using `conf` # keyword argument if authentication is enabled at server side. # Please refer to keystone_auth.py for more information. cli = client.Client(URL) queue = cli.queue('worker-jobs') def send_jobs(): jobs = [ {'name': 'fluffy'}, {'name': 'scout'}, {'name': 'jo'} ] queue.post([{'body': j, 'ttl': 360} for j in jobs]) def process_jobs(): claim1 = queue.claim(ttl=500, grace=900, limit=2) for msg in claim1: claim_id = msg.claim_id print('{claim_id} =? {id}'.format(claim_id=claim_id, id=claim1.id)) print('processing job %s' % (msg)) msg.delete() time.sleep(0.5) if __name__ == '__main__': while True: send_jobs() process_jobs() python-zaqarclient-1.11.0/examples/management.py0000666000175000017500000000177313364112606021770 0ustar zuulzuul00000000000000# 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. from zaqarclient.queues import client URL = 'http://localhost:8888' def healthy(): # Note: credential information should be provided # using `conf` keyword argument if authentication # is enabled at server side. Please refer to # keystone_auth.py for more information. cli = client.Client(url=URL, version=2) return True if cli.health() else False if __name__ == '__main__': healthy() python-zaqarclient-1.11.0/examples/keystone_auth.py0000666000175000017500000000347613364112606022540 0ustar zuulzuul00000000000000# Copyright 2014 Red Hat, Inc. # 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. from zaqarclient.queues.v2 import client URL = 'http://localhost:8888' def create_post_delete(queue_name, messages): """Auth example Creates a queue, posts messages to it and finally deletes it with keystone auth strategy enabled on Zaqar server side. :params queue_name: The name of the queue :type queue_name: `six.text_type` :params messages: Messages to post. :type messages: list """ conf = {'auth_opts': {'backend': 'keystone', 'options': {'os_username': 'zaqar', 'os_password': 'zaqar', 'os_project_id': 'ccad479c402f43a2994f6e372ab3f8fe', 'os_project_name': '', 'os_auth_url': 'http://127.0.0.1:5000/v2.0/', 'insecure': ''} } } cli = client.Client(URL, conf=conf) queue = cli.queue(queue_name) queue.post(messages) for msg in queue.messages(echo=True): print(msg.body) msg.delete() queue.delete() if __name__ == '__main__': messages = [{'body': {'id': idx}, 'ttl': 360} for idx in range(20)] create_post_delete('my_queue', messages) python-zaqarclient-1.11.0/README.rst0000666000175000017500000000577113364112605017154 0ustar zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/tc/badges/python-zaqarclient.svg :target: http://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python Zaqar Client =================== .. image:: https://img.shields.io/pypi/v/python-zaqarclient.svg :target: https://pypi.org/project/python-zaqarclient/ :alt: Latest Version :Wiki: `Zaqar Wiki`_ :Launchpad: `Zaqar Launchpad`_ :Review: `Code Review`_ :Design: `Client Wiki`_ :IRC: #openstack-zaqar @ freenode Welcome to the `Zaqar`_ Python Client project! Installation ------------ The latest stable release can be installed from PyPI:: pip install --upgrade python-zaqarclient For the adventurous, you may also install the latest code directly from git .openstack.org:: pip install git+https://git.openstack.org/openstack/python-zaqarclient.git What's in the box ----------------- By installing python-zaqarclient you get programmatic access to the Zaqar v1.0 API library. Plus, it installs a plugin to python-openstackclient that allows you to perform simple queue operations. How to use ========== Python client ------------- Details about design, features, usage and workflow can be found in the `Python Client Wiki`_. .. _Python Client Wiki: https://wiki.openstack.org/wiki/Zaqar/PythonClient Command line interface ---------------------- Zaqar bases its client implementation in the `OpenStack Client`_. It can be installed and configured by following the instructions in *Getting Started* and *Configuration* in the `OpenStack Client Readme`_ respectively. The CLI currently allows creation, removal and listing of queues. Some examples are:: $ openstack queue list --limit 3 $ openstack queue create myqueue $ openstack queue delete myqueue .. _`OpenStack Client`: https://git.openstack.org/cgit/openstack/python-openstackclient .. _`OpenStack Client Readme`: https://git.openstack.org/cgit/openstack/python-openstackclient/tree/README.rst Contributing ============ Be sure to reference the `HACKING`_ file for details on coding style. You may also wish to read through Zaqar's `Contributor Guide`_ before contributing your first patch. .. _Zaqar: https://git.openstack.org/cgit/openstack/zaqar .. _HACKING: https://git.openstack.org/cgit/openstack/python-zaqarclient/tree/HACKING.rst .. _Zaqar Wiki: https://wiki.openstack.org/wiki/Zaqar .. _Contributor Guide: https://wiki.openstack.org/wiki/Zaqar#Contributor_Guide .. _Zaqar Launchpad: https://launchpad.net/zaqar .. _Code Review: https://review.openstack.org/#/q/status:open+project:openstack/python-zaqarclient,n,z .. _Client Wiki: https://wiki.openstack.org/wiki/Python_Zaqar_Client * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Bugs`_ - issue tracking * `Source`_ .. _PyPi: https://pypi.org/project/python-zaqarclient .. _Bugs: https://bugs.launchpad.net/python-zaqarclient .. _Source: https://git.openstack.org/cgit/openstack/python-zaqarclient python-zaqarclient-1.11.0/setup.py0000666000175000017500000000200613364112606017164 0ustar zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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 FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) python-zaqarclient-1.11.0/tox.ini0000666000175000017500000000307613364112606016775 0ustar zuulzuul00000000000000[tox] minversion = 2.0 envlist = py35,py27,pep8 skipsdist = True [testenv] usedevelop = True # Customize pip command, add -U to force updates. install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = find . -type f -name "*.pyc" -delete stestr run {posargs} whitelist_externals = find [tox:jenkins] sitepackages = True [testenv:pep8] basepython = python3 commands = flake8 [testenv:cover] basepython = python3 setenv = {[testenv]setenv} PYTHON=coverage run --source zaqarclient --parallel-mode commands = stestr -q run {posargs} coverage combine coverage html -d cover coverage xml -o cover/coverage.xml [testenv:venv] basepython = python3 commands = {posargs} [testenv:docs] basepython = python3 deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -W -b html doc/source doc/build/html [testenv:releasenotes] basepython = python3 deps = -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] builtins = _ exclude = .venv,.git,.tox,dist,doc,*.egg [testenv:lower-constraints] basepython = python3 deps = -c{toxinidir}/lower-constraints.txt -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt python-zaqarclient-1.11.0/AUTHORS0000664000175000017500000000720713364112773016535 0ustar zuulzuul0000000000000098k <18552437190@163.com> Alejandro Cabrera Alessio Ababilov Alessio Ababilov Alessio Ababilov Alex Gaynor Andreas Jaeger Andrey Kurilin Angus Salkeld Angus Salkeld Bartosz Fic Brian Curtin Caleb Groom Cao Xuan Hoang Chad Lung Chen Christian Berendt Dan Prince Dirk Mueller Doug Hellmann Eva Balycheva Fei Long Wang Fei Long Wang Fei Long Wang Flaper Fesp Flavio Percoco Hangdong Zhang Janonymous Jay Baugh Jeffrey Zhang Jeremy Stanley Joe Gordon John Heatherington KATO Tomoyuki Kevin_Zheng MD NADEEM MD NADEEM Md Nadeem Muharem Hrnjadovic Nguyen Hai Oleksii Chuprykov Ondřej Nový OpenStack Release Bot Pavlo Shchelokovskyy Rajiv Kumar Robert Collins Rui Chen Ryan S. Brown Sascha Peilicke Sascha Peilicke Sergey Lukjanov Shaifali Agrawal Shane Wang ShangXiao Shuquan Huang Sriram Madapusi Vasudevan Steve Martinelli Swapnil Kulkarni (coolsvap) Tang Chen TheSriram Thomas Bechtold Thomas Herve Thomas Herve Tony Breeds Tony Xu Tovin Seven Victoria Martinez de la Cruz Victoria Martínez de la Cruz Yuanbin.Chen Yuuichi Fujioka ZhaoBo Zhi Yan Liu avnish caishan daohanli digambar dynarro gecong1973 gengchc2 howardlee jonnary kgriffs lingyongxu liusheng melissaml miaohb rabi rajat29 ricolin ricolin shu-mutou wanghao wanghao wangxiyuan xianming mao xywang <233652566@qq.com> yangzhenyu yanyanhu zengjianfang python-zaqarclient-1.11.0/ChangeLog0000664000175000017500000003403013364112773017231 0ustar zuulzuul00000000000000CHANGES ======= 1.11.0 ------ * Properly pass the CA to requests * Import zaqarclient-dsvm-functional job * Remove PyPI downloads * add python 3.6 unit test job * switch documentation job to new PTI * import zuul job settings from project-config * Replace os-client-config to openstacksdk * Update reno for stable/rocky * Update releasenotes index for Rocky 1.10.0 ------ * fix tox python3 overrides * Comply with Python PTI * Fix doc CI failure * Trivial: Update pypi url to new url * Follow the new PTI for document build * add lower-constraints job * Fix the old or invalid links in docs * Updated from global requirements * Fix zuul check failure at legacy-zaqarclient-dsvm-functional * Support client of bp support-md5-of-body * Add checksum to message \_\_init\_\_() * Update reno for stable/queens * Updated from global requirements * fix README.rst format error * Cleanup test-requirements 1.9.0 ----- * Support client for delayed queues * Change wrong url for zaqarclient * Update queue metadata test 1.8.0 ----- * Add claim\_count to message \_\_init\_\_() * Remove -U from pip install * Avoid tox\_install.sh for constraints support * Remove setting of version/release from releasenotes * Updated from global requirements * Updated from global requirements * Update queue metadata failed when the original value is zero * Updated from global requirements * Fix functional CI failure * Updated from global requirements * Fix renew claim NoneType error * Update reno for stable/pike 1.7.0 ----- * Fix class Queue \_\_init\_\_ method's param note * Updated from global requirements * Switch from oslosphinx to openstackdocstheme * Update the documentation link for doc migration * Add new command guide doc * Fix query claim NoneType error * Replace uuid.uuid4() with uuidutils.generate\_uuid() * Fix the inconsistent command format in openstackclient * Add ZaqarClient "set metadata" help message * Updated from global requirements * Fix the creation issue when special meanings words in queue name * Add subscription other properties 1.6.0 ----- * Update purge doc * CLI: support homedoc in client 1.5.0 ----- * Updated from global requirements * CLI: support detailed in queue list * Fix flavor creation issue with CLI * Don not show 'capabilities' if not specify '--detailed' * Support post and list messages * remove "--detailed" in subscription list doc * Add 'pool' description to pool flavor commands * Remove log translations * Drop "os" prefix for project id * Revert "Fix The header X-PROJECT-ID missing bug" * Fix The header X-PROJECT-ID missing bug * Remove "detailed" parser from subscription list * Updated from global requirements * [Fix gate]Update test requirement * Support \`age\` and \`confirmed\` for subscription * Change resource\_types action * Support purge queue * Add Ocata version mapping * Update reno for stable/ocata * Replace the github with git.openstack.org * Remove support for py34 1.4.0 ----- * Updated from global requirements * Set client module \_\_version\_\_ * Enable release notes translation * Switch to oslo\_log 1.3.0 ----- * Remove unnecessary utf8 coding format in the head of files * Updated from global requirements * Add doc for subscription cli * Update release note doc * Add the releasenote detail * Add command guide for openstack ping&health CLI * Add command guide for openstack flavor CLI * Add command guide for openstack pool CLI * Add Constraints support * Fix typos in zaqarclient * Add releasenotes for client * Add command guide for openstack claim CLI * Add command guide for queue * update doc to Api v2.0 * translate all command help strings * Remove the TODO for subscription ttl test * Remove version in README * Update author and home-page * Fix CI failure * Show team and repo badges on README * Delete deprecated directory openstack/common * Add plug-in summary for osc doc * Updated from global requirements * Fix the CI failure * Add profiling support to Zaqar client * Support keystone session when creating client * Add Python 3.5 classifier and venv * Files with no code must be left completely empty * Support SSL and Insecure * Change assertTrue(isinstance()) by optimal assert * Switch keystoneclient to keystoneauth * Remove unused openstack-doc-tools from test-requirements.txt * Using v2 interface in example 1.2.0 ----- * Updated from global requirements * Remove discover from test-requirements * Clean imports in code * Update the functional test * Fix the attribute missing error * Create a websocket transport * Updated from global requirements * Add requests-mock to test-requirements.txt * Use osc\_lib instead of cliff * Add an example for pre signed URL * Use osc-lib instead of openstackclient 1.1.0 ----- * Add update queue function in v2 * Fix the zaqar functional test job * Ensure the float value of api version could work * Updated from global requirements * Fix doc build if git is absent * Refactor queue create * Support /ping and /health for v2 * Fix tests related to queue attributes in API V2 * Use v2 as the default cli version * Remove pypy support 1.0.0 ----- * Support PATCH of queue metadata * "pool\_group" word should be used instead "pool" * Update pool on pool create if it exists * Update flavor on flavor create if it exists * Make TransportErrors more descriptive * Remove unused pngmath Sphinx extension * Raise ConflictError like other transport errors * Do not catch ConflictError on subscription create * Add subscriptions for queue object * Updated from global requirements * Support claims for v2 * Fix wrong api version type * Improve subscription listing * Fix Subscription's queue\_name variable being tuple * Add CLI support for signed URLs * Fix queue stats for v1.1 and above versions * Fix client not working on Python 3 * Updated from global requirements * Clean up flavor test classes * Fix typo preventing queue list for v1 * Add a way to create a signed URL from a queue * Use API version checking directly * Updated from global requirements * Fixing the deprecated library function * Add Support for subscription list v2 * Add support for subscription show v2 * Expose more CLI commands for v2 * Add support for subscription delete v2 * Add support for subscription update v2 * Add support for subscription create v2 * Claim release CLI support for v1 * Claim renew CLI support for v1 * Query claim CLI support for v1 * Flavor list support for v2 * Handle os\_auth\_token option in keystone config * Flavor create CLI support for v2 * Updated from global requirements * Fix bad "pool list" api v2 entry point for CLI * Claim create CLI support for v1 * Put py34 first in the env order of tox * Make sure queue create works for cli * Replace assertEqual(None, \*) with assertIsNone in tests * Added support to claims * Updated from global requirements * Flavor update cli support for v2 * Flavor show cli support for v2 * Drop py33 support * Fix freeze of Claim object's age property * Deprecated tox -downloadcache option removed * Add cli support for flavor create v1 * Updated from global requirements * Delete CLI for Get/SetQueueMetadata which is API-v1 only * Expose CLI commands for v2 * Delete CLI for CheckQueueExistence which is <=v1.1 only * Refactor the test for v2 queues and messages * Add support for flavor list v1 * Add cli support for flavor show v1 * Updated from global requirements * Using clouds.yaml to get the credentials * Remove py26 support * delete python bytecode before every test run * Pool & flavor cli implementation for v2 * Pool list cli support for v2 * Pool delete cli support for v2 * Add cli support for flavor update v1 * Pool update support for v2 * Added pool list support for v1 * Fix unexpected output of pools() * Updated from global requirements * Add \`pool\` support for v2 * Add \`flavor\` support for v2 * Implement CLI support for pool delete * Added pool update support for v1 * Attaching a default project\_id * Pool show support for v2 * Added pool show support to v1 * Fix create pool error * Support creating signed url's in client * Fix client UnauthorizedError * Updated from global requirements 0.3.0 ----- * Rename \`flavor delete\` command * Added cli implementation for v2 * Remove periods of docstring * Added API\_VERSION for v2 * Added support to v2 * improve readme contents * Fix order of arguments in assertEqual * Fix order of arguments in assertEqual * Fix order of arguments in assertEqual * Fix functional test of get\_many\_messages 0.2.0 ----- * Release notes for 0.2.0 * Using messaging instead of queueing * Updated from global requirements * Allow for authentication in functional tests * Don't pass \`options\` to pool creation * Don't reuse request and transport instances * Pass \`group\` in pool's functional tests * Send claims \`limit\` as a query param * v1.1 and v2 claims return document not list * Make sure the API version is passed down * Make v1.1 the default CLI version * Updated from global requirements * Updated from global requirements * Implement CLI support for flavor * Implements CLI for pool * Raises an error if the queue name is empty * Added support to pools and flavors * Removed deprecated 'shard' methods 0.1.1 ----- * Relese notes for zaqarclient 0.1.1 * Drop incubating theme from docs * Deleted unuseful line * Drop use of 'oslo' namespace package * Fix handling of 1.1 API * Update README to work with release tools * Gets 'flavor' data if the resource exists * Gets 'pool' data if the resource exists * Handling exception on 504 Error * Updated from global requirements * Added i18n support * Makes health return True or False * Remove unused openstack/common modules * Adds encapsulation control to the client * Updated from global requirements * Extend some docstrings with useful information * Add reference docs for latest recommended client * Add docs for \`Client\` instances * Setup developer docs for zaqarclient * Fix the client name typo * Updated from global requirements * fix KeystoneAuth doc string * Updated from global requirements * Updates API name 0.1.0 ----- * Updated from global requirements * Add a read-only property for Queues * Cleanup technical debt * Always pass a project\_id * Respect queue's lazy creation * Use queue\_creation to send queue's metadata * Fix functional tests * Add support for flavor to the client library * Rename \`shard\` to \`pool\` * Add support for \`pop\` implemented in v1.1 * Add support for bulk message delete in v1 * CLI support for queue existence and metadata operations * Updated from global requirements * Send more than 1 message in messages\_get\_many * Start adding support for v1.1 * Work toward Python 3.4 support and testing * Remove hardcoded version 0.0.3 ----- * Fix .gitreview due to the repo rename/move * Dividing markups into multiple lines * Rename Marconi to Zaqar * Updated from global requirements * Adds extra info about python-marconiclient and usage instructions * Updated from global requirements * doc: Update README.rst with correct installation and contibution info 0.0.2 ----- * chore: Bump version to 0.0.2 in preparation for bugfix release * Throw exceptions on erroneous status codes * Enable deleting of message with claim id * Updated from global requirements * Initial support for openstack-client * fix: add https support 0.0.1 ----- * chore: Classify as Beta (was pre-alpha) * Updated from global requirements * Updated from global requirements * Bump client version to 0.0.1 * Don't stream by default * Updated from global requirements * Updated from global requirements * Add sample for Keystone auth * Updated from global requirements * Move auth tests under the unit package * Refactoring iterators * Added API version to URL * Add support for claims * Updated from global requirements * Updated from global requirements * Added iterable list of queues * Fix the message \_\_repr\_\_ formatter * Add python3 and pypy trove classifiers * Fix misspellings in python marconiclient * Add /health support to the client * Removed oslo.config from requirements.text * Delete unused module * Expose the stats attribute on a queue * Sync with global requirements * Add shard support to the client * Keystoneclient supports Py3K now * Let Hacking choose the right dependencies on its own * Fixes wrong variable invoking during get transport 0.0.1a1 ------- * chore: Bump version to 0.0.1a1 in preparation for our first release! * Add a Message resource and a MessageIterator * Add \`deserialized\_content\` to the response * Use oslo.config>=1.2.0 * Add a base test class for the queues package * Add a Client 'instantiator' * Move request\_and\_transport to the Client * Make pbr only a build-time dependency * Add missing requests requirement * Add \`simple\` example for the client library * Remove the dependency on oslo.config * Bootstrap Messages support * fix: import-time side effect on errors * Remove unused packages * Support building wheels (PEP-427) * Fix some links in the README * Updated the readme to have valid links * Add list of required fields to the API definition * Implement queue's API methods * change assertEquals to assertEqual * Pass keywords to the request initialization * Implement HTTP Transport * Make the request object API aware * Split get\_transport into 2 different functions * Complete refactor of api.py * Create v1 package and move messages there * Add prepare\_request function to requests.py * Add a base transport class * Restructure client code * Use latest PBR * Add keystone backend * Authentication API + NoAuth backend * Add common http class * This adds a transport layer request spec class * Refactor client's structure to reflect Marconi's * Remove mox from test-requirements.txt * Added a base class for tests * Adding first oslo module and config * Update requirements and pbr version * Update .gitreview for incubation org move * Implement message controller * Update tox.ini and setup.cfg * Added support for running the tests under PyPy with tox * Revert "Add apiclient library" * Expose the version of the client * Gate on Python 3.3 * Improve README, add HACKING * Ignore \*.egg files * Convert to more modern openstack-common.conf format * docs(README): add link to design wiki * Add apiclient library * Rename requires files to standard names * Migrate to pbr * Lets get the party started :) * Added .gitreview python-zaqarclient-1.11.0/.zuul.yaml0000666000175000017500000000146413364112605017421 0ustar zuulzuul00000000000000- job: name: python-zaqarclient-functional parent: legacy-dsvm-base run: playbooks/zaqarclient-dsvm-functional/run.yaml post-run: playbooks/zaqarclient-dsvm-functional/post.yaml timeout: 6000 required-projects: - openstack-infra/devstack-gate - openstack/python-zaqarclient - openstack/zaqar - openstack/zaqar-tempest-plugin - openstack/zaqar-ui - project: templates: - check-requirements - openstack-lower-constraints-jobs - openstack-python-jobs - openstack-python35-jobs - openstack-python36-jobs - openstackclient-plugin-jobs - publish-openstack-docs-pti - release-notes-jobs-python3 check: jobs: - python-zaqarclient-functional gate: jobs: - python-zaqarclient-functional python-zaqarclient-1.11.0/playbooks/0000775000175000017500000000000013364112773017462 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/playbooks/zaqarclient-dsvm-functional/0000775000175000017500000000000013364112773025106 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/playbooks/zaqarclient-dsvm-functional/post.yaml0000666000175000017500000000455113364112606026761 0ustar zuulzuul00000000000000- hosts: primary tasks: - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}' mode: pull copy_links: true verify_host: true rsync_opts: - --include=**/*nose_results.html - --include=*/ - --exclude=* - --prune-empty-dirs - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}' mode: pull copy_links: true verify_host: true rsync_opts: - --include=**/*testr_results.html.gz - --include=*/ - --exclude=* - --prune-empty-dirs - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}' mode: pull copy_links: true verify_host: true rsync_opts: - --include=/.testrepository/tmp* - --include=*/ - --exclude=* - --prune-empty-dirs - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}' mode: pull copy_links: true verify_host: true rsync_opts: - --include=**/*testrepository.subunit.gz - --include=*/ - --exclude=* - --prune-empty-dirs - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}/tox' mode: pull copy_links: true verify_host: true rsync_opts: - --include=/.tox/*/log/* - --include=*/ - --exclude=* - --prune-empty-dirs - name: Copy files from {{ ansible_user_dir }}/workspace/ on node synchronize: src: '{{ ansible_user_dir }}/workspace/' dest: '{{ zuul.executor.log_root }}' mode: pull copy_links: true verify_host: true rsync_opts: - --include=/logs/** - --include=*/ - --exclude=* - --prune-empty-dirs python-zaqarclient-1.11.0/playbooks/zaqarclient-dsvm-functional/run.yaml0000666000175000017500000000501713364112606026576 0ustar zuulzuul00000000000000- hosts: all name: Autoconverted job legacy-zaqarclient-dsvm-functional from old job gate-zaqarclient-dsvm-functional-ubuntu-xenial tasks: - name: Ensure legacy workspace directory file: path: '{{ ansible_user_dir }}/workspace' state: directory - shell: cmd: | set -e set -x cat > clonemap.yaml << EOF clonemap: - name: openstack-infra/devstack-gate dest: devstack-gate EOF /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \ git://git.openstack.org \ openstack-infra/devstack-gate executable: /bin/bash chdir: '{{ ansible_user_dir }}/workspace' environment: '{{ zuul | zuul_legacy_vars }}' - shell: cmd: | set -e set -x cat << 'EOF' >>"/tmp/dg-local.conf" [[local|localrc]] enable_plugin zaqar git://git.openstack.org/openstack/zaqar # Enable Zaqar Tempest Plugin TEMPEST_PLUGINS='/opt/stack/new/zaqar-tempest-plugin' EOF executable: /bin/bash chdir: '{{ ansible_user_dir }}/workspace' environment: '{{ zuul | zuul_legacy_vars }}' - shell: cmd: | set -e set -x export PROJECTS="openstack/python-zaqarclient $PROJECTS" export PROJECTS="openstack/zaqar-ui $PROJECTS" export PYTHONUNBUFFERED=true export FUNCTEST_TIMEOUT=30 export DEVSTACK_GATE_ZAQAR=1 export DEVSTACK_GATE_TEMPEST=0 export DEVSTACK_GATE_EXERCISES=0 export DEVSTACK_GATE_INSTALL_TESTONLY=1 export ENABLED_SERVICES=mysql,key,tempest export DEVSTACK_GATE_TEMPEST_REGEX="zaqar_tempest_plugin.tests" export BRANCH_OVERRIDE=default if [ "$BRANCH_OVERRIDE" != "default" ] ; then export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE fi export PROJECTS="openstack/zaqar-tempest-plugin $PROJECTS" export ZAQARCLIENT_AUTH_FUNCTIONAL=1 export ZAQARCLIENT_TEST_FUNCTIONAL=1 function post_test_hook { cd /opt/stack/new/python-zaqarclient nosetests tests.functional } export -f post_test_hook cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh executable: /bin/bash chdir: '{{ ansible_user_dir }}/workspace' environment: '{{ zuul | zuul_legacy_vars }}' python-zaqarclient-1.11.0/setup.cfg0000666000175000017500000001450113364112773017303 0ustar zuulzuul00000000000000[metadata] name = python-zaqarclient summary = Client Library for OpenStack Zaqar Messaging API description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = https://docs.openstack.org/python-zaqarclient/latest/ classifier = Development Status :: 4 - Beta Environment :: Console Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: Developers Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 [global] setup-hooks = pbr.hooks.setup_hook [files] packages = zaqarclient [entry_points] zaqarclient.transport = http.v1 = zaqarclient.transport.http:HttpTransport https.v1 = zaqarclient.transport.http:HttpTransport 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 ws.v1 = zaqarclient.transport.ws:WebsocketTransport ws.v1.1 = zaqarclient.transport.ws:WebsocketTransport ws.v2 = zaqarclient.transport.ws:WebsocketTransport 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 queue_create = zaqarclient.queues.v1.cli:CreateQueue queue_delete = zaqarclient.queues.v1.cli:DeleteQueue queue_exists = zaqarclient.queues.v1.cli:CheckQueueExistence queue_set_metadata = zaqarclient.queues.v1.cli:SetQueueMetadata queue_get_metadata = zaqarclient.queues.v1.cli:GetQueueMetadata queue_stats = zaqarclient.queues.v1.cli:GetQueueStats pool_create = zaqarclient.queues.v1.cli:CreatePool pool_show = zaqarclient.queues.v1.cli:ShowPool pool_update = zaqarclient.queues.v1.cli:UpdatePool pool_delete = zaqarclient.queues.v1.cli:DeletePool pool_list = zaqarclient.queues.v1.cli:ListPools messaging_flavor_list = zaqarclient.queues.v1.cli:ListFlavors messaging_flavor_delete = zaqarclient.queues.v1.cli:DeleteFlavor messaging_flavor_update = zaqarclient.queues.v1.cli:UpdateFlavor messaging_flavor_show = zaqarclient.queues.v1.cli:ShowFlavor messaging_flavor_create = zaqarclient.queues.v1.cli:CreateFlavor claim_create = zaqarclient.queues.v1.cli:CreateClaim claim_query = zaqarclient.queues.v1.cli:QueryClaim claim_renew = zaqarclient.queues.v1.cli:RenewClaim claim_release = zaqarclient.queues.v1.cli:ReleaseClaim openstack.messaging.v2 = queue_list = zaqarclient.queues.v2.cli:OldListQueues queue_create = zaqarclient.queues.v2.cli:OldCreateQueue queue_delete = zaqarclient.queues.v2.cli:OldDeleteQueue queue_stats = zaqarclient.queues.v2.cli:OldGetQueueStats queue_set_metadata = zaqarclient.queues.v2.cli:OldSetQueueMetadata queue_get_metadata = zaqarclient.queues.v2.cli:OldGetQueueMetadata queue_purge = zaqarclient.queues.v2.cli:OldPurgeQueue pool_create = zaqarclient.queues.v2.cli:OldCreatePool pool_show = zaqarclient.queues.v2.cli:OldShowPool pool_update = zaqarclient.queues.v2.cli:OldUpdatePool pool_delete = zaqarclient.queues.v2.cli:OldDeletePool pool_list = zaqarclient.queues.v2.cli:OldListPools messaging_queue_list = zaqarclient.queues.v2.cli:ListQueues messaging_queue_create = zaqarclient.queues.v2.cli:CreateQueue messaging_queue_delete = zaqarclient.queues.v2.cli:DeleteQueue messaging_queue_stats = zaqarclient.queues.v2.cli:GetQueueStats messaging_queue_set_metadata = zaqarclient.queues.v2.cli:SetQueueMetadata messaging_queue_get_metadata = zaqarclient.queues.v2.cli:GetQueueMetadata messaging_queue_purge = zaqarclient.queues.v2.cli:PurgeQueue messaging_pool_create = zaqarclient.queues.v2.cli:CreatePool messaging_pool_show = zaqarclient.queues.v2.cli:ShowPool messaging_pool_update = zaqarclient.queues.v2.cli:UpdatePool messaging_pool_delete = zaqarclient.queues.v2.cli:DeletePool messaging_pool_list = zaqarclient.queues.v2.cli:ListPools messaging_flavor_list = zaqarclient.queues.v2.cli:ListFlavors messaging_flavor_delete = zaqarclient.queues.v2.cli:DeleteFlavor messaging_flavor_update = zaqarclient.queues.v2.cli:UpdateFlavor messaging_flavor_show = zaqarclient.queues.v2.cli:ShowFlavor messaging_flavor_create = zaqarclient.queues.v2.cli:CreateFlavor claim_create = zaqarclient.queues.v2.cli:OldCreateClaim claim_query = zaqarclient.queues.v2.cli:OldQueryClaim claim_renew = zaqarclient.queues.v2.cli:OldRenewClaim claim_release = zaqarclient.queues.v2.cli:OldReleaseClaim subscription_create = zaqarclient.queues.v2.cli:OldCreateSubscription subscription_update = zaqarclient.queues.v2.cli:OldUpdateSubscription subscription_delete = zaqarclient.queues.v2.cli:OldDeleteSubscription subscription_show = zaqarclient.queues.v2.cli:OldShowSubscription subscription_list = zaqarclient.queues.v2.cli:OldListSubscriptions queue_signed_url = zaqarclient.queues.v2.cli:OldCreateSignedUrl messaging_claim_create = zaqarclient.queues.v2.cli:CreateClaim messaging_claim_query = zaqarclient.queues.v2.cli:QueryClaim messaging_claim_renew = zaqarclient.queues.v2.cli:RenewClaim messaging_claim_release = zaqarclient.queues.v2.cli:ReleaseClaim messaging_subscription_create = zaqarclient.queues.v2.cli:CreateSubscription messaging_subscription_update = zaqarclient.queues.v2.cli:UpdateSubscription messaging_subscription_delete = zaqarclient.queues.v2.cli:DeleteSubscription messaging_subscription_show = zaqarclient.queues.v2.cli:ShowSubscription messaging_subscription_list = zaqarclient.queues.v2.cli:ListSubscriptions messaging_queue_signed_url = zaqarclient.queues.v2.cli:CreateSignedUrl messaging_ping = zaqarclient.queues.v2.cli:Ping messaging_health = zaqarclient.queues.v2.cli:Health messaging_homedoc = zaqarclient.queues.v2.cli:HomeDoc message_post = zaqarclient.queues.v2.cli:OldPostMessages message_list = zaqarclient.queues.v2.cli:OldListMessages messaging_message_post = zaqarclient.queues.v2.cli:PostMessages messaging_message_list = zaqarclient.queues.v2.cli:ListMessages openstack.cli.extension = messaging = zaqarclient.queues.cli [nosetests] where = tests verbosity = 2 [wheel] universal = 1 [egg_info] tag_build = tag_date = 0 python-zaqarclient-1.11.0/LICENSE0000666000175000017500000002363613364112605016472 0ustar zuulzuul00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. python-zaqarclient-1.11.0/test-requirements.txt0000666000175000017500000000104213364112606021712 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. # Hacking already pins down pep8, pyflakes and flake8 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 # Unit testing fixtures>=3.0.0 # Apache-2.0/BSD mock>=2.0.0 # BSD testtools>=2.2.0 # MIT # Test runner stestr>=1.0.0 # Apache-2.0 # Metrics and style coverage!=4.4,>=4.0 # Apache-2.0 ddt>=1.0.1 # MIT requests-mock>=1.2.0 # Apache-2.0 python-zaqarclient-1.11.0/doc/0000775000175000017500000000000013364112773016224 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/doc/requirements.txt0000666000175000017500000000057713364112605021515 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD os-client-config>=1.28.0 # Apache-2.0 openstackdocstheme>=1.18.1 # Apache-2.0 reno>=2.5.0 # Apache-2.0 requests-mock>=1.2.0 # Apache-2.0 python-zaqarclient-1.11.0/doc/README.md0000666000175000017500000000013213364112605017473 0ustar zuulzuul00000000000000Zaqar service's python library documentation ============================================ python-zaqarclient-1.11.0/doc/source/0000775000175000017500000000000013364112773017524 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/doc/source/command/0000775000175000017500000000000013364112773021142 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/doc/source/command/flavor.rst0000777000175000017500000000725413364112605023174 0ustar zuulzuul00000000000000Flavor ====== For help on a specific :command:`openstack messaging flavor` command, enter: .. code-block:: console $ openstack messaging flavor COMMAND -h/--help The five commands: .. code-block:: console messaging flavor create messaging flavor delete messaging flavor list messaging flavor show messaging flavor update .. _openstack_messaging_flavor_create: openstack messaging flavor create --------------------------------- .. code-block:: console usage: openstack messaging flavor create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--capabilities ] Create a pool flavor. **Positional arguments:** ```` Name of the flavor. ```` Pool group for flavor. **Optional arguments:** ``--capabilities `` Describes flavor-specific capabilities, This option is only available in client api version < 2. .. _openstack_messaging_flavor_delete: openstack messaging flavor delete --------------------------------- .. code-block:: console usage: openstack messaging flavor delete [-h] Delete a pool flavor. **Positional arguments:** ```` Name of the flavor. .. _openstack_messaging_flavor_list: openstack messaging flavor list ------------------------------- .. code-block:: console usage: openstack messaging flavor list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] [--detailed ] List available pool flavors. **Optional arguments:** ``--marker `` Flavor's paging marker. ``--limit `` Page size limit. ``--detailed `` If show detailed capabilities of flavor. .. _openstack_messaging_flavor_show: openstack messaging flavor show ------------------------------- .. code-block:: console usage: openstack messaging flavor show [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Display flavor details. **Positional arguments:** ```` Flavor to display (name). .. _openstack_messaging_flavor_update: openstack messaging flavor update --------------------------------- .. code-block:: console usage: openstack messaging flavor update [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--pool_group ] [--capabilities ] Update a pool flavor's attributes. **Positional arguments:** ```` Name of the flavor. **Optional arguments:** ``--pool_group `` Pool group the flavor sits on. ``--capabilities `` Describes flavor-specific capabilities. python-zaqarclient-1.11.0/doc/source/command/ping.rst0000666000175000017500000000111113364112605022617 0ustar zuulzuul00000000000000Ping ==== For help on a specific :command:`openstack messaging ping` command, enter: .. code-block:: console $ openstack messaging ping COMMAND -h/--help The one command: .. code-block:: console messaging ping .. _openstack_messaging_ping: openstack messaging ping ------------------------ .. code-block:: console usage: openstack messaging ping [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Check if Zaqar server is alive or not. python-zaqarclient-1.11.0/doc/source/command/subscription.rst0000666000175000017500000001612313364112605024417 0ustar zuulzuul00000000000000Subscription ============ For help on a specific :command:`openstack subscription` command, enter: .. code-block:: console $ openstack subscription COMMAND -h/--help The ten commands: .. code-block:: console subscription create messaging subscription create subscription delete messaging subscription delete subscription list messaging subscription list subscription show messaging subscription show subscription update messaging subscription update .. _openstack_subscription_create: openstack subscription create ----------------------------- .. code-block:: console usage: openstack subscription create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--options ] Create a subscription. **Positional arguments:** ```` Name of the queue. ```` Subscriber which will be notified. ```` Time to live of the subscription in seconds. .. _openstack_messaging_subscription_create: openstack messaging subscription create --------------------------------------- .. code-block:: console usage: openstack messaging subscription create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--options ] Create a subscription. **Positional arguments:** ```` Name of the queue. ```` Subscriber which will be notified. ```` Time to live of the subscription in seconds. .. _openstack_subscription_delete: openstack subscription delete ----------------------------- .. code-block:: console usage: openstack subscription delete [-h] Delete a subscription. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription. .. _openstack_messaging_subscription_delete: openstack messaging subscription delete --------------------------------------- .. code-block:: console usage: openstack messaging subscription delete [-h] Delete a subscription. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription. .. _openstack_subscription_list: openstack subscription list --------------------------- .. code-block:: console usage: openstack subscription list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] Get list of subscriptions. **Positional arguments:** ```` Name of the queue. .. _openstack_messaging_subscription_list: openstack messaging subscription list ------------------------------------- .. code-block:: console usage: openstack messaging subscription list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] Get list of subscriptions. **Positional arguments:** ```` Name of the queue. .. _openstack_subscription_show: openstack subscription show --------------------------- .. code-block:: console usage: openstack subscription show [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Query a subscription details. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription. .. _openstack_messaging_subscription_show: openstack messaging subscription show ------------------------------------- .. code-block:: console usage: openstack messaging subscription show [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Query a subscription details. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription. .. _openstack_subscription_update: openstack subscription update ----------------------------- .. code-block:: console usage: openstack subscription update [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--subscriber ] [--ttl ] [--options ] Update a subscription. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription **Optional arguments:** ``--subscriber `` Subscriber which will be notified. ``--ttl `` Time to live of the subscription in seconds. ``--options `` Metadata of the subscription in JSON format. .. _openstack_messaging_subscription_update: openstack messaging subscription update --------------------------------------- .. code-block:: console usage: openstack messaging subscription update [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--subscriber ] [--ttl ] [--options ] Update a subscription. **Positional arguments:** ```` Name of the queue. ```` ID of the subscription **Optional arguments:** ``--subscriber `` Subscriber which will be notified. ``--ttl `` Time to live of the subscription in seconds. ``--options `` Metadata of the subscription in JSON format. python-zaqarclient-1.11.0/doc/source/command/health.rst0000666000175000017500000000067013364112605023140 0ustar zuulzuul00000000000000Health ====== For help on a specific :command:`openstack messaging health` command, enter: .. code-block:: console $ openstack messaging health COMMAND -h/--help The one command: .. code-block:: console messaging health .. _openstack_messaging_health: openstack messaging health -------------------------- .. code-block:: console usage: openstack messaging health [-h] Display detailed health status of Zaqar server. python-zaqarclient-1.11.0/doc/source/command/claim.rst0000666000175000017500000001231013364112605022752 0ustar zuulzuul00000000000000Claim ===== For help on a specific :command:`openstack claim` command, enter: .. code-block:: console $ openstack claim COMMAND -h/--help The eight commands: .. code-block:: console claim create messaging claim create claim query messaging claim query claim release messaging claim release claim renew messaging claim renew .. _openstack_claim_create: openstack claim create ---------------------- .. code-block:: console usage: openstack claim create [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--ttl ] [--grace ] [--limit ] Create claim and return a list of claimed messages. **Positional arguments:** ```` Name of the queue to be claim. **Optional arguments:** ``--ttl `` Time to live in seconds for claim. ``--grace `` The message grace period in seconds. ``--limit `` Claims a set of messages, up to limit. .. _openstack_messaging_claim_create: openstack messaging claim create -------------------------------- .. code-block:: console usage: openstack messaging claim create [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--ttl ] [--grace ] [--limit ] Create claim and return a list of claimed messages. **Positional arguments:** ```` Name of the queue to be claim. **Optional arguments:** ``--ttl `` Time to live in seconds for claim. ``--grace `` The message grace period in seconds. ``--limit `` Claims a set of messages, up to limit. .. _openstack_claim_query: openstack claim query --------------------- .. code-block:: console usage: openstack claim query [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] Display claim details. **Positional arguments:** ```` Name of the claimed queue. ```` ID of the claim. .. _openstack_messaging_claim_query: openstack messaging claim query ------------------------------- .. code-block:: console usage: openstack messaging claim query [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] Display claim details. **Positional arguments:** ```` Name of the claimed queue. ```` ID of the claim. .. _openstack_claim_release: openstack claim release ----------------------- .. code-block:: console usage: openstack claim release [-h] Delete a claim. **Positional arguments:** ```` Name of the claimed queue. ```` Claim ID to delete. .. _openstack_messaging_claim_release: openstack messaging claim release --------------------------------- .. code-block:: console usage: openstack messaging claim release [-h] Delete a claim. **Positional arguments:** ```` Name of the claimed queue. ```` Claim ID to delete. .. _openstack_claim_renew: openstack claim renew --------------------- .. code-block:: console usage: openstack claim renew [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--ttl ] [--grace ] Renew a claim. **Positional arguments:** ```` Name of the claimed queue. ```` Claim ID. **Optional arguments:** ``--ttl `` Time to live in seconds for claim. ``--grace `` The message grace period in seconds. .. _openstack_messaging_claim_renew: openstack messaging claim renew ------------------------------- .. code-block:: console usage: openstack messaging claim renew [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--ttl ] [--grace ] Renew a claim. **Positional arguments:** ```` Name of the claimed queue. ```` Claim ID. **Optional arguments:** ``--ttl `` Time to live in seconds for claim. ``--grace `` The message grace period in seconds. python-zaqarclient-1.11.0/doc/source/command/queue.rst0000666000175000017500000002273013364112605023020 0ustar zuulzuul00000000000000Queue ===== For help on a specific :command:`openstack queue` command, enter: .. code-block:: console $ openstack queue COMMAND -h/--help The fourteen commands: .. code-block:: console queue create messaging queue create queue delete messaging queue delete queue get metadata messaging queue get metadata queue list messaging queue list queue set metadata messaging queue set metadata queue signed url messaging queue signed url queue stats messaging queue stats .. _openstack_queue_create: openstack queue create ---------------------- .. code-block:: console usage: openstack queue create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Create a queue. **Positional arguments:** ```` Name of the queue. .. _openstack_messaging_queue_create: openstack messaging queue create -------------------------------- .. code-block:: console usage: openstack messaging queue create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Create a queue. **Positional arguments:** ```` Name of the queue. .. _openstack_queue_delete: openstack queue delete ---------------------- .. code-block:: console usage: openstack queue delete [-h] Delete a queue. **Positional arguments:** ```` Name of the queue. .. _openstack_messaging_queue_delete: openstack messaging queue delete -------------------------------- .. code-block:: console usage: openstack messaging queue delete [-h] Delete a queue. **Positional arguments:** ```` Name of the queue. .. _openstack_queue_get_metadata: openstack queue get metadata ---------------------------- .. code-block:: console usage: openstack queue get metadata [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Get queue metadata. **Positional arguments:** ```` Name of the queue. .. _openstack_messaging_queue_get_metadata: openstack messaging queue get metadata -------------------------------------- .. code-block:: console usage: openstack messaging queue get metadata [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Get queue metadata. **Positional arguments:** ```` Name of the queue. .. _openstack_queue_list: openstack queue list -------------------- .. code-block:: console usage: openstack queue list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] [--detailed] List available queues. **Optional arguments:** ``--marker `` Queue's paging marker. ``--limit `` Page size limit. ``--detailed`` If show detailed information of queue. .. _openstack_messaging_queue_list: openstack messaging queue list ------------------------------ .. code-block:: console usage: openstack messaging queue list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] [--detailed] List available queues. **Optional arguments:** ``--marker `` Queue's paging marker. ``--limit `` Page size limit. ``--detailed`` If show detailed information of queue. .. _openstack_queue_set_metadata: openstack queue set metadata ---------------------------- .. code-block:: console usage: openstack queue set metadata [-h] Set queue metadata. **Positional arguments:** ```` Name of the queue. ```` Queue metadata. It should be json like. For example: '{"age": 18}' .. _openstack_messaging_queue_set_metadata: openstack messaging queue set metadata -------------------------------------- .. code-block:: console usage: openstack messaging queue set metadata [-h] Set queue metadata.All the metadata of the queue will be replaced by queue_metadata. **Positional arguments:** ```` Name of the queue. ```` Queue metadata. It should be json like. For example: '{"age": 18}' .. _openstack_queue_signed_url: openstack queue signed url -------------------------- .. code-block:: console usage: openstack queue signed url [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--paths ] [--ttl-seconds ] [--methods ] Create a pre-signed url for the queue. **Positional arguments:** ```` Name of the queue. **Optional arguments:** ``--paths `` Allowed paths in a comma-separated list. Options: messages, subscriptions, claims. ``--ttl-seconds `` Length of time (in seconds) until the signature expires. ``--methods `` HTTP methods to allow as a comma-separated list. Options: GET, HEAD, OPTIONS, POST, PUT, DELETE. .. _openstack_messaging_queue_signed_url: openstack messaging queue signed url ------------------------------------ .. code-block:: console usage: openstack messaging queue signed url [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--paths ] [--ttl-seconds ] [--methods ] Create a pre-signed url for the queue. **Positional arguments:** ```` Name of the queue. **Optional arguments:** ``--paths `` Allowed paths in a comma-separated list. Options: messages, subscriptions, claims. ``--ttl-seconds `` Length of time (in seconds) until the signature expires. ``--methods `` HTTP methods to allow as a comma-separated list. Options: GET, HEAD, OPTIONS, POST, PUT, DELETE. .. _openstack_queue_stats: openstack queue stats --------------------- .. code-block:: console usage: openstack queue stats [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Get queue stats. **Positional arguments:** ```` Name of the queue. .. _openstack_messaging_queue_stats: openstack messaging queue stats ------------------------------- .. code-block:: console usage: openstack messaging queue stats [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Get queue stats. **Positional arguments:** ```` Name of the queue. .. _openstack_queue_purge: openstack queue purge --------------------- .. code-block:: console usage: openstack queue purge [-h] [--resource_types ] Purge a queue. All the metadata of the queue will be kept. Use ``--resource_types`` to specify which resource should be pured. If ``--resource_types`` is not specified, all the messages and subscriptions in the queue will be purged by default. **Positional arguments:** ```` Name of the queue. **Optional arguments:** ``--resource_types `` Resource types want to be purged. Support ``messages`` and ``subscriptions``. .. _openstack_messaging_queue_purge: openstack messaging queue purge ------------------------------- .. code-block:: console usage: openstack messaging queue purge [-h] [--resource_types ] Purge a queue. All the metadata of the queue will be kept. Use ``--resource_types`` to specify which resource should be pured. If ``--resource_types`` is not specified, all the messages and subscriptions in the queue will be purged by default. **Positional arguments:** ```` Name of the queue. **Optional arguments:** ``--resource_types `` Resource types want to be purged. Support ``messages`` and ``subscriptions``. python-zaqarclient-1.11.0/doc/source/command/pool.rst0000666000175000017500000001520513364112605022644 0ustar zuulzuul00000000000000Pool ==== For help on a specific :command:`openstack pool` command, enter: .. code-block:: console $ openstack pool COMMAND -h/--help The ten commands: .. code-block:: console pool create messaging pool create pool delete messaging pool delete pool list messaging pool list pool show messaging pool show pool update messaging pool update .. _openstack_pool_create: openstack pool create --------------------- .. code-block:: console usage: openstack pool create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--pool_group ] [--pool_options ] Create a pool. **Positional arguments:** ```` Name of the pool. ```` Storage engine URI. ```` weight of the pool. **Optional arguments:** ``--pool_group `` Group of the pool. ``--pool_options `` An optional request component related to storage-specific options. .. _openstack_messaging_pool_create: openstack messaging pool create ------------------------------- .. code-block:: console usage: openstack messaging pool create [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--pool_group ] [--pool_options ] Create a pool. **Positional arguments:** ```` Name of the pool. ```` Storage engine URI. ```` weight of the pool. **Optional arguments:** ``--pool_group `` Group of the pool. ``--pool_options `` An optional request component related to storage-specific options. .. _openstack_pool_delete: openstack pool delete --------------------- .. code-block:: console usage: openstack pool delete [-h] Delete a pool. **Positional arguments:** ```` Name of the pool. .. _openstack_messaging_pool_delete: openstack messaging pool delete ------------------------------- .. code-block:: console usage: openstack messaging pool delete [-h] Delete a pool. **Positional arguments:** ```` Name of the pool. .. _openstack_pool_list: openstack pool list ------------------- .. code-block:: console usage: openstack pool list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] [--detailed ] List available Pools. **Optional arguments:** ``--marker `` Pool's paging marker. ``--limit `` Page size limit. ``--detailed `` Detailed output. .. _openstack_messaging_pool_list: openstack messaging pool list ----------------------------- .. code-block:: console usage: openstack messaging pool list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [--marker ] [--limit ] [--detailed ] List available Pools. **Optional arguments:** ``--marker `` Pool's paging marker. ``--limit `` Page size limit. ``--detailed `` Detailed output. .. _openstack_pool_show: openstack pool show ------------------- .. code-block:: console usage: openstack pool show [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Display pool details. **Positional arguments:** ```` Pool to display (name). .. _openstack_messaging_pool_show: openstack messaging pool show ----------------------------- .. code-block:: console usage: openstack messaging pool show [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] Display pool details. **Positional arguments:** ```` Pool to display (name). .. _openstack_pool_update: openstack pool update --------------------- .. code-block:: console usage: openstack pool update [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--pool_uri ] [--pool_weight ] [--pool_group ] [--pool_options ] Update a pool attribute. **Positional arguments:** ```` Name of the pool. **Optional arguments:** ``--pool_uri `` Storage engine URI. ``--pool_weight `` Weight of the pool. ``--pool_group `` Group of the pool. ``--pool_options `` An optional request component related to storage-specific options. .. _openstack_messaging_pool_update: openstack messaging pool update ------------------------------- .. code-block:: console usage: openstack messaging pool update [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--prefix PREFIX] [--pool_uri ] [--pool_weight ] [--pool_group ] [--pool_options ] Update a pool attribute. **Positional arguments:** ```` Name of the pool. **Optional arguments:** ``--pool_uri `` Storage engine URI. ``--pool_weight `` Weight of the pool. ``--pool_group `` Group of the pool. ``--pool_options `` An optional request component related to storage-specific options. python-zaqarclient-1.11.0/doc/source/index.rst0000666000175000017500000000637513364112605021374 0ustar zuulzuul00000000000000.. 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. ==================================================== Welcome to the Zaqar-client developer documentation! ==================================================== `Zaqar`_ is a multi-tenant cloud messaging and notification service for web and mobile developers. The service features a ReST API, which developers can use to send messages between various components of their SaaS and mobile applications, by using a variety of communication patterns. Underlying this API is an efficient messaging engine designed with scalability and security in mind. Other OpenStack components can integrate with Zaqar to surface events to end users and to communicate with guest agents that run in the "over-cloud" layer. .. note:: This documentation is generated by the Sphinx toolkit and lives in the Zaqar project source tree. Additional draft and project documentation regarding Zaqar and other components of OpenStack can be found on the `OpenStack Wiki`_, as well as in the user guides found on `docs.openstack.org`_. .. _`Zaqar`: https://wiki.openstack.org/wiki/Zaqar .. _`OpenStack Wiki`: https://wiki.openstack.org/wiki/Main_Page .. _`docs.openstack.org`: https://docs.openstack.org Contents ======== .. toctree:: :maxdepth: 1 client command-line Release Notes ============= New Release Note ---------------- We use reno to publish the release note now. Please see `Release Page`_ for more detail. 0.2.0 ----- * 1934a98 Updated from global requirements * 863371b Allow for authentication in functional tests * b35689d Don't pass `options` to pool creation * 8104ff4 Don't reuse request and transport instances * bf841b5 Pass `group` in pool's functional tests * 2490ed4 Send claims `limit` as a query param * baf6fa7 v1.1 and v2 claims return document not list * 0d80728 Make sure the API version is passed down * 407925c Make v1.1 the default CLI version * 895aad2 Updated from global requirements * 8a81c44 Updated from global requirements * 705ee75 Implement CLI support for flavor * 32a847e Implements CLI for pool * 964443d Raises an error if the queue name is empty * e9a8d01 Added support to pools and flavors * f46979b Removed deprecated 'shard' methods * 1a85f83 Update README to work with release tools 0.1.1 ----- * Fix handling of 1.1 API * Gets 'flavor' data if the resource exists * Gets 'pool' data if the resource exists * Handling exception on 504 Error * Added i18n support * Makes health return True or False * Add reference docs for latest recommended client * Add docs for `Client` instances * Add a read-only property for Queues Indices and tables ------------------ * :ref:`genindex` * :ref:`modindex` * :ref:`search` .. _`Release Page`: https://docs.openstack.org/releasenotes/python-zaqarclient python-zaqarclient-1.11.0/doc/source/command-line.rst0000666000175000017500000000071313364112605022616 0ustar zuulzuul00000000000000============ Command-line ============ This chapter documents the usage of Zaqar Client Command Line with API v2.0. Zaqar client now support some kinds of resources or actions: ``queue``, ``claim``, ``subscription``, ``pool``, ``flavor``, ``ping``, ``health``. Click the Link below for the details. .. toctree:: :maxdepth: 1 command/queue command/claim command/pool command/flavor command/ping command/health command/subscription python-zaqarclient-1.11.0/doc/source/conf.py0000666000175000017500000001761213364112605021026 0ustar zuulzuul00000000000000# 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. # Zaqar documentation build configuration file, created by # sphinx-quickstart on Sat May 1 15:17:47 2010. # # This file is execfile()d with the current directory set # to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('../../')) sys.path.insert(0, os.path.abspath('../')) sys.path.insert(0, os.path.abspath('./')) # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. # They can be extensions coming with Sphinx (named 'sphinx.ext.*') # or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.intersphinx', 'sphinx.ext.graphviz', 'openstackdocstheme', ] # autodoc generation is a bit aggressive and a nuisance # when doing heavy text edit cycles. Execute "export SPHINX_DEBUG=1" # in your terminal to disable todo_include_todos = True # Add any paths that contain templates here, relative to this directory. # Changing the path so that the Hudson build output contains GA code # and the source docs do not contain the code so local, offline sphinx builds # are "clean." #templates_path = [] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'zaqarclient' copyright = u'2010-present, OpenStack Foundation' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # from zaqarclient.version import version_string # The full version, including alpha/beta/rc tags. version = release = version_string # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. unused_docs = [ 'api_ext/rst_extension_template', 'installer', ] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (used for this markup: `text`) to use # for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = False # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['zaqarclient.'] # -- Options for man page output ---------------------------------------------- # Grouping the document tree for man pages. # List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # Must set this variable to include year, month, day, hours, and minutes. html_last_updated_fmt = '%Y-%m-%d %H:%M' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'zaqarclientdoc' # -- Options for LaTeX output ------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', 'Zaqarclient.tex', u'Zaqar Library Documentation', u'Anso Labs, LLC', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True # -- Options for openstackdocstheme ------------------------------------------- repository_name = 'openstack/python-zaqarclient' bug_project = 'python-zaqarclient' bug_tag = '' python-zaqarclient-1.11.0/doc/source/client.rst0000666000175000017500000000057113364112605021533 0ustar zuulzuul00000000000000------ Client ------ .. automodule:: zaqarclient.queues.client .. currentmodule:: zaqarclient.queues.client Client Object Reference ----------------------- This is the reference documentation for all API version. API v1 and v1.1: .. autoclass:: zaqarclient.queues.v1.client.Client :members: API v2.0: .. autoclass:: zaqarclient.queues.v2.client.Client :members: python-zaqarclient-1.11.0/.stestr.conf0000666000175000017500000000012113364112605017716 0ustar zuulzuul00000000000000[DEFAULT] test_path=${OS_TEST_PATH:-./tests/} top_dir=./ group_regex=([^\.]+\.)+ python-zaqarclient-1.11.0/PKG-INFO0000664000175000017500000001122113364112773016551 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-zaqarclient Version: 1.11.0 Summary: Client Library for OpenStack Zaqar Messaging API Home-page: https://docs.openstack.org/python-zaqarclient/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/tc/badges/python-zaqarclient.svg :target: http://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Python Zaqar Client =================== .. image:: https://img.shields.io/pypi/v/python-zaqarclient.svg :target: https://pypi.org/project/python-zaqarclient/ :alt: Latest Version :Wiki: `Zaqar Wiki`_ :Launchpad: `Zaqar Launchpad`_ :Review: `Code Review`_ :Design: `Client Wiki`_ :IRC: #openstack-zaqar @ freenode Welcome to the `Zaqar`_ Python Client project! Installation ------------ The latest stable release can be installed from PyPI:: pip install --upgrade python-zaqarclient For the adventurous, you may also install the latest code directly from git .openstack.org:: pip install git+https://git.openstack.org/openstack/python-zaqarclient.git What's in the box ----------------- By installing python-zaqarclient you get programmatic access to the Zaqar v1.0 API library. Plus, it installs a plugin to python-openstackclient that allows you to perform simple queue operations. How to use ========== Python client ------------- Details about design, features, usage and workflow can be found in the `Python Client Wiki`_. .. _Python Client Wiki: https://wiki.openstack.org/wiki/Zaqar/PythonClient Command line interface ---------------------- Zaqar bases its client implementation in the `OpenStack Client`_. It can be installed and configured by following the instructions in *Getting Started* and *Configuration* in the `OpenStack Client Readme`_ respectively. The CLI currently allows creation, removal and listing of queues. Some examples are:: $ openstack queue list --limit 3 $ openstack queue create myqueue $ openstack queue delete myqueue .. _`OpenStack Client`: https://git.openstack.org/cgit/openstack/python-openstackclient .. _`OpenStack Client Readme`: https://git.openstack.org/cgit/openstack/python-openstackclient/tree/README.rst Contributing ============ Be sure to reference the `HACKING`_ file for details on coding style. You may also wish to read through Zaqar's `Contributor Guide`_ before contributing your first patch. .. _Zaqar: https://git.openstack.org/cgit/openstack/zaqar .. _HACKING: https://git.openstack.org/cgit/openstack/python-zaqarclient/tree/HACKING.rst .. _Zaqar Wiki: https://wiki.openstack.org/wiki/Zaqar .. _Contributor Guide: https://wiki.openstack.org/wiki/Zaqar#Contributor_Guide .. _Zaqar Launchpad: https://launchpad.net/zaqar .. _Code Review: https://review.openstack.org/#/q/status:open+project:openstack/python-zaqarclient,n,z .. _Client Wiki: https://wiki.openstack.org/wiki/Python_Zaqar_Client * License: Apache License, Version 2.0 * `PyPi`_ - package installation * `Bugs`_ - issue tracking * `Source`_ .. _PyPi: https://pypi.org/project/python-zaqarclient .. _Bugs: https://bugs.launchpad.net/python-zaqarclient .. _Source: https://git.openstack.org/cgit/openstack/python-zaqarclient Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 python-zaqarclient-1.11.0/releasenotes/0000775000175000017500000000000013364112773020150 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/releasenotes/source/0000775000175000017500000000000013364112773021450 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/releasenotes/source/rocky.rst0000666000175000017500000000022113364112606023321 0ustar zuulzuul00000000000000=================================== Rocky Series Release Notes =================================== .. release-notes:: :branch: stable/rocky python-zaqarclient-1.11.0/releasenotes/source/ocata.rst0000666000175000017500000000023013364112606023261 0ustar zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata python-zaqarclient-1.11.0/releasenotes/source/pike.rst0000666000175000017500000000021713364112606023127 0ustar zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike python-zaqarclient-1.11.0/releasenotes/source/index.rst0000666000175000017500000000152413364112606023310 0ustar zuulzuul00000000000000=========================== Zaqar Client Release Notes =========================== .. toctree:: :maxdepth: 1 unreleased rocky queens pike ocata OpenStack Releases ------------------ The ZaqarClient release that was current when the corresponding OpenStack release was made is shown below: ================= =================== OpenStack Release ZaqarClient Release ================= =================== Rocky 1.10.0 Queens 1.9.0 Pike 1.7.0 Ocata 1.4.0 Newton 1.2.0 ================= =================== Further details for historical OpenStack releases are found at the `OpenStack Releases`_ page. .. _`OpenStack Releases`: https://releases.openstack.org/ Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` python-zaqarclient-1.11.0/releasenotes/source/unreleased.rst0000666000175000017500000000012613364112606024325 0ustar zuulzuul00000000000000===================== Current Release Notes ===================== .. release-notes:: python-zaqarclient-1.11.0/releasenotes/source/conf.py0000666000175000017500000002163013364112606022746 0ustar zuulzuul00000000000000# 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. # Zaqar-Client documentation build configuration file, created by # sphinx-quickstart on Tue Dec 20 11:53:00 2016. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'openstackdocstheme', 'reno.sphinxext', ] # Add any paths that contain templates here, relative to this directory. # templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'ZaqarClientReleaseNotes' copyright = u'2016, OpenStack Foundation' # Release notes are version independent. # The short X.Y version. version = '' # The full version, including alpha/beta/rc tags. release = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'ZaqarClientReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- # The item in latex_elements: # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', latex_elements = {} # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'ZaqarClientReleaseNotes.tex', u'ZaqarClient ReleaseNotes Documentation', u'OpenStack Foundation', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'ZaqarClientReleaseNotes', u'ZaqarClient ReleaseNotes Documentation', [u'OpenStack Foundation'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'ZaqarClientReleaseNotes', u'ZaqarClient ReleaseNotes Documentation', u'OpenStack Foundation', 'ZaqarClientReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] # -- Options for openstackdocstheme ------------------------------------------- repository_name = 'openstack/python-zaqarclient' bug_project = 'python-zaqarclient' bug_tag = '' python-zaqarclient-1.11.0/releasenotes/source/queens.rst0000666000175000017500000000022313364112606023474 0ustar zuulzuul00000000000000=================================== Queens Series Release Notes =================================== .. release-notes:: :branch: stable/queens python-zaqarclient-1.11.0/releasenotes/notes/0000775000175000017500000000000013364112773021300 5ustar zuulzuul00000000000000python-zaqarclient-1.11.0/releasenotes/notes/support-SSL-and-insecure-9b2bbec12b76bf7f.yaml0000666000175000017500000000030613364112606031343 0ustar zuulzuul00000000000000--- features: - Zaqar client now support SSL and insecure for the request. [Blueprint `support-ssl-insecure `_] python-zaqarclient-1.11.0/releasenotes/notes/support-session-c3f81233e03dacc8.yaml0000666000175000017500000000013413364112606027641 0ustar zuulzuul00000000000000--- features: - Now Zaqar client supports using keystone session to init "Client" object. python-zaqarclient-1.11.0/releasenotes/notes/support-doc-f12538ac5f35a282.yaml0000666000175000017500000000027713364112606026600 0ustar zuulzuul00000000000000--- features: - Zaqar client has the doc page now. The link will work after a new release. [Link `python-zaqarclient doc page `_] python-zaqarclient-1.11.0/releasenotes/notes/keystoneclient-to-keystoneauth-85c5f098bd023030.yaml0000666000175000017500000000040513364112606032430 0ustar zuulzuul00000000000000--- features: - The auth mechanism has been upgraded from keystone client to keystoneauth to support keystone V3. [Blueprint `keystoneclient-to-keystoneauth `_] python-zaqarclient-1.11.0/releasenotes/notes/support-osprofiler-41af30da3bee5ed0.yaml0000666000175000017500000000027413364112606030500 0ustar zuulzuul00000000000000--- features: - Support to create profiling traces for Zaqar. To use this feature, Zaqar should enable it first. The command is like "openstack --os-profile queue list" python-zaqarclient-1.11.0/releasenotes/notes/consistent-command-format-82df852b384bd284.yaml0000666000175000017500000000036013364112606031420 0ustar zuulzuul00000000000000--- fixes: - Change zaqarclient command to keep the same format like other project does. the consistent command format is 'openstack messaging XXX'. Marks those old commands as deprecated and will remove them after Queen release. python-zaqarclient-1.11.0/releasenotes/notes/support-post-list-messages-cc224643840a1242.yaml0000666000175000017500000000021713364112606031414 0ustar zuulzuul00000000000000--- features: - | Allow post and list messages with CLI so that user can easily verify Zaqar's messaging functions with command line.python-zaqarclient-1.11.0/releasenotes/notes/support-detailed-queue-list-0335b3ebde115bfd.yaml0000666000175000017500000000031613364112606032101 0ustar zuulzuul00000000000000--- features: - Support 'openstack queue list --detailed' in openstackclient to query the detailed queue list from Zaqar server. The detailed information includes queue's Name, Metadata and Href. python-zaqarclient-1.11.0/releasenotes/notes/add-validation-for-queue-name-6e417870cc257308.yaml0000666000175000017500000000070313364112606031667 0ustar zuulzuul00000000000000--- fixes: - Fix the creation issue when special meanings words in queue name. When using zaqarclient to create a queue with some special meanings words like "#" and "%", then cli will return the queue with the name has created successfully, but in zaqar server side, the name is not as same as the client side. Add the check for some special meanings words, it will raise error message when using those words in queue name. python-zaqarclient-1.11.0/releasenotes/notes/remove_os_prefix-14fc4a97527dee81.yaml0000666000175000017500000000035613364112606027765 0ustar zuulzuul00000000000000--- fixes: - The "os" prefix for project id has been dropped to keep the same with OpenStack and Keystone Client. To keep the backwards compatibility, the "os" prefix still can be used. And it'll be removed in the next release.