From ac800de3e00b96008028694d44e02337491261b0 Mon Sep 17 00:00:00 2001 From: hwang Date: Tue, 23 Sep 2025 10:27:17 -0700 Subject: [PATCH] Remove support for V1.1 APIs from Zaqar 3 This patch will remove wsgi apis from code tree Change-Id: I4966ba7d15ae86566dffed7b6c95e4bd4f01bc3a Signed-off-by: Hao Wang Depends-On: https://review.opendev.org/c/openstack/zaqar-tempest-plugin/+/962231 --- zaqar/tests/functional/wsgi/v1_1/__init__.py | 0 .../tests/functional/wsgi/v1_1/test_claims.py | 276 --------- .../tests/functional/wsgi/v1_1/test_health.py | 84 --- .../functional/wsgi/v1_1/test_messages.py | 527 ------------------ .../tests/functional/wsgi/v1_1/test_pools.py | 234 -------- .../tests/functional/wsgi/v1_1/test_queues.py | 351 ------------ .../tests/unit/transport/wsgi/test_version.py | 19 +- zaqar/transport/wsgi/driver.py | 3 - zaqar/transport/wsgi/v1_1/__init__.py | 129 ----- zaqar/transport/wsgi/v1_1/claims.py | 199 ------- zaqar/transport/wsgi/v1_1/flavors.py | 203 ------- zaqar/transport/wsgi/v1_1/health.py | 39 -- zaqar/transport/wsgi/v1_1/homedoc.py | 292 ---------- zaqar/transport/wsgi/v1_1/messages.py | 368 ------------ zaqar/transport/wsgi/v1_1/ping.py | 30 - zaqar/transport/wsgi/v1_1/pools.py | 251 --------- zaqar/transport/wsgi/v1_1/queues.py | 161 ------ zaqar/transport/wsgi/v1_1/stats.py | 73 --- zaqar/transport/wsgi/version.py | 2 - 19 files changed, 1 insertion(+), 3240 deletions(-) delete mode 100644 zaqar/tests/functional/wsgi/v1_1/__init__.py delete mode 100644 zaqar/tests/functional/wsgi/v1_1/test_claims.py delete mode 100644 zaqar/tests/functional/wsgi/v1_1/test_health.py delete mode 100644 zaqar/tests/functional/wsgi/v1_1/test_messages.py delete mode 100644 zaqar/tests/functional/wsgi/v1_1/test_pools.py delete mode 100644 zaqar/tests/functional/wsgi/v1_1/test_queues.py delete mode 100644 zaqar/transport/wsgi/v1_1/__init__.py delete mode 100644 zaqar/transport/wsgi/v1_1/claims.py delete mode 100644 zaqar/transport/wsgi/v1_1/flavors.py delete mode 100644 zaqar/transport/wsgi/v1_1/health.py delete mode 100644 zaqar/transport/wsgi/v1_1/homedoc.py delete mode 100644 zaqar/transport/wsgi/v1_1/messages.py delete mode 100644 zaqar/transport/wsgi/v1_1/ping.py delete mode 100644 zaqar/transport/wsgi/v1_1/pools.py delete mode 100644 zaqar/transport/wsgi/v1_1/queues.py delete mode 100644 zaqar/transport/wsgi/v1_1/stats.py diff --git a/zaqar/tests/functional/wsgi/v1_1/__init__.py b/zaqar/tests/functional/wsgi/v1_1/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/zaqar/tests/functional/wsgi/v1_1/test_claims.py b/zaqar/tests/functional/wsgi/v1_1/test_claims.py deleted file mode 100644 index edcc29e8d..000000000 --- a/zaqar/tests/functional/wsgi/v1_1/test_claims.py +++ /dev/null @@ -1,276 +0,0 @@ -# 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 uuid - -import ddt - -from zaqar.tests.functional import base -from zaqar.tests.functional import helpers - - -@ddt.ddt -class TestClaims(base.V1_1FunctionalTestBase): - """Tests for Claims.""" - - server_class = base.ZaqarServer - - def setUp(self): - super(TestClaims, self).setUp() - - self.headers = helpers.create_zaqar_headers(self.cfg) - self.client.headers = self.headers - - self.queue = uuid.uuid1() - self.queue_url = ("{url}/{version}/queues/{queue}".format( - url=self.cfg.zaqar.url, - version="v1.1", - queue=self.queue)) - - self.client.put(self.queue_url) - - self.claim_url = self.queue_url + '/claims' - self.client.set_base_url(self.claim_url) - - # Post Messages - url = self.queue_url + '/messages' - doc = helpers.create_message_body_v1_1( - messagecount=self.limits.max_messages_per_page) - - for i in range(10): - self.client.post(url, data=doc) - - @ddt.data({}, {'limit': 2}) - def test_claim_messages(self, params): - """Claim messages.""" - message_count = params.get('limit', - self.limits.max_messages_per_claim_or_pop) - - doc = {"ttl": 300, "grace": 100} - - result = self.client.post(params=params, data=doc) - self.assertEqual(201, result.status_code) - self.assertSchema(result.json(), 'claim_create') - - actual_message_count = len(result.json()['messages']) - self.assertMessageCount(actual_message_count, message_count) - - response_headers = set(result.headers.keys()) - self.assertIsSubset(self.headers_response_with_body, response_headers) - - test_claim_messages.tags = ['smoke', 'positive'] - - def test_query_claim(self): - """Query Claim.""" - params = {'limit': 1} - doc = {"ttl": 300, "grace": 100} - - result = self.client.post(params=params, data=doc) - location = result.headers['Location'] - - url = self.cfg.zaqar.url + location - - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - test_query_claim.tags = ['smoke', 'positive'] - - @ddt.data({}, {"grace": 100}) - def test_claim_default_ttl(self, doc): - """Create claim with default TTL and grace values.""" - params = {'limit': 1} - - result = self.client.post(params=params, data=doc) - self.assertEqual(201, result.status_code) - - location = result.headers['Location'] - - url = self.cfg.zaqar.url + location - - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - default_ttl = result.json()['ttl'] - self.assertEqual(self.resource_defaults.claim_ttl, default_ttl) - - test_claim_default_ttl.tags = ['smoke', 'positive'] - - def test_claim_more_than_allowed(self): - """Claim more than max allowed per request. - - Zaqar allows a maximum of 20 messages per claim by default. - """ - params = {"limit": self.limits.max_messages_per_claim_or_pop + 1} - doc = {"ttl": 300, "grace": 100} - - result = self.client.post(params=params, data=doc) - self.assertEqual(400, result.status_code) - - test_claim_more_than_allowed.tags = ['negative'] - - def test_claim_patch(self): - """Update Claim.""" - - # Test Setup - Post Claim - doc = {"ttl": 300, "grace": 400} - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # Patch Claim - claim_location = result.headers['Location'] - url = self.cfg.zaqar.url + claim_location - doc_updated = {"ttl": 300, 'grace': 60} - - result = self.client.patch(url, data=doc_updated) - self.assertEqual(204, result.status_code) - - # verify that the claim TTL is updated - result = self.client.get(url) - new_ttl = result.json()['ttl'] - self.assertEqual(doc_updated['ttl'], new_ttl) - - test_claim_patch.tags = ['smoke', 'positive'] - - def test_delete_claimed_message(self): - """Delete message belonging to a Claim.""" - # Test Setup - Post claim - doc = {"ttl": 60, "grace": 60} - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # Delete Claimed Messages - for rst in result.json()['messages']: - href = rst['href'] - url = self.cfg.zaqar.url + href - result = self.client.delete(url) - self.assertEqual(204, result.status_code) - - test_delete_claimed_message.tags = ['smoke', 'positive'] - - def test_claim_release(self): - """Release Claim.""" - doc = {"ttl": 300, "grace": 100} - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # Extract claim location and construct the claim URL. - location = result.headers['Location'] - url = self.cfg.zaqar.url + location - - # Release Claim. - result = self.client.delete(url) - self.assertEqual(204, result.status_code) - - test_claim_release.tags = ['smoke', 'positive'] - - @ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000) - def test_claim_invalid_ttl(self, ttl): - """Post Claim with invalid TTL. - - The request JSON body will have a TTL value - outside the allowed range.Allowed ttl values is - 60 <= ttl <= 43200. - """ - doc = {"ttl": ttl, "grace": 100} - - result = self.client.post(data=doc) - self.assertEqual(400, result.status_code) - - test_claim_invalid_ttl.tags = ['negative'] - - @ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000) - def test_claim_invalid_grace(self, grace): - """Post Claim with invalid grace. - - The request JSON body will have a grace value - outside the allowed range.Allowed grace values is - 60 <= grace <= 43200. - """ - doc = {"ttl": 100, "grace": grace} - - result = self.client.post(data=doc) - self.assertEqual(400, result.status_code) - - test_claim_invalid_grace.tags = ['negative'] - - @ddt.data(0, -100, 30, 10000000000000000000) - def test_claim_invalid_limit(self, grace): - """Post Claim with invalid limit. - - The request url will have a limit outside the allowed range. - Allowed limit values are 0 < limit <= 20(default max). - """ - doc = {"ttl": 100, "grace": grace} - - result = self.client.post(data=doc) - self.assertEqual(400, result.status_code) - - test_claim_invalid_limit.tags = ['negative'] - - @ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000) - def test_patch_claim_invalid_ttl(self, ttl): - """Patch Claim with invalid TTL. - - The request JSON body will have a TTL value - outside the allowed range.Allowed ttl values is - 60 <= ttl <= 43200. - """ - doc = {"ttl": 100, "grace": 100} - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # Extract claim location and construct the claim URL. - location = result.headers['Location'] - url = self.cfg.zaqar.url + location - - # Patch Claim. - doc = {"ttl": ttl} - result = self.client.patch(url, data=doc) - self.assertEqual(400, result.status_code) - - test_patch_claim_invalid_ttl.tags = ['negative'] - - def test_query_non_existing_claim(self): - """Query Non Existing Claim.""" - path = '/non-existing-claim' - result = self.client.get(path) - self.assertEqual(404, result.status_code) - - test_query_non_existing_claim.tags = ['negative'] - - def test_patch_non_existing_claim(self): - """Patch Non Existing Claim.""" - path = '/non-existing-claim' - doc = {"ttl": 400} - result = self.client.patch(path, data=doc) - self.assertEqual(404, result.status_code) - - test_patch_non_existing_claim.tags = ['negative'] - - def test_delete_non_existing_claim(self): - """Patch Non Existing Claim.""" - path = '/non-existing-claim' - result = self.client.delete(path) - self.assertEqual(204, result.status_code) - - test_delete_non_existing_claim.tags = ['negative'] - - def tearDown(self): - """Delete Queue after Claim Test.""" - super(TestClaims, self).tearDown() - self.client.delete(self.queue_url) diff --git a/zaqar/tests/functional/wsgi/v1_1/test_health.py b/zaqar/tests/functional/wsgi/v1_1/test_health.py deleted file mode 100644 index 5e46a3bbd..000000000 --- a/zaqar/tests/functional/wsgi/v1_1/test_health.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2014 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 zaqar.tests.functional import base -from zaqar.tests.functional import helpers - - -class TestHealth(base.V1_1FunctionalTestBase): - - server_class = base.ZaqarAdminServer - config_file = 'wsgi_mongodb_pooled.conf' - - def setUp(self): - super(TestHealth, self).setUp() - self.base_url = ("{url}/{version}".format( - url=self.cfg.zaqar.url, - version="v1.1" - )) - self.cfg.zaqar.version = "v1.1" - - self.headers = helpers.create_zaqar_headers(self.cfg) - self.client.headers = self.headers - - self.client.set_base_url(self.base_url) - - def test_health_with_pool(self): - # FIXME(flwang): Please use mongodb after the sqlalchemy is disabled - # as pool node and the mongodb is working on gate successfully. - doc = helpers.create_pool_body( - weight=10, - uri=self.mconf['drivers:management_store:mongodb'].uri, - options=dict(database='zaqar_test_pooled_1') - ) - - pool_name = "pool_1" - - result = self.client.put('/pools/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - queue_name = 'fake_queue' - result = self.client.put('/queues/' + queue_name) - self.assertEqual(201, result.status_code) - - sample_messages = {'messages': [ - {'body': 239, 'ttl': 999}, - {'body': {'key': 'value'}, 'ttl': 888} - ]} - - result = self.client.post('/queues/%s/messages' % queue_name, - data=sample_messages) - self.assertEqual(201, result.status_code) - - claim_metadata = {'ttl': 100, 'grace': 300} - - result = self.client.post('/queues/%s/claims' % queue_name, - data=claim_metadata) - self.assertEqual(201, result.status_code) - - response = self.client.get('/health') - self.assertEqual(200, response.status_code) - health = response.json() - - self.assertTrue(health['catalog_reachable']) - self.assertTrue(health[pool_name]['storage_reachable']) - op_status = health[pool_name]['operation_status'] - for op in op_status.keys(): - self.assertTrue(op_status[op]['succeeded']) - - message_volume = health[pool_name]['message_volume'] - self.assertEqual(2, message_volume['claimed']) - self.assertEqual(0, message_volume['free']) - self.assertEqual(2, message_volume['total']) diff --git a/zaqar/tests/functional/wsgi/v1_1/test_messages.py b/zaqar/tests/functional/wsgi/v1_1/test_messages.py deleted file mode 100644 index 3f5521f12..000000000 --- a/zaqar/tests/functional/wsgi/v1_1/test_messages.py +++ /dev/null @@ -1,527 +0,0 @@ -# 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 uuid - -import ddt - -from oslo_serialization import jsonutils - -from zaqar.common import consts -from zaqar.tests.functional import base -from zaqar.tests.functional import helpers - - -@ddt.ddt -class TestMessages(base.V1_1FunctionalTestBase): - """Message Tests Specific to V1.1.""" - - server_class = base.ZaqarServer - - def setUp(self): - super(TestMessages, self).setUp() - - self.queue = uuid.uuid1() # Generate a random queue ID - self.queue_url = ("{url}/{version}/queues/{queue}".format( - url=self.cfg.zaqar.url, - version="v1.1", - queue=self.queue)) - - self.headers = helpers.create_zaqar_headers(self.cfg) - self.client.headers = self.headers - - self.client.put(self.queue_url) # Create the queue - self.message_url = self.queue_url + '/messages' - self.client.set_base_url(self.message_url) - - def tearDown(self): - self.client.delete(self.queue_url) # Remove the queue - super(TestMessages, self).tearDown() - - def _post_large_bulk_insert(self, offset): - """Insert just under than max allowed messages.""" - - message1 = {"body": '', "ttl": 300} - message2 = {"body": '', "ttl": 120} - - doc = {'messages': [message1, message2]} - overhead = len(jsonutils.dumps(doc)) - - half_size = (self.limits.max_messages_post_size - overhead) // 2 - message1['body'] = helpers.generate_random_string(half_size) - message2['body'] = helpers.generate_random_string(half_size + offset) - - return self.client.post(data=doc) - - def test_message_single_insert(self): - """Insert Single Message into the Queue. - - This test also verifies that claimed messages are - retuned (or not) depending on the include_claimed flag. - """ - doc = helpers.create_message_body_v1_1(messagecount=1) - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - response_headers = set(result.headers.keys()) - self.assertIsSubset(self.headers_response_with_body, response_headers) - - # GET on posted message - href = result.json()['resources'][0] - url = self.cfg.zaqar.url + href - - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - # Compare message metadata - result_body = result.json()['body'] - posted_metadata = doc['messages'][0]['body'] - self.assertEqual(posted_metadata, result_body) - - # Post a claim & verify the include_claimed flag. - url = self.queue_url + '/claims' - doc = {"ttl": 300, "grace": 100} - result = self.client.post(url, data=doc) - self.assertEqual(201, result.status_code) - - params = {'include_claimed': True, - 'echo': True} - result = self.client.get(params=params) - self.assertEqual(200, result.status_code) - - response_message_body = result.json()["messages"][0]["body"] - self.assertEqual(posted_metadata, response_message_body) - - # By default, include_claimed = false - result = self.client.get(self.message_url) - self.assertEqual(200, result.status_code) - - test_message_single_insert.tags = ['smoke', 'positive'] - - def test_message_bulk_insert(self): - """Bulk Insert Messages into the Queue.""" - message_count = self.limits.max_messages_per_page - doc = helpers.create_message_body_v1_1(messagecount=message_count) - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # GET on posted messages - location = result.headers['location'] - url = self.cfg.zaqar.url + location - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - # Verify that the response json schema matches the expected schema - self.assertSchema(result.json(), consts.MESSAGE_GET_MANY) - - self.skipTest('Bug #1273335 - Get set of messages returns wrong hrefs ' - '(happens randomly)') - - # Compare message metadata - result_body = [msg['body'] for msg in result.json()['messages']] - result_body.sort() - - posted_metadata = [msg['body'] for msg in doc['messages']] - posted_metadata.sort() - - self.assertEqual(posted_metadata, result_body) - - test_message_bulk_insert.tags = ['smoke', 'positive'] - - def test_message_default_ttl(self): - """Insert Single Message into the Queue using the default TTL.""" - doc = helpers.create_message_body_v1_1(messagecount=1, - default_ttl=True) - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # GET on posted message - href = result.json()['resources'][0] - url = self.cfg.zaqar.url + href - - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - # Compare message metadata - default_ttl = result.json()['ttl'] - self.assertEqual(self.resource_defaults.message_ttl, default_ttl) - - test_message_default_ttl.tags = ['smoke', 'positive'] - - @ddt.data({}, {'limit': 5}) - def test_get_message(self, params): - """Get Messages.""" - - # Note(abettadapur): This will now return 200s and []. - # Needs to be addressed when feature patch goes in - self.skipTest("Not supported") - expected_msg_count = params.get('limit', - self.limits.max_messages_per_page) - - # Test Setup - doc = helpers.create_message_body_v1_1( - messagecount=self.limits.max_messages_per_page) - - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - url = '' - params['echo'] = True - - # Follow the hrefs & perform GET, till the end of messages i.e. http - # 204 - while result.status_code in [201, 200]: - result = self.client.get(url, params=params) - self.assertIn(result.status_code, [200, 204]) - - if result.status_code == 200: - actual_msg_count = len(result.json()['messages']) - self.assertMessageCount(actual_msg_count, expected_msg_count) - - href = result.json()['links'][0]['href'] - url = self.cfg.zaqar.url + href - - self.assertEqual(204, result.status_code) - - test_get_message.tags = ['smoke', 'positive'] - - def test_message_delete(self): - """Delete Message.""" - # Test Setup - doc = helpers.create_message_body_v1_1(messagecount=1) - result = self.client.post(data=doc) - self.assertEqual(201, result.status_code) - - # Delete posted message - href = result.json()['resources'][0] - url = self.cfg.zaqar.url + href - - result = self.client.delete(url) - self.assertEqual(204, result.status_code) - - result = self.client.get(url) - self.assertEqual(404, result.status_code) - - test_message_delete.tags = ['smoke', 'positive'] - - def test_message_bulk_delete(self): - """Bulk Delete Messages.""" - doc = helpers.create_message_body_v1_1(messagecount=10) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Delete posted messages - location = result.headers['Location'] - url = self.cfg.zaqar.url + location - - result = self.client.delete(url) - self.assertEqual(204, result.status_code) - - result = self.client.get(url) - self.assertEqual(404, result.status_code) - - test_message_bulk_delete.tags = ['smoke', 'positive'] - - def test_message_delete_nonexisting(self): - """Delete non-existing Messages.""" - result = self.client.delete('/non-existing') - - self.assertEqual(204, result.status_code) - - test_message_delete_nonexisting.tags = ['negative'] - - def test_message_partial_delete(self): - """Delete Messages will be partially successful.""" - doc = helpers.create_message_body_v1_1(messagecount=3) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Delete posted message - location = result.headers['Location'] - url = self.cfg.zaqar.url + location - url += ',nonexisting' - result = self.client.delete(url) - self.assertEqual(204, result.status_code) - - test_message_partial_delete.tags = ['negative'] - - @ddt.data(5, 1) - def test_messages_pop(self, limit=5): - """Pop messages from a queue.""" - doc = helpers.create_message_body_v1_1(messagecount=limit) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Pop messages - url = self.message_url + '?pop=' + str(limit) - - result = self.client.delete(url) - self.assertEqual(200, result.status_code) - - params = {'echo': True} - - result = self.client.get(self.message_url, params=params) - self.assertEqual(200, result.status_code) - - messages = result.json()['messages'] - self.assertEqual([], messages) - - test_messages_pop.tags = ['smoke', 'positive'] - - @ddt.data(10000000, 0, -1) - def test_messages_pop_invalid(self, limit): - """Pop messages from a queue.""" - doc = helpers.create_message_body_v1_1( - messagecount=self.limits.max_messages_per_page) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Pop messages - url = self.message_url + '?pop=' + str(limit) - - result = self.client.delete(url) - self.assertEqual(400, result.status_code) - - params = {'echo': True} - result = self.client.get(self.message_url, params=params) - self.assertEqual(200, result.status_code) - - messages = result.json()['messages'] - self.assertNotEqual(messages, []) - - test_messages_pop_invalid.tags = ['smoke', 'negative'] - - def test_messages_delete_pop_and_id(self): - """Delete messages with pop & id params in the request.""" - doc = helpers.create_message_body_v1_1( - messagecount=1) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - location = result.headers['Location'] - - # Pop messages - url = self.cfg.zaqar.url + location + '&pop=1' - - result = self.client.delete(url) - self.assertEqual(400, result.status_code) - - params = {'echo': True} - - result = self.client.get(self.message_url, params=params) - self.assertEqual(200, result.status_code) - - messages = result.json()['messages'] - self.assertNotEqual(messages, []) - - test_messages_delete_pop_and_id.tags = ['smoke', 'negative'] - - def test_messages_pop_empty_queue(self): - """Pop messages from an empty queue.""" - url = self.message_url + '?pop=2' - - result = self.client.delete(url) - self.assertEqual(200, result.status_code) - - messages = result.json()['messages'] - self.assertEqual([], messages) - - test_messages_pop_empty_queue.tags = ['smoke', 'positive'] - - def test_messages_pop_one(self): - """Pop single messages from a queue.""" - doc = helpers.create_message_body_v1_1( - messagecount=self.limits.max_messages_per_page) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Pop Single Message - url = self.message_url + '?pop=1' - - result = self.client.delete(url) - self.assertEqual(200, result.status_code) - - # Get messages from the queue & verify message count - params = {'echo': True, 'limit': self.limits.max_messages_per_page} - - result = self.client.get(self.message_url, params=params) - self.assertEqual(200, result.status_code) - - expected_msg_count = self.limits.max_messages_per_page - 1 - actual_msg_count = len(result.json()['messages']) - self.assertEqual(expected_msg_count, actual_msg_count) - - test_messages_pop_one.tags = ['smoke', 'positive'] - - def test_message_partial_get(self): - """Get Messages will be partially successful.""" - doc = helpers.create_message_body_v1_1(messagecount=3) - result = self.client.post(data=doc) - - self.assertEqual(201, result.status_code) - - # Get posted message and a nonexisting message - location = result.headers['Location'] - url = self.cfg.zaqar.url + location - url += ',nonexisting' - result = self.client.get(url) - self.assertEqual(200, result.status_code) - - test_message_partial_get.tags = ['negative'] - - @ddt.data(-10, -1, 0) - def test_message_bulk_insert_large_bodies(self, offset): - """Insert just under than max allowed messages.""" - result = self._post_large_bulk_insert(offset) - self.assertEqual(201, result.status_code) - - test_message_bulk_insert_large_bodies.tags = ['positive'] - - @ddt.data(1, 10) - def test_message_bulk_insert_large_bodies_(self, offset): - """Insert just under than max allowed messages.""" - result = self._post_large_bulk_insert(offset) - self.assertEqual(400, result.status_code) - - test_message_bulk_insert_large_bodies_.tags = ['negative'] - - def test_message_bulk_insert_oversized(self): - """Insert more than max allowed size.""" - - doc = '[{{"body": "{0}", "ttl": 300}}, {{"body": "{1}", "ttl": 120}}]' - overhead = len(doc.format('', '')) - - half_size = (self.limits.max_messages_post_size - overhead) // 2 - doc = doc.format(helpers.generate_random_string(half_size), - helpers.generate_random_string(half_size + 1)) - - result = self.client.post(data=doc) - self.assertEqual(400, result.status_code) - - test_message_bulk_insert_oversized.tags = ['negative'] - - @ddt.data(10000000000000000000, -100, 0, 30, -10000000000000000000) - def test_message_get_invalid_limit(self, limit): - """Get Messages with invalid value for limit. - - Allowed values for limit are 0 < limit <= 20(configurable). - """ - params = {'limit': limit} - result = self.client.get(params=params) - self.assertEqual(400, result.status_code) - - test_message_get_invalid_limit.tags = ['negative'] - - def test_message_bulk_delete_negative(self): - """Delete more messages than allowed in a single request. - - By default, max messages that can be deleted in a single - request is 20. - """ - url = (self.message_url + '?ids=' - + ','.join(str(i) for i in - range(self.limits.max_messages_per_page + 1))) - result = self.client.delete(url) - - self.assertEqual(400, result.status_code) - - test_message_bulk_delete_negative.tags = ['negative'] - - def test_message_bulk_get_negative(self): - """GET more messages by id than allowed in a single request. - - By default, max messages that can be fetched in a single - request is 20. - """ - - url = (self.message_url + '?ids=' - + ','.join(str(i) for i in - range(self.limits.max_messages_per_page + 1))) - - result = self.client.get(url) - - self.assertEqual(400, result.status_code) - - test_message_bulk_get_negative.tags = ['negative'] - - def test_get_messages_malformed_marker(self): - """Get messages with non-existing marker.""" - url = self.message_url + '?marker=invalid' - - result = self.client.get(url, headers=self.headers) - self.assertEqual(200, result.status_code) - self.assertSchema(result.json(), 'message_list') - - test_get_messages_malformed_marker.tags = ['negative'] - - @ddt.data(None, '1234', 'aa2-bb3', - '103e09c6-31b7-11e3-86bc-b8ca3ad0f5d81', - '103e09c6-31b7-11e3-86bc-b8ca3ad0f5d') - def test_get_messages_invalid_client_id(self, client_id): - """Get messages with invalid client id.""" - url = self.message_url - - header = helpers.create_zaqar_headers(self.cfg) - header['Client-ID'] = client_id - - result = self.client.get(url, headers=header) - self.assertEqual(400, result.status_code) - - test_get_messages_invalid_client_id.tags = ['negative'] - - def test_query_non_existing_message(self): - """Get Non Existing Message.""" - path = '/non-existing-message' - result = self.client.get(path) - self.assertEqual(404, result.status_code) - - test_query_non_existing_message.tags = ['negative'] - - def test_query_non_existing_message_set(self): - """Get Set of Non Existing Messages.""" - path = '?ids=not_there1,not_there2' - result = self.client.get(path) - self.assertEqual(404, result.status_code) - - test_query_non_existing_message_set.tags = ['negative'] - - def test_delete_non_existing_message(self): - """Delete Non Existing Message.""" - path = '/non-existing-message' - result = self.client.delete(path) - self.assertEqual(204, result.status_code) - - test_delete_non_existing_message.tags = ['negative'] - - def test_message_bad_header_single_insert(self): - """Insert Single Message into the Queue. - - This should fail because of the lack of a Client-ID header - """ - - self.skipTest("Not supported") - del self.client.headers["Client-ID"] - doc = helpers.create_message_body_v1_1(messagecount=1) - - result = self.client.post(data=doc) - self.assertEqual(400, result.status_code) diff --git a/zaqar/tests/functional/wsgi/v1_1/test_pools.py b/zaqar/tests/functional/wsgi/v1_1/test_pools.py deleted file mode 100644 index 8b8bcfad0..000000000 --- a/zaqar/tests/functional/wsgi/v1_1/test_pools.py +++ /dev/null @@ -1,234 +0,0 @@ -# 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 ddt - -from zaqar import tests as testing -from zaqar.tests.functional import base -from zaqar.tests.functional import helpers - - -@ddt.ddt -class TestPools(base.V1_1FunctionalTestBase): - - server_class = base.ZaqarAdminServer - config_file = 'wsgi_mongodb_pooled.conf' - - @testing.requires_mongodb - def setUp(self): - super(TestPools, self).setUp() - - self.pool_url = ("{url}/{version}/pools".format( - url=self.cfg.zaqar.url, - version="v1.1" - )) - self.cfg.zaqar.version = "v1.1" - - self.headers = helpers.create_zaqar_headers(self.cfg) - self.client.headers = self.headers - - self.client.set_base_url(self.pool_url) - - @ddt.data( - { - 'name': "newpool", - 'weight': 10 - } - ) - def test_insert_pool(self, params): - """Test the registering of one pool.""" - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - # Test existence - result = self.client.get('/' + pool_name) - self.assertEqual(200, result.status_code) - - @ddt.data( - { - 'name': "newpool", - 'weight': 10 - } - ) - def test_pool_details(self, params): - """Get the details of a pool. Assert the respective schema.""" - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - # Test existence - result = self.client.get('/' + pool_name + '?detailed=true') - self.assertEqual(200, result.status_code) - self.assertSchema(result.json(), 'pool_get_detail') - - @ddt.data( - { - 'name': "newpool", - 'weight': 10, - } - ) - def test_delete_pool(self, params): - """Create a pool, then delete it. - - Make sure operation is successful. - """ - - # Create the pool - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - - pool_name = params.get('name', "newpool") - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - # Make sure it exists - result = self.client.get('/' + pool_name) - self.assertEqual(200, result.status_code) - - # Delete it - result = self.client.delete('/' + pool_name) - self.assertEqual(204, result.status_code) - - @ddt.data( - { - 'name': "newpool", - 'weight': 10, - } - ) - def test_list_pools(self, params): - """Add a pool. Get the list of all the pools. - - Assert respective schema - """ - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - result = self.client.get() - self.assertEqual(200, result.status_code) - self.assertSchema(result.json(), 'pool_list') - - @ddt.data( - { - 'name': "newpool", - 'weight': 10, - } - ) - def test_patch_pool(self, params): - """Create a pool. Issue a patch command, - - make sure command was successful. Check details to be sure. - """ - - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - # Update that pool - - patchdoc = helpers.create_pool_body( - weight=5, - uri=self.mongodb_url - ) - result = self.client.patch('/' + pool_name, data=patchdoc) - self.assertEqual(200, result.status_code) - - # Get the pool, check update# - result = self.client.get('/' + pool_name) - self.assertEqual(200, result.status_code) - self.assertEqual(5, result.json()["weight"]) - - @ddt.data( - { - 'name': "newpool", - 'weight': 10, - } - ) - def test_patch_pool_bad_data(self, params): - """Issue a patch command without a body. Assert 400.""" - # create a pool - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(201, result.status_code) - - # Update pool with bad post data. Ensure 400 - result = self.client.patch('/' + pool_name) - self.assertEqual(400, result.status_code) - - @ddt.data( - { - 'name': "newpool", - 'weight': 10, - } - ) - def test_patch_pool_non_exist(self, params): - """Issue patch command to pool that doesn't exist. Assert 404.""" - doc = helpers.create_pool_body( - weight=5, - uri=self.mongodb_url - ) - result = self.client.patch('/nonexistpool', data=doc) - self.assertEqual(404, result.status_code) - - @ddt.data( - {'name': '\u6c49\u5b57\u6f22\u5b57'}, - {'name': 'i' * 65}, - {'weight': -1} - ) - def test_insert_pool_bad_data(self, params): - """Create pools with invalid names and weights. Assert 400.""" - self.skip("FIXME: https://bugs.launchpad.net/zaqar/+bug/1373486") - doc = helpers.create_pool_body( - weight=params.get('weight', 10), - uri=self.mongodb_url - ) - pool_name = params.get('name', "newpool") - self.addCleanup(self.client.delete, url='/' + pool_name) - result = self.client.put('/' + pool_name, data=doc) - self.assertEqual(400, result.status_code) - - def test_delete_pool_non_exist(self): - """Delete a pool that doesn't exist. Assert 404.""" - result = self.client.delete('/nonexistpool') - self.assertEqual(204, result.status_code) diff --git a/zaqar/tests/functional/wsgi/v1_1/test_queues.py b/zaqar/tests/functional/wsgi/v1_1/test_queues.py deleted file mode 100644 index 3f2b32ea0..000000000 --- a/zaqar/tests/functional/wsgi/v1_1/test_queues.py +++ /dev/null @@ -1,351 +0,0 @@ -# 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 uuid - -import ddt - -from zaqar.tests.functional import base -from zaqar.tests.functional import helpers - - -class NamedBinaryStr(bytes): - - """Wrapper for bytes to facilitate overriding __name__.""" - - -class NamedUnicodeStr(str): - - """Unicode string look-alike to facilitate overriding __name__.""" - - def __init__(self, value): - self.value = value - - def __str__(self): - return self.value - - def encode(self, enc): - return self.value.encode(enc) - - def __format__(self, formatstr): - """Workaround for ddt bug. - - DDT will always call __format__ even when __name__ exists, - which blows up for Unicode strings under Py2. - """ - return '' - - -class NamedDict(dict): - - """Wrapper for dict to facilitate overriding __name__.""" - - -def annotated(test_name, test_input): - if isinstance(test_input, dict): - annotated_input = NamedDict(test_input) - elif isinstance(test_input, str): - annotated_input = NamedUnicodeStr(test_input) - else: - annotated_input = NamedBinaryStr(test_input) - - setattr(annotated_input, '__name__', test_name) - return annotated_input - - -@ddt.ddt -class TestInsertQueue(base.V1_1FunctionalTestBase): - - """Tests for Insert queue.""" - - server_class = base.ZaqarServer - - def setUp(self): - super(TestInsertQueue, self).setUp() - self.base_url = '{0}/{1}'.format(self.cfg.zaqar.url, - "v1.1") - - self.header = helpers.create_zaqar_headers(self.cfg) - self.headers_response_empty = {'location'} - self.client.set_base_url(self.base_url) - self.client.headers = self.header - - @ddt.data('qtestqueue', 'TESTqueue', 'hyphen-name', '_undersore', - annotated('test_insert_queue_long_name', 'i' * 64)) - def test_insert_queue(self, queue_name): - """Create Queue.""" - self.url = self.base_url + '/queues/' + queue_name - self.addCleanup(self.client.delete, self.url) - - result = self.client.put(self.url) - self.assertEqual(201, result.status_code) - - response_headers = set(result.headers.keys()) - self.assertIsSubset(self.headers_response_empty, response_headers) - - test_insert_queue.tags = ['positive', 'smoke'] - - @ddt.data(annotated('test_insert_queue_non_ascii_name', - '\u6c49\u5b57\u6f22\u5b57'), - '@$@^qw', - annotated('test_insert_queue_invalid_name_length', 'i' * 65)) - def test_insert_queue_invalid_name(self, queue_name): - """Create Queue.""" - self.url = self.base_url + '/queues/' + queue_name - self.addCleanup(self.client.delete, self.url) - - result = self.client.put(self.url) - self.assertEqual(400, result.status_code) - - test_insert_queue_invalid_name.tags = ['negative'] - - def test_insert_queue_header_plaintext(self): - """Insert Queue with 'Accept': 'plain/text'.""" - path = '/queues/plaintextheader' - self.addCleanup(self.client.delete, path) - - header = {"Accept": 'plain/text'} - result = self.client.put(path, headers=header) - self.assertEqual(406, result.status_code) - - test_insert_queue_header_plaintext.tags = ['negative'] - - def test_insert_queue_header_asterisk(self): - """Insert Queue with 'Accept': '*/*'.""" - path = '/queues/asteriskinheader' - headers = {'Accept': '*/*', - 'Client-ID': str(uuid.uuid4()), - 'X-Project-ID': '518b51ea133c4facadae42c328d6b77b'} - self.addCleanup(self.client.delete, url=path, headers=headers) - - result = self.client.put(path, headers=headers) - self.assertEqual(201, result.status_code) - - test_insert_queue_header_asterisk.tags = ['positive'] - - def test_insert_queue_with_metadata(self): - """Insert queue with a non-empty request body.""" - self.url = self.base_url + '/queues/hasmetadata' - doc = {"queue": "Has Metadata"} - self.addCleanup(self.client.delete, self.url) - result = self.client.put(self.url, data=doc) - - self.assertEqual(201, result.status_code) - - self.url = self.base_url + '/queues/hasmetadata' - result = self.client.get(self.url) - - self.assertEqual(200, result.status_code) - self.assertEqual({"queue": "Has Metadata"}, result.json()) - - test_insert_queue_with_metadata.tags = ['negative'] - - def tearDown(self): - super(TestInsertQueue, self).tearDown() - - -@ddt.ddt -class TestQueueMisc(base.V1_1FunctionalTestBase): - - server_class = base.ZaqarServer - - def setUp(self): - super(TestQueueMisc, self).setUp() - self.base_url = self.cfg.zaqar.url - self.client.set_base_url(self.base_url) - - self.queue_url = self.base_url + ('/{0}/queues/{1}' - .format("v1.1", uuid.uuid1())) - - def test_list_queues(self): - """List Queues.""" - - self.client.put(self.queue_url) - self.addCleanup(self.client.delete, self.queue_url) - - result = self.client.get('/{0}/queues' - .format("v1.1")) - self.assertEqual(200, result.status_code) - self.assertSchema(result.json(), 'queue_list') - - test_list_queues.tags = ['smoke', 'positive'] - - def test_list_queues_detailed(self): - """List Queues with detailed = True.""" - - self.client.put(self.queue_url) - self.addCleanup(self.client.delete, self.queue_url) - - params = {'detailed': True} - result = self.client.get('/{0}/queues' - .format("v1.1"), - params=params) - self.assertEqual(200, result.status_code) - self.assertSchema(result.json(), 'queue_list') - - response_keys = result.json()['queues'][0].keys() - self.assertIn('metadata', response_keys) - - test_list_queues_detailed.tags = ['smoke', 'positive'] - - @ddt.data(0, -1, 1001) - def test_list_queue_invalid_limit(self, limit): - """List Queues with a limit value that is not allowed.""" - - params = {'limit': limit} - result = self.client.get('/{0}/queues' - .format("v1.1"), - params=params) - self.assertEqual(400, result.status_code) - - test_list_queue_invalid_limit.tags = ['negative'] - - def test_check_queue_exists(self): - """Checks if queue exists.""" - - self.client.put(self.queue_url) - self.addCleanup(self.client.delete, self.queue_url) - - result = self.client.head(self.queue_url) - self.assertEqual(405, result.status_code) - - test_check_queue_exists.tags = ['negative'] - - def test_get_queue_malformed_marker(self): - """List queues with invalid marker.""" - - path = '/{0}/queues?marker=zzz'.format("v1.1") - result = self.client.get(path) - self.assertEqual(200, result.status_code) - - test_get_queue_malformed_marker.tags = ['negative'] - - def test_get_stats_empty_queue(self): - """Get queue stats on an empty queue.""" - - result = self.client.put(self.queue_url) - self.addCleanup(self.client.delete, self.queue_url) - self.assertEqual(201, result.status_code) - - stats_url = self.queue_url + '/stats' - - # Get stats on an empty queue - result = self.client.get(stats_url) - self.assertEqual(200, result.status_code) - - expected_response = {'messages': - {'claimed': 0, 'total': 0, 'free': 0}} - self.assertEqual(expected_response, result.json()) - - test_get_stats_empty_queue.tags = ['positive'] - - @ddt.data(0, 1) - def test_get_queue_stats_claimed(self, claimed): - """Get stats on a queue.""" - result = self.client.put(self.queue_url) - self.addCleanup(self.client.delete, self.queue_url) - self.assertEqual(201, result.status_code) - - # Post Messages to the test queue - doc = helpers.create_message_body_v1_1( - messagecount=self.limits.max_messages_per_claim_or_pop) - - message_url = self.queue_url + '/messages' - result = self.client.post(message_url, data=doc) - self.assertEqual(201, result.status_code) - - if claimed > 0: - claim_url = self.queue_url + '/claims?limit=' + str(claimed) - doc = {'ttl': 300, 'grace': 300} - result = self.client.post(claim_url, data=doc) - self.assertEqual(201, result.status_code) - - # Get stats on the queue. - stats_url = self.queue_url + '/stats' - result = self.client.get(stats_url) - self.assertEqual(200, result.status_code) - - self.assertQueueStats(result.json(), claimed) - - test_get_queue_stats_claimed.tags = ['positive'] - - def test_ping_queue(self): - pass - - def tearDown(self): - super(TestQueueMisc, self).tearDown() - - -class TestQueueNonExisting(base.V1_1FunctionalTestBase): - - """Test Actions on non existing queue.""" - - server_class = base.ZaqarServer - - def setUp(self): - super(TestQueueNonExisting, self).setUp() - if self.cfg.version != "v1": - self.skipTest("Not Supported") - - self.base_url = '{0}/{1}'.format(self.cfg.zaqar.url, - "v1.1") - self.queue_url = (self.base_url + - '/queues/0a5b1b85-4263-11e3-b034-28cfe91478b9') - self.client.set_base_url(self.queue_url) - - self.header = helpers.create_zaqar_headers(self.cfg) - self.headers_response_empty = {'location'} - self.header = helpers.create_zaqar_headers(self.cfg) - - def test_get_stats(self): - """Get stats on non existing Queue.""" - result = self.client.get('/stats') - self.assertEqual(200, result.status_code) - self.assertEqual([], result.json()) - - def test_get_metadata(self): - """Get metadata on non existing Queue.""" - result = self.client.get('/') - self.assertEqual(200, result.status_code) - self.assertEqual([], result.json()) - - def test_get_messages(self): - """Get messages on non existing Queue.""" - result = self.client.get('/messages') - self.assertEqual(200, result.status_code) - self.assertEqual([], result.json()) - - def test_post_messages(self): - """Post messages to a non existing Queue.""" - doc = [{"ttl": 200, "body": {"Home": ""}}] - result = self.client.post('/messages', data=doc) - self.assertEqual(201, result.status_code) - - # check existence of queue - result = self.client.get() - self.assertEqual(200, result.status_code) - self.assertNotEqual([], result.json()) - - def test_claim_messages(self): - """Claim messages from a non existing Queue.""" - doc = {"ttl": 200, "grace": 300} - result = self.client.post('/claims', data=doc) - self.assertEqual(200, result.status_code) - self.assertEqual([], result.json()) - - def test_delete_queue(self): - """Delete non existing Queue.""" - result = self.client.delete() - self.assertEqual(204, result.status_code) diff --git a/zaqar/tests/unit/transport/wsgi/test_version.py b/zaqar/tests/unit/transport/wsgi/test_version.py index 7d43a9e1c..52e27e7c7 100644 --- a/zaqar/tests/unit/transport/wsgi/test_version.py +++ b/zaqar/tests/unit/transport/wsgi/test_version.py @@ -19,23 +19,6 @@ from oslo_serialization import jsonutils from zaqar.tests.unit.transport.wsgi import base EXPECTED_VERSIONS = [ - { - 'id': '1.1', - 'status': 'DEPRECATED', - 'updated': '2016-7-29T02:22:47Z', - 'media-types': [ - { - 'base': 'application/json', - 'type': 'application/vnd.openstack.messaging-v1_1+json' - } - ], - 'links': [ - { - 'href': '/v1.1/', - 'rel': 'self' - } - ] - }, { 'id': '2', 'status': 'CURRENT', @@ -65,5 +48,5 @@ class TestVersion(base.TestBase): versions = jsonutils.loads(response[0])['versions'] self.assertEqual(falcon.HTTP_300, self.srmock.status) - self.assertEqual(2, len(versions)) + self.assertEqual(1, len(versions)) self.assertEqual(EXPECTED_VERSIONS, versions) diff --git a/zaqar/transport/wsgi/driver.py b/zaqar/transport/wsgi/driver.py index 66e21fc76..faee97e53 100644 --- a/zaqar/transport/wsgi/driver.py +++ b/zaqar/transport/wsgi/driver.py @@ -32,7 +32,6 @@ from zaqar.transport.middleware import auth from zaqar.transport.middleware import cors from zaqar.transport.middleware import profile from zaqar.transport import validation -from zaqar.transport.wsgi import v1_1 from zaqar.transport.wsgi import v2_0 from zaqar.transport.wsgi import version @@ -108,14 +107,12 @@ class Driver(transport.DriverBase): """Initialize hooks and URI routes to resources.""" catalog = [ - ('/v1.1', v1_1.public_endpoints(self, self._conf)), ('/v2', v2_0.public_endpoints(self, self._conf)), ('/', [('', version.Resource())]) ] if self._conf.admin_mode: catalog.extend([ - ('/v1.1', v1_1.private_endpoints(self, self._conf)), ('/v2', v2_0.private_endpoints(self, self._conf)), ]) diff --git a/zaqar/transport/wsgi/v1_1/__init__.py b/zaqar/transport/wsgi/v1_1/__init__.py deleted file mode 100644 index bec7c5314..000000000 --- a/zaqar/transport/wsgi/v1_1/__init__.py +++ /dev/null @@ -1,129 +0,0 @@ -# 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. - -from oslo_log import log as logging - -from zaqar.common import decorators -from zaqar.transport.wsgi.v1_1 import claims -from zaqar.transport.wsgi.v1_1 import flavors -from zaqar.transport.wsgi.v1_1 import health -from zaqar.transport.wsgi.v1_1 import homedoc -from zaqar.transport.wsgi.v1_1 import messages -from zaqar.transport.wsgi.v1_1 import ping -from zaqar.transport.wsgi.v1_1 import pools -from zaqar.transport.wsgi.v1_1 import queues -from zaqar.transport.wsgi.v1_1 import stats - - -LOG = logging.getLogger(__name__) - - -VERSION = { - 'id': '1.1', - 'status': 'DEPRECATED', - 'updated': '2016-7-29T02:22:47Z', - 'media-types': [ - { - 'base': 'application/json', - 'type': 'application/vnd.openstack.messaging-v1_1+json' - } - ], - 'links': [ - { - 'href': '/v1.1/', - 'rel': 'self' - } - ] -} - - -@decorators.api_version_manager(VERSION) -def public_endpoints(driver, conf): - queue_controller = driver._storage.queue_controller - message_controller = driver._storage.message_controller - claim_controller = driver._storage.claim_controller - - defaults = driver._defaults - - return [ - # Home - ('/', - homedoc.Resource(conf)), - - # Queues Endpoints - ('/queues', - queues.CollectionResource(driver._validate, - queue_controller)), - ('/queues/{queue_name}', - queues.ItemResource(driver._validate, - queue_controller, - message_controller)), - ('/queues/{queue_name}/stats', - stats.Resource(queue_controller)), - - # Messages Endpoints - ('/queues/{queue_name}/messages', - messages.CollectionResource(driver._wsgi_conf, - driver._validate, - message_controller, - queue_controller, - defaults.message_ttl)), - ('/queues/{queue_name}/messages/{message_id}', - messages.ItemResource(message_controller)), - - # Claims Endpoints - ('/queues/{queue_name}/claims', - claims.CollectionResource(driver._wsgi_conf, - driver._validate, - claim_controller, - defaults.claim_ttl, - defaults.claim_grace)), - ('/queues/{queue_name}/claims/{claim_id}', - claims.ItemResource(driver._wsgi_conf, - driver._validate, - claim_controller, - defaults.claim_ttl, - defaults.claim_grace)), - - # Ping - ('/ping', - ping.Resource(driver._storage)) - ] - - -@decorators.api_version_manager(VERSION) -def private_endpoints(driver, conf): - - catalogue = [ - # Health - ('/health', - health.Resource(driver._storage)), - ] - - if conf.pooling: - pools_controller = driver._control.pools_controller - flavors_controller = driver._control.flavors_controller - - catalogue.extend([ - ('/pools', - pools.Listing(pools_controller)), - ('/pools/{pool}', - pools.Resource(pools_controller)), - ('/flavors', - flavors.Listing(flavors_controller)), - ('/flavors/{flavor}', - flavors.Resource(flavors_controller)), - ]) - - return catalogue diff --git a/zaqar/transport/wsgi/v1_1/claims.py b/zaqar/transport/wsgi/v1_1/claims.py deleted file mode 100644 index be0e835b1..000000000 --- a/zaqar/transport/wsgi/v1_1/claims.py +++ /dev/null @@ -1,199 +0,0 @@ -# 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 falcon -from oslo_log import log as logging - -from zaqar.common import decorators -from zaqar.i18n import _ -from zaqar.storage import errors as storage_errors -from zaqar.transport import utils -from zaqar.transport import validation -from zaqar.transport.wsgi import errors as wsgi_errors -from zaqar.transport.wsgi import utils as wsgi_utils - -LOG = logging.getLogger(__name__) - - -class CollectionResource(object): - __slots__ = ( - '_claim_controller', - '_validate', - '_claim_post_spec', - '_default_meta', - ) - - def __init__(self, wsgi_conf, validate, claim_controller, - default_claim_ttl, default_grace_ttl): - - self._claim_controller = claim_controller - self._validate = validate - - self._claim_post_spec = ( - ('ttl', int, default_claim_ttl), - ('grace', int, default_grace_ttl), - ) - - # NOTE(kgriffs): Create this once up front, rather than creating - # a new dict every time, for the sake of performance. - self._default_meta = { - 'ttl': default_claim_ttl, - 'grace': default_grace_ttl, - } - - @decorators.TransportLog("Claims collection") - def on_post(self, req, resp, project_id, queue_name): - # Check for an explicit limit on the # of messages to claim - limit = req.get_param_as_int('limit') - claim_options = {} if limit is None else {'limit': limit} - - # NOTE(kgriffs): Clients may or may not actually include the - # Content-Length header when the body is empty; the following - # check works for both 0 and None. - if not req.content_length: - # No values given, so use defaults - metadata = self._default_meta - else: - # Read claim metadata (e.g., TTL) and raise appropriate - # HTTP errors as needed. - document = wsgi_utils.deserialize(req.stream, req.content_length) - metadata = wsgi_utils.sanitize(document, self._claim_post_spec) - - # Claim some messages - try: - self._validate.claim_creation(metadata, limit=limit) - - cid, msgs = self._claim_controller.create( - queue_name, - metadata=metadata, - project=project_id, - **claim_options) - - # Buffer claimed messages - # TODO(kgriffs): optimize, along with serialization (below) - resp_msgs = list(msgs) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except Exception: - description = _('Claim could not be created.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Serialize claimed messages, if any. This logic assumes - # the storage driver returned well-formed messages. - if len(resp_msgs) != 0: - base_path = req.path.rpartition('/')[0] - resp_msgs = [wsgi_utils.format_message_v1_1(msg, base_path, cid) - for msg in resp_msgs] - - resp.location = req.path + '/' + cid - resp.text = utils.to_json({'messages': resp_msgs}) - resp.status = falcon.HTTP_201 - else: - resp.status = falcon.HTTP_204 - - -class ItemResource(object): - - __slots__ = ('_claim_controller', '_validate', '_claim_patch_spec') - - def __init__(self, wsgi_conf, validate, claim_controller, - default_claim_ttl, default_grace_ttl): - self._claim_controller = claim_controller - self._validate = validate - - self._claim_patch_spec = ( - ('ttl', int, default_claim_ttl), - ('grace', int, default_grace_ttl), - ) - - @decorators.TransportLog("Claim item") - def on_get(self, req, resp, project_id, queue_name, claim_id): - try: - meta, msgs = self._claim_controller.get( - queue_name, - claim_id=claim_id, - project=project_id) - - # Buffer claimed messages - # TODO(kgriffs): Optimize along with serialization (see below) - meta['messages'] = list(msgs) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - except Exception: - description = _('Claim could not be queried.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Serialize claimed messages - # TODO(kgriffs): Optimize - base_path = req.path.rsplit('/', 2)[0] - meta['messages'] = [wsgi_utils.format_message_v1_1(msg, base_path, - claim_id) - for msg in meta['messages']] - - meta['href'] = req.path - del meta['id'] - - resp.text = utils.to_json(meta) - # status defaults to 200 - - @decorators.TransportLog("Claim item") - def on_patch(self, req, resp, project_id, queue_name, claim_id): - # Read claim metadata (e.g., TTL) and raise appropriate - # HTTP errors as needed. - document = wsgi_utils.deserialize(req.stream, req.content_length) - metadata = wsgi_utils.sanitize(document, self._claim_patch_spec) - - try: - self._validate.claim_updating(metadata) - self._claim_controller.update(queue_name, - claim_id=claim_id, - metadata=metadata, - project=project_id) - - resp.status = falcon.HTTP_204 - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - except Exception: - description = _('Claim could not be updated.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - @decorators.TransportLog("Claim item") - def on_delete(self, req, resp, project_id, queue_name, claim_id): - try: - self._claim_controller.delete(queue_name, - claim_id=claim_id, - project=project_id) - - resp.status = falcon.HTTP_204 - - except Exception: - description = _('Claim could not be deleted.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) diff --git a/zaqar/transport/wsgi/v1_1/flavors.py b/zaqar/transport/wsgi/v1_1/flavors.py deleted file mode 100644 index 79bd1f0ea..000000000 --- a/zaqar/transport/wsgi/v1_1/flavors.py +++ /dev/null @@ -1,203 +0,0 @@ -# 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 falcon -import jsonschema -from oslo_log import log - -from zaqar.common.api.schemas.v1_1 import flavors as schema -from zaqar.common import utils as common_utils -from zaqar.i18n import _ -from zaqar.storage import errors -from zaqar.transport import utils as transport_utils -from zaqar.transport.wsgi import errors as wsgi_errors -from zaqar.transport.wsgi import utils as wsgi_utils - -LOG = log.getLogger(__name__) - - -class Listing(object): - """A resource to list registered flavors - - :param flavors_controller: means to interact with storage - """ - - def __init__(self, flavors_controller): - self._ctrl = flavors_controller - - def on_get(self, request, response, project_id): - """Returns a flavor listing as objects embedded in an object: - - :: - - { - "flavors": [ - {"href": "", "capabilities": {}, "pool": ""}, - ... - ], - "links": [ - {"rel": "next", "href": ""}, - ... - ] - } - - :returns: HTTP | 200 - """ - - LOG.debug('LIST flavors for project_id %s', project_id) - - store = {} - request.get_param('marker', store=store) - request.get_param_as_int('limit', store=store) - request.get_param_as_bool('detailed', store=store) - - cursor = self._ctrl.list(project=project_id, **store) - flavors = list(next(cursor)) - - results = {'links': []} - - if flavors: - store['marker'] = next(cursor) - - for entry in flavors: - entry['href'] = request.path + '/' + entry['name'] - - results['links'] = [ - { - 'rel': 'next', - 'href': request.path + falcon.to_query_str(store) - } - ] - - results['flavors'] = flavors - - response.text = transport_utils.to_json(results) - response.status = falcon.HTTP_200 - - -class Resource(object): - """A handler for individual flavor. - - :param flavors_controller: means to interact with storage - """ - - def __init__(self, flavors_controller): - self._ctrl = flavors_controller - validator_type = jsonschema.Draft4Validator - self._validators = { - 'create': validator_type(schema.create), - 'capabilities': validator_type(schema.patch_capabilities), - } - - def on_get(self, request, response, project_id, flavor): - """Returns a JSON object for a single flavor entry: - - :: - - {"pool_group": "", capabilities: {...}} - - :returns: HTTP | [200, 404] - """ - - LOG.debug('GET flavor - name: %s', flavor) - data = None - detailed = request.get_param_as_bool('detailed') or False - - try: - data = self._ctrl.get(flavor, - project=project_id, - detailed=detailed) - except errors.FlavorDoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - data['href'] = request.path - - response.text = transport_utils.to_json(data) - - def on_put(self, request, response, project_id, flavor): - """Registers a new flavor. Expects the following input: - - :: - - {"capabilities": {}} - - A capabilities object may also be provided. - - :returns: HTTP | [201, 400] - """ - - LOG.debug('PUT flavor - name: %s', flavor) - - data = wsgi_utils.load(request) - wsgi_utils.validate(self._validators['create'], data) - try: - self._ctrl.create(flavor, - project=project_id, - capabilities=data['capabilities']) - response.status = falcon.HTTP_201 - response.location = request.path - except errors.PoolGroupDoesNotExist: - description = (_('Flavor %(flavor)s could not be created. ') % - dict(flavor=flavor)) - LOG.exception(description) - raise falcon.HTTPBadRequest( - title=_('Unable to create'), description=description) - - def on_delete(self, request, response, project_id, flavor): - """Deregisters a flavor. - - :returns: HTTP | [204] - """ - - LOG.debug('DELETE flavor - name: %s', flavor) - self._ctrl.delete(flavor, project=project_id) - response.status = falcon.HTTP_204 - - def on_patch(self, request, response, project_id, flavor): - """Allows one to update a flavors's pool and/or capabilities. - - This method expects the user to submit a JSON object - containing at least one of: 'pool_group', 'capabilities'. If - none are found, the request is flagged as bad. There is also - strict format checking through the use of - jsonschema. Appropriate errors are returned in each case for - badly formatted input. - - :returns: HTTP | [200, 400] - """ - - LOG.debug('PATCH flavor - name: %s', flavor) - data = wsgi_utils.load(request) - - EXPECT = ('capabilities') - if not any([(field in data) for field in EXPECT]): - LOG.debug('PATCH flavor, bad params') - raise wsgi_errors.HTTPBadRequestBody( - '`capabilities` needs ' - 'to be specified' - ) - - for field in EXPECT: - wsgi_utils.validate(self._validators[field], data) - - fields = common_utils.fields(data, EXPECT, - pred=lambda v: v is not None) - - try: - self._ctrl.update(flavor, project=project_id, **fields) - except errors.FlavorDoesNotExist as ex: - LOG.exception('Flavor "%s" does not exist', flavor) - raise wsgi_errors.HTTPNotFound(str(ex)) diff --git a/zaqar/transport/wsgi/v1_1/health.py b/zaqar/transport/wsgi/v1_1/health.py deleted file mode 100644 index 70b5bfb24..000000000 --- a/zaqar/transport/wsgi/v1_1/health.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2014 Rackspace, Inc. -# Copyright 2014 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 oslo_log import log as logging - -from zaqar.i18n import _ -from zaqar.transport import utils -from zaqar.transport.wsgi import errors as wsgi_errors - -LOG = logging.getLogger(__name__) - - -class Resource(object): - - __slots__ = ('_driver',) - - def __init__(self, driver): - self._driver = driver - - def on_get(self, req, resp, **kwargs): - try: - resp_dict = self._driver.health() - resp.text = utils.to_json(resp_dict) - except Exception: - description = _('Health status could not be read.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) diff --git a/zaqar/transport/wsgi/v1_1/homedoc.py b/zaqar/transport/wsgi/v1_1/homedoc.py deleted file mode 100644 index 042f92cc3..000000000 --- a/zaqar/transport/wsgi/v1_1/homedoc.py +++ /dev/null @@ -1,292 +0,0 @@ -# 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. - -from oslo_serialization import jsonutils - - -# NOTE(kgriffs): http://tools.ietf.org/html/draft-nottingham-json-home-03 -JSON_HOME = { - 'resources': { - # ----------------------------------------------------------------- - # Queues - # ----------------------------------------------------------------- - 'rel/queues': { - 'href-template': '/v1.1/queues{?marker,limit,detailed}', - 'href-vars': { - 'marker': 'param/marker', - 'limit': 'param/queue_limit', - 'detailed': 'param/detailed', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/queue': { - 'href-template': '/v1.1/queues/{queue_name}', - 'href-vars': { - 'queue_name': 'param/queue_name', - }, - 'hints': { - 'allow': ['PUT', 'DELETE'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/queue_stats': { - 'href-template': '/v1.1/queues/{queue_name}/stats', - 'href-vars': { - 'queue_name': 'param/queue_name', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - - # ----------------------------------------------------------------- - # Messages - # ----------------------------------------------------------------- - 'rel/messages': { - 'href-template': ('/v1.1/queues/{queue_name}/messages' - '{?marker,limit,echo,include_claimed}'), - 'href-vars': { - 'queue_name': 'param/queue_name', - 'marker': 'param/marker', - 'limit': 'param/messages_limit', - 'echo': 'param/echo', - 'include_claimed': 'param/include_claimed', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/post_messages': { - 'href-template': '/v1.1/queues/{queue_name}/messages', - 'href-vars': { - 'queue_name': 'param/queue_name', - }, - 'hints': { - 'allow': ['POST'], - 'formats': { - 'application/json': {}, - }, - 'accept-post': ['application/json'], - }, - }, - 'rel/messages_delete': { - 'href-template': '/v1.1/queues/{queue_name}/messages{?ids,pop}', - 'href-vars': { - 'queue_name': 'param/queue_name', - 'ids': 'param/ids', - 'pop': 'param/pop' - }, - 'hints': { - 'allow': [ - 'DELETE' - ], - 'formats': { - 'application/json': {} - } - } - }, - 'rel/message_delete': { - 'href-template': '/v1.1/queues/{queue_name}/messages/{message_id}{?claim}', # noqa - 'href-vars': { - 'queue_name': 'param/queue_name', - 'message_id': 'param/message_id', - 'claim': 'param/claim_id' - }, - 'hints': { - 'allow': [ - 'DELETE' - ], - 'formats': { - 'application/json': {} - } - } - }, - - # ----------------------------------------------------------------- - # Claims - # ----------------------------------------------------------------- - 'rel/claim': { - 'href-template': '/v1.1/queues/{queue_name}/claims/{claim_id}', - 'href-vars': { - 'queue_name': 'param/queue_name', - 'claim_id': 'param/claim_id', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/post_claim': { - 'href-template': '/v1.1/queues/{queue_name}/claims{?limit}', - 'href-vars': { - 'queue_name': 'param/queue_name', - 'limit': 'param/claim_limit', - }, - 'hints': { - 'allow': ['POST'], - 'formats': { - 'application/json': {}, - }, - 'accept-post': ['application/json'] - }, - }, - 'rel/patch_claim': { - 'href-template': '/v1.1/queues/{queue_name}/claims/{claim_id}', - 'href-vars': { - 'queue_name': 'param/queue_name', - 'claim_id': 'param/claim_id', - }, - 'hints': { - 'allow': ['PATCH'], - 'formats': { - 'application/json': {}, - }, - 'accept-post': ['application/json'] - }, - }, - 'rel/delete_claim': { - 'href-template': '/v1.1/queues/{queue_name}/claims/{claim_id}', - 'href-vars': { - 'queue_name': 'param/queue_name', - 'claim_id': 'param/claim_id', - }, - 'hints': { - 'allow': ['DELETE'], - 'formats': { - 'application/json': {}, - }, - }, - }, - # ----------------------------------------------------------------- - # Ping - # ----------------------------------------------------------------- - 'rel/ping': { - 'href-template': '/v1.1/ping', - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - } - } - } - } -} - - -ADMIN_RESOURCES = { - # ----------------------------------------------------------------- - # Pools - # ----------------------------------------------------------------- - 'rel/pools': { - 'href-template': '/v1.1/pools{?detailed,limit,marker}', - 'href-vars': { - 'detailed': 'param/detailed', - 'limit': 'param/pool_limit', - 'marker': 'param/marker', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/pool': { - 'href-template': '/v1.1/pools/{pool_name}', - 'href-vars': { - 'pool_name': 'param/pool_name', - }, - 'hints': { - 'allow': ['GET', 'PUT', 'PATCH', 'DELETE'], - 'formats': { - 'application/json': {}, - }, - }, - }, - - # ----------------------------------------------------------------- - # Flavors - # ----------------------------------------------------------------- - 'rel/flavors': { - 'href-template': '/v1.1/flavors{?detailed,limit,marker}', - 'href-vars': { - 'detailed': 'param/detailed', - 'limit': 'param/flavor_limit', - 'marker': 'param/marker', - }, - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, - 'rel/flavor': { - 'href-template': '/v1.1/flavors/{flavor_name}', - 'href-vars': { - 'flavor_name': 'param/flavor_name', - }, - 'hints': { - 'allow': ['GET', 'PUT', 'PATCH', 'DELETE'], - 'formats': { - 'application/json': {}, - }, - }, - }, - - # ----------------------------------------------------------------- - # Health - # ----------------------------------------------------------------- - 'rel/health': { - 'href': '/v1.1/health', - 'hints': { - 'allow': ['GET'], - 'formats': { - 'application/json': {}, - }, - }, - }, -} - - -class Resource(object): - - def __init__(self, conf): - if conf.admin_mode: - JSON_HOME['resources'].update(ADMIN_RESOURCES) - - document = jsonutils.dumps(JSON_HOME, ensure_ascii=False, indent=4) - self.document_utf8 = document.encode('utf-8') - - def on_get(self, req, resp, project_id): - resp.data = self.document_utf8 - - resp.content_type = 'application/json-home' - resp.cache_control = ['max-age=86400'] - # status defaults to 200 diff --git a/zaqar/transport/wsgi/v1_1/messages.py b/zaqar/transport/wsgi/v1_1/messages.py deleted file mode 100644 index 24acdfcea..000000000 --- a/zaqar/transport/wsgi/v1_1/messages.py +++ /dev/null @@ -1,368 +0,0 @@ -# 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 falcon -from oslo_log import log as logging - -from zaqar.common import decorators -from zaqar.common.transport.wsgi import helpers as wsgi_helpers -from zaqar.i18n import _ -from zaqar.storage import errors as storage_errors -from zaqar.transport import utils -from zaqar.transport import validation -from zaqar.transport.wsgi import errors as wsgi_errors -from zaqar.transport.wsgi import utils as wsgi_utils - -LOG = logging.getLogger(__name__) - - -class CollectionResource(object): - - __slots__ = ( - '_message_controller', - '_queue_controller', - '_wsgi_conf', - '_validate', - '_message_post_spec', - ) - - def __init__(self, wsgi_conf, validate, - message_controller, queue_controller, - default_message_ttl): - - self._wsgi_conf = wsgi_conf - self._validate = validate - self._message_controller = message_controller - self._queue_controller = queue_controller - - self._message_post_spec = ( - ('ttl', int, default_message_ttl), - ('body', '*', None), - ) - - # ---------------------------------------------------------------------- - # Helpers - # ---------------------------------------------------------------------- - - def _get_by_id(self, base_path, project_id, queue_name, ids): - """Returns one or more messages from the queue by ID.""" - try: - self._validate.message_listing(limit=len(ids)) - messages = self._message_controller.bulk_get( - queue_name, - message_ids=ids, - project=project_id) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except Exception: - description = _('Message could not be retrieved.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Prepare response - messages = list(messages) - if not messages: - return None - - messages = [wsgi_utils.format_message_v1_1(m, base_path, m['claim_id']) - for m in messages] - - return {'messages': messages} - - def _get(self, req, project_id, queue_name): - client_uuid = wsgi_helpers.get_client_uuid(req) - kwargs = {} - - # NOTE(kgriffs): This syntax ensures that - # we don't clobber default values with None. - req.get_param('marker', store=kwargs) - req.get_param_as_int('limit', store=kwargs) - req.get_param_as_bool('echo', store=kwargs) - req.get_param_as_bool('include_claimed', store=kwargs) - - try: - self._validate.message_listing(**kwargs) - results = self._message_controller.list( - queue_name, - project=project_id, - client_uuid=client_uuid, - **kwargs) - - # Buffer messages - cursor = next(results) - messages = list(cursor) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except storage_errors.QueueDoesNotExist as ex: - LOG.debug(ex) - messages = None - - except Exception: - description = _('Messages could not be listed.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - if not messages: - messages = [] - - else: - # Found some messages, so prepare the response - kwargs['marker'] = next(results) - base_path = req.path.rsplit('/', 1)[0] - messages = [wsgi_utils.format_message_v1_1(m, base_path, - m['claim_id']) - for m in messages] - - links = [] - if messages: - links = [ - { - 'rel': 'next', - 'href': req.path + falcon.to_query_str(kwargs) - } - ] - - return { - 'messages': messages, - 'links': links - } - - # ---------------------------------------------------------------------- - # Interface - # ---------------------------------------------------------------------- - - @decorators.TransportLog("Messages collection") - def on_post(self, req, resp, project_id, queue_name): - client_uuid = wsgi_helpers.get_client_uuid(req) - - try: - # Place JSON size restriction before parsing - self._validate.message_length(req.content_length) - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - # Deserialize and validate the incoming messages - document = wsgi_utils.deserialize(req.stream, req.content_length) - - if 'messages' not in document: - description = _('No messages were found in the request body.') - raise wsgi_errors.HTTPBadRequestAPI(description) - - messages = wsgi_utils.sanitize(document['messages'], - self._message_post_spec, - doctype=wsgi_utils.JSONArray) - - try: - self._validate.message_posting(messages) - - if not self._queue_controller.exists(queue_name, project_id): - self._queue_controller.create(queue_name, project=project_id) - - message_ids = self._message_controller.post( - queue_name, - messages=messages, - project=project_id, - client_uuid=client_uuid) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - except storage_errors.MessageConflict: - description = _('No messages could be enqueued.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - except Exception: - description = _('Messages could not be enqueued.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Prepare the response - ids_value = ','.join(message_ids) - resp.location = req.path + '?ids=' + ids_value - - hrefs = [req.path + '/' + id for id in message_ids] - body = {'resources': hrefs} - resp.text = utils.to_json(body) - resp.status = falcon.HTTP_201 - - @decorators.TransportLog("Messages collection") - def on_get(self, req, resp, project_id, queue_name): - ids = req.get_param_as_list('ids') - - if ids is None: - response = self._get(req, project_id, queue_name) - - else: - response = self._get_by_id(req.path.rsplit('/', 1)[0], project_id, - queue_name, ids) - - if response is None: - # NOTE(TheSriram): Trying to get a message by id, should - # return the message if its present, otherwise a 404 since - # the message might have been deleted. - msg = _('No messages with IDs: {ids} found in the queue {queue} ' - 'for project {project}.') - description = msg.format(queue=queue_name, project=project_id, - ids=ids) - raise wsgi_errors.HTTPNotFound(description) - - else: - resp.text = utils.to_json(response) - # status defaults to 200 - - @decorators.TransportLog("Messages collection") - def on_delete(self, req, resp, project_id, queue_name): - ids = req.get_param_as_list('ids') - pop_limit = req.get_param_as_int('pop') - try: - self._validate.message_deletion(ids, pop_limit) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - if ids: - resp.status = self._delete_messages_by_id(queue_name, ids, - project_id) - - elif pop_limit: - resp.status, resp.text = self._pop_messages(queue_name, - project_id, - pop_limit) - - def _delete_messages_by_id(self, queue_name, ids, project_id): - try: - self._message_controller.bulk_delete( - queue_name, - message_ids=ids, - project=project_id) - - except Exception: - description = _('Messages could not be deleted.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - return falcon.HTTP_204 - - def _pop_messages(self, queue_name, project_id, pop_limit): - try: - LOG.debug('POP messages - queue: %(queue)s, ' - 'project: %(project)s', - {'queue': queue_name, 'project': project_id}) - - messages = self._message_controller.pop( - queue_name, - project=project_id, - limit=pop_limit) - - except Exception: - description = _('Messages could not be popped.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Prepare response - if not messages: - messages = [] - body = {'messages': messages} - body = utils.to_json(body) - - return falcon.HTTP_200, body - - -class ItemResource(object): - - __slots__ = '_message_controller' - - def __init__(self, message_controller): - self._message_controller = message_controller - - @decorators.TransportLog("Messages item") - def on_get(self, req, resp, project_id, queue_name, message_id): - try: - message = self._message_controller.get( - queue_name, - message_id, - project=project_id) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - except Exception: - description = _('Message could not be retrieved.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Prepare response - message['href'] = req.path - message = wsgi_utils.format_message_v1_1(message, - req.path.rsplit('/', 2)[0], - message['claim_id']) - - resp.text = utils.to_json(message) - # status defaults to 200 - - @decorators.TransportLog("Messages item") - def on_delete(self, req, resp, project_id, queue_name, message_id): - error_title = _('Unable to delete') - - try: - self._message_controller.delete( - queue_name, - message_id=message_id, - project=project_id, - claim=req.get_param('claim_id')) - - except storage_errors.MessageNotClaimed as ex: - LOG.debug(ex) - description = _('A claim was specified, but the message ' - 'is not currently claimed.') - raise falcon.HTTPBadRequest( - title=error_title, description=description) - - except storage_errors.ClaimDoesNotExist as ex: - LOG.debug(ex) - description = _('The specified claim does not exist or ' - 'has expired.') - raise falcon.HTTPBadRequest( - title=error_title, description=description) - - except storage_errors.NotPermitted as ex: - LOG.debug(ex) - description = _('This message is claimed; it cannot be ' - 'deleted without a valid claim ID.') - raise falcon.HTTPForbidden( - title=error_title, description=description) - - except Exception: - description = _('Message could not be deleted.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Alles guete - resp.status = falcon.HTTP_204 diff --git a/zaqar/transport/wsgi/v1_1/ping.py b/zaqar/transport/wsgi/v1_1/ping.py deleted file mode 100644 index 1ea344282..000000000 --- a/zaqar/transport/wsgi/v1_1/ping.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2014 IBM Corp. 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 falcon - - -class Resource(object): - - __slots__ = ('_driver',) - - def __init__(self, driver): - self._driver = driver - - def on_get(self, req, resp, **kwargs): - resp.status = (falcon.HTTP_204 if self._driver.is_alive() - else falcon.HTTP_503) - - def on_head(self, req, resp, **kwargs): - resp.status = falcon.HTTP_204 diff --git a/zaqar/transport/wsgi/v1_1/pools.py b/zaqar/transport/wsgi/v1_1/pools.py deleted file mode 100644 index 933e444f7..000000000 --- a/zaqar/transport/wsgi/v1_1/pools.py +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright (c) 2013 Rackspace Hosting, 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. - -"""pools: a resource to handle storage pool management - -A pool is added by an operator by interacting with the -pooling-related endpoints. When specifying a pool, the -following fields are required: - -:: - - { - "name": string, - "weight": integer, - "uri": string::uri - } - -Furthermore, depending on the underlying storage type of pool being -registered, there is an optional field: -:: - - { - "options": {...} - } -""" - -import falcon -import jsonschema -from oslo_log import log - -from zaqar.common.api.schemas import pools as schema -from zaqar.common import utils as common_utils -from zaqar.i18n import _ -from zaqar.storage import errors -from zaqar.storage import utils as storage_utils -from zaqar.transport import utils as transport_utils -from zaqar.transport.wsgi import errors as wsgi_errors -from zaqar.transport.wsgi import utils as wsgi_utils - -LOG = log.getLogger(__name__) - - -class Listing(object): - """A resource to list registered pools - - :param pools_controller: means to interact with storage - """ - - def __init__(self, pools_controller): - self._ctrl = pools_controller - - def on_get(self, request, response, project_id): - """Returns a pool listing as objects embedded in an object: - - :: - - { - "pools": [ - {"href": "", "weight": 100, "uri": ""}, - ... - ], - "links": [ - {"href": "", "rel": "next"} - ] - } - - :returns: HTTP | 200 - """ - - LOG.debug('LIST pools') - - store = {} - request.get_param('marker', store=store) - request.get_param_as_int('limit', store=store) - request.get_param_as_bool('detailed', store=store) - - cursor = self._ctrl.list(**store) - pools = list(next(cursor)) - - results = {'links': []} - - if pools: - store['marker'] = next(cursor) - - for entry in pools: - entry['href'] = request.path + '/' + entry['name'] - - results['links'] = [ - { - 'rel': 'next', - 'href': request.path + falcon.to_query_str(store) - } - ] - - results['pools'] = pools - - response.content_location = request.relative_uri - response.text = transport_utils.to_json(results) - response.status = falcon.HTTP_200 - - -class Resource(object): - """A handler for individual pool. - - :param pools_controller: means to interact with storage - """ - - def __init__(self, pools_controller): - self._ctrl = pools_controller - validator_type = jsonschema.Draft4Validator - self._validators = { - 'weight': validator_type(schema.patch_weight), - 'uri': validator_type(schema.patch_uri), - 'group': validator_type(schema.patch_uri), - 'options': validator_type(schema.patch_options), - 'create': validator_type(schema.create) - } - - def on_get(self, request, response, project_id, pool): - """Returns a JSON object for a single pool entry: - - :: - - {"weight": 100, "uri": "", options: {...}} - - :returns: HTTP | [200, 404] - """ - - LOG.debug('GET pool - name: %s', pool) - data = None - detailed = request.get_param_as_bool('detailed') or False - - try: - data = self._ctrl.get(pool, detailed) - - except errors.PoolDoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - data['href'] = request.path - - response.text = transport_utils.to_json(data) - - def on_put(self, request, response, project_id, pool): - """Registers a new pool. Expects the following input: - - :: - - {"weight": 100, "uri": ""} - - An options object may also be provided. - - :returns: HTTP | [201, 204] - """ - - LOG.debug('PUT pool - name: %s', pool) - - conf = self._ctrl.driver.conf - data = wsgi_utils.load(request) - wsgi_utils.validate(self._validators['create'], data) - if not storage_utils.can_connect(data['uri'], conf=conf): - raise wsgi_errors.HTTPBadRequestBody( - 'cannot connect to %s' % data['uri'] - ) - try: - self._ctrl.create(pool, weight=data['weight'], - uri=data['uri'], - options=data.get('options', {})) - response.status = falcon.HTTP_201 - response.location = request.path - except errors.PoolCapabilitiesMismatch as e: - title = _('Unable to create pool') - LOG.exception(title) - raise falcon.HTTPBadRequest(title=title, description=str(e)) - except errors.PoolAlreadyExists as e: - LOG.exception('Pool "%s" already exists', pool) - raise wsgi_errors.HTTPConflict(str(e)) - - def on_delete(self, request, response, project_id, pool): - """Deregisters a pool. - - :returns: HTTP | [204, 403] - """ - - LOG.debug('DELETE pool - name: %s', pool) - - try: - self._ctrl.delete(pool) - except errors.PoolInUseByFlavor as ex: - title = _('Unable to delete') - description = _('This pool is used by flavors {flavor}; ' - 'It cannot be deleted.') - description = description.format(flavor=ex.flavor) - LOG.exception(description) - raise falcon.HTTPForbidden(title=title, description=description) - - response.status = falcon.HTTP_204 - - def on_patch(self, request, response, project_id, pool): - """Allows one to update a pool's weight, uri, and/or options. - - This method expects the user to submit a JSON object - containing at least one of: 'uri', 'weight', 'group', 'options'. If - none are found, the request is flagged as bad. There is also - strict format checking through the use of - jsonschema. Appropriate errors are returned in each case for - badly formatted input. - - :returns: HTTP | 200,400 - """ - - LOG.debug('PATCH pool - name: %s', pool) - data = wsgi_utils.load(request) - - EXPECT = ('weight', 'uri', 'options') - if not any([(field in data) for field in EXPECT]): - LOG.debug('PATCH pool, bad params') - raise wsgi_errors.HTTPBadRequestBody( - 'One of `uri`, `weight`,or `options` needs ' - 'to be specified' - ) - - for field in EXPECT: - wsgi_utils.validate(self._validators[field], data) - - conf = self._ctrl.driver.conf - if 'uri' in data and not storage_utils.can_connect(data['uri'], - conf=conf): - raise wsgi_errors.HTTPBadRequestBody( - 'cannot connect to %s' % data['uri'] - ) - fields = common_utils.fields(data, EXPECT, - pred=lambda v: v is not None) - - try: - self._ctrl.update(pool, **fields) - except errors.PoolDoesNotExist as ex: - LOG.exception('Pool "%s" does not exist', pool) - raise wsgi_errors.HTTPNotFound(str(ex)) diff --git a/zaqar/transport/wsgi/v1_1/queues.py b/zaqar/transport/wsgi/v1_1/queues.py deleted file mode 100644 index 9d6db6179..000000000 --- a/zaqar/transport/wsgi/v1_1/queues.py +++ /dev/null @@ -1,161 +0,0 @@ -# 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 falcon -from oslo_log import log as logging - -from zaqar.common import decorators -from zaqar.i18n import _ -from zaqar.storage import errors as storage_errors -from zaqar.transport import utils -from zaqar.transport import validation -from zaqar.transport.wsgi import errors as wsgi_errors -from zaqar.transport.wsgi import utils as wsgi_utils - - -LOG = logging.getLogger(__name__) - - -class ItemResource(object): - - __slots__ = ('_validate', '_queue_controller', '_message_controller') - - def __init__(self, validate, queue_controller, message_controller): - self._validate = validate - self._queue_controller = queue_controller - self._message_controller = message_controller - - @decorators.TransportLog("Queue metadata") - def on_get(self, req, resp, project_id, queue_name): - try: - resp_dict = self._queue_controller.get(queue_name, - project=project_id) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - except Exception: - description = _('Queue metadata could not be retrieved.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - resp.text = utils.to_json(resp_dict) - # status defaults to 200 - - @decorators.TransportLog("Queue item") - def on_put(self, req, resp, project_id, queue_name): - try: - # Place JSON size restriction before parsing - self._validate.queue_metadata_length(req.content_length) - # Deserialize queue metadata - metadata = None - if req.content_length: - document = wsgi_utils.deserialize(req.stream, - req.content_length) - metadata = wsgi_utils.sanitize(document) - # NOTE(Eva-i): reserved queue attributes is Zaqar's feature since - # API v2. But we have to ensure the bad data will not come from - # older APIs, so we validate metadata here. - self._validate.queue_metadata_putting(metadata) - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - try: - created = self._queue_controller.create(queue_name, - metadata=metadata, - project=project_id) - - except storage_errors.FlavorDoesNotExist as ex: - LOG.exception('"%s" does not exist', queue_name) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except Exception: - description = _('Queue could not be created.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - resp.status = falcon.HTTP_201 if created else falcon.HTTP_204 - resp.location = req.path - - @decorators.TransportLog("Queue item") - def on_delete(self, req, resp, project_id, queue_name): - try: - self._queue_controller.delete(queue_name, project=project_id) - - except Exception: - description = _('Queue could not be deleted.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - resp.status = falcon.HTTP_204 - - -class CollectionResource(object): - - __slots__ = ('_queue_controller', '_validate') - - def __init__(self, validate, queue_controller): - self._queue_controller = queue_controller - self._validate = validate - - @decorators.TransportLog("Queue collection") - def on_get(self, req, resp, project_id): - kwargs = {} - - # NOTE(kgriffs): This syntax ensures that - # we don't clobber default values with None. - req.get_param('marker', store=kwargs) - req.get_param_as_int('limit', store=kwargs) - req.get_param_as_bool('detailed', store=kwargs) - - try: - self._validate.queue_listing(**kwargs) - results = self._queue_controller.list(project=project_id, **kwargs) - - # Buffer list of queues - queues = list(next(results)) - - except validation.ValidationFailed as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPBadRequestAPI(str(ex)) - - except Exception: - description = _('Queues could not be listed.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) - - # Got some. Prepare the response. - kwargs['marker'] = next(results) or kwargs.get('marker', '') - for each_queue in queues: - each_queue['href'] = req.path + '/' + each_queue['name'] - - links = [] - if queues: - links = [ - { - 'rel': 'next', - 'href': req.path + falcon.to_query_str(kwargs) - } - ] - - response_body = { - 'queues': queues, - 'links': links - } - - resp.text = utils.to_json(response_body) - # status defaults to 200 diff --git a/zaqar/transport/wsgi/v1_1/stats.py b/zaqar/transport/wsgi/v1_1/stats.py deleted file mode 100644 index 4f4297a1b..000000000 --- a/zaqar/transport/wsgi/v1_1/stats.py +++ /dev/null @@ -1,73 +0,0 @@ -# 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. - -from oslo_log import log as logging - -from zaqar.i18n import _ -from zaqar.storage import errors as storage_errors -from zaqar.transport import utils -from zaqar.transport.wsgi import errors as wsgi_errors - - -LOG = logging.getLogger(__name__) - - -class Resource(object): - - __slots__ = '_queue_ctrl' - - def __init__(self, queue_controller): - self._queue_ctrl = queue_controller - - def on_get(self, req, resp, project_id, queue_name): - try: - resp_dict = self._queue_ctrl.stats(queue_name, - project=project_id) - - message_stats = resp_dict['messages'] - - if message_stats['total'] != 0: - base_path = req.path[:req.path.rindex('/')] + '/messages/' - - newest = message_stats['newest'] - newest['href'] = base_path + newest['id'] - del newest['id'] - - oldest = message_stats['oldest'] - oldest['href'] = base_path + oldest['id'] - del oldest['id'] - - resp.text = utils.to_json(resp_dict) - # status defaults to 200 - - except (storage_errors.QueueDoesNotExist, - storage_errors.QueueIsEmpty): - resp_dict = { - 'messages': { - 'claimed': 0, - 'free': 0, - 'total': 0 - } - } - resp.text = utils.to_json(resp_dict) - - except storage_errors.DoesNotExist as ex: - LOG.debug(ex) - raise wsgi_errors.HTTPNotFound(str(ex)) - - except Exception: - description = _('Queue stats could not be read.') - LOG.exception(description) - raise wsgi_errors.HTTPServiceUnavailable(description) diff --git a/zaqar/transport/wsgi/version.py b/zaqar/transport/wsgi/version.py index 689a8b075..5701dba56 100644 --- a/zaqar/transport/wsgi/version.py +++ b/zaqar/transport/wsgi/version.py @@ -15,12 +15,10 @@ import falcon from zaqar.transport import utils -from zaqar.transport.wsgi import v1_1 from zaqar.transport.wsgi import v2_0 VERSIONS = { 'versions': [ - v1_1.VERSION, v2_0.VERSION ] }