diff --git a/barbican_tempest_plugin/plugin.py b/barbican_tempest_plugin/plugin.py index 68a971a..a0f4ca4 100644 --- a/barbican_tempest_plugin/plugin.py +++ b/barbican_tempest_plugin/plugin.py @@ -44,8 +44,9 @@ class BarbicanTempestPlugin(plugins.TempestPlugin): 'client_names': [ 'ConsumerClient', 'ContainerClient', - 'SecretMetadataClient', - 'SecretClient' + 'OrderClient', + 'SecretClient', + 'SecretMetadataClient' ], } return [v1_params] diff --git a/barbican_tempest_plugin/services/key_manager/json/__init__.py b/barbican_tempest_plugin/services/key_manager/json/__init__.py index ffb1734..b3ee41e 100644 --- a/barbican_tempest_plugin/services/key_manager/json/__init__.py +++ b/barbican_tempest_plugin/services/key_manager/json/__init__.py @@ -16,6 +16,8 @@ from barbican_tempest_plugin.services.key_manager.json.consumer_client \ import ConsumerClient from barbican_tempest_plugin.services.key_manager.json.container_client \ import ContainerClient +from barbican_tempest_plugin.services.key_manager.json.order_client \ + import OrderClient from barbican_tempest_plugin.services.key_manager.json.secret_client \ import SecretClient from barbican_tempest_plugin.services.key_manager.json.secret_metadata_client \ @@ -24,6 +26,7 @@ from barbican_tempest_plugin.services.key_manager.json.secret_metadata_client \ __all__ = [ 'ConsumerClient', 'ContainerClient', - 'SecretMetadataClient', - 'SecretClient' + 'OrderClient', + 'SecretClient', + 'SecretMetadataClient' ] diff --git a/barbican_tempest_plugin/services/key_manager/json/order_client.py b/barbican_tempest_plugin/services/key_manager/json/order_client.py new file mode 100644 index 0000000..ba0ce51 --- /dev/null +++ b/barbican_tempest_plugin/services/key_manager/json/order_client.py @@ -0,0 +1,56 @@ +# Copyright (c) 2016 Johns Hopkins University Applied Physics Laboratory +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +import json + +from six.moves.urllib import parse as urllib + +from tempest import config +from tempest.lib.common import rest_client + +CONF = config.CONF + + +class OrderClient(rest_client.RestClient): + + def list_orders(self, **kwargs): + uri = "/v1/orders" + if kwargs: + uri += "?%s" % urllib.urlencode(kwargs) + + response, body = self.get(uri) + self.expected_success(200, response.status) + return json.loads(body) + + def create_order(self, **kwargs): + uri = "/v1/orders" + + response, body = self.post(uri, json.dumps(kwargs)) + self.expected_success(202, response.status) + return json.loads(body) + + def get_order(self, order_id): + uri = "v1/orders/%s" % order_id + + response, body = self.get(uri) + self.expected_success(200, response.status) + return json.loads(body) + + def delete_order(self, order_id): + uri = "/v1/orders/%s" % order_id + + response, _ = self.delete(uri) + self.expected_success(204, response.status) + return diff --git a/barbican_tempest_plugin/tests/api/base.py b/barbican_tempest_plugin/tests/api/base.py index 58f6bbf..abf1e830 100644 --- a/barbican_tempest_plugin/tests/api/base.py +++ b/barbican_tempest_plugin/tests/api/base.py @@ -23,7 +23,7 @@ from barbican_tempest_plugin import clients CONF = config.CONF # NOTE(dane-fichter): We need to track resource types for cleanup. -RESOURCE_TYPES = ['secret', 'container'] +RESOURCE_TYPES = ['container', 'order', 'secret'] def _get_uuid(href): @@ -37,10 +37,16 @@ def creates(resource): @functools.wraps(f) def wrapper(cls, *args, **kwargs): resp = f(cls, *args, **kwargs) - if resource == 'secret': - uuid = _get_uuid(resp['secret_ref']) if resource == 'container': uuid = _get_uuid(resp['container_ref']) + if resource == 'order': + uuid = _get_uuid(resp.get('order_ref')) + order_metadata = cls.get_order(uuid) + secret_ref = order_metadata.get('secret_ref') + if secret_ref: + cls.created_objects['secret'].add(_get_uuid(secret_ref)) + if resource == 'secret': + uuid = _get_uuid(resp['secret_ref']) cls.created_objects[resource].add(uuid) return resp return wrapper @@ -65,10 +71,11 @@ class BaseKeyManagerTest(test.BaseTestCase): cls.container_client = os.secret_v1.ContainerClient( service='key-manager' ) + cls.order_client = os.secret_v1.OrderClient(service='key-manager') + cls.secret_client = os.secret_v1.SecretClient(service='key-manager') cls.secret_metadata_client = os.secret_v1.SecretMetadataClient( service='key-manager' ) - cls.secret_client = os.secret_v1.SecretClient(service='key-manager') @classmethod def resource_setup(cls): @@ -79,23 +86,15 @@ class BaseKeyManagerTest(test.BaseTestCase): @classmethod def resource_cleanup(cls): try: - for secret_uuid in list(cls.created_objects['secret']): - cls.delete_secret(secret_uuid) for container_uuid in list(cls.created_objects['container']): cls.delete_container(container_uuid) + for order_uuid in list(cls.created_objects['order']): + cls.delete_order(order_uuid) + for secret_uuid in list(cls.created_objects['secret']): + cls.delete_secret(secret_uuid) finally: super(BaseKeyManagerTest, cls).resource_cleanup() - @classmethod - @creates('secret') - def create_secret(cls, **kwargs): - return cls.secret_client.create_secret(**kwargs) - - @classmethod - def delete_secret(cls, uuid): - cls.created_objects['secret'].remove(uuid) - return cls.secret_client.delete_secret(uuid) - @classmethod @creates('container') def create_container(cls, **kwargs): @@ -105,3 +104,27 @@ class BaseKeyManagerTest(test.BaseTestCase): def delete_container(cls, uuid): cls.created_objects['container'].remove(uuid) return cls.container_client.delete_container(uuid) + + @classmethod + @creates('order') + def create_order(cls, **kwargs): + return cls.order_client.create_order(**kwargs) + + @classmethod + def get_order(cls, uuid): + return cls.order_client.get_order(uuid) + + @classmethod + def delete_order(cls, uuid): + cls.created_objects['order'].remove(uuid) + return cls.order_client.delete_order(uuid) + + @classmethod + @creates('secret') + def create_secret(cls, **kwargs): + return cls.secret_client.create_secret(**kwargs) + + @classmethod + def delete_secret(cls, uuid): + cls.created_objects['secret'].remove(uuid) + return cls.secret_client.delete_secret(uuid) diff --git a/barbican_tempest_plugin/tests/api/test_orders.py b/barbican_tempest_plugin/tests/api/test_orders.py new file mode 100644 index 0000000..fa76516 --- /dev/null +++ b/barbican_tempest_plugin/tests/api/test_orders.py @@ -0,0 +1,135 @@ +# Copyright (c) 2016 Johns Hopkins University Applied Physics Laboratory +# +# 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 barbican_tempest_plugin.tests.api import base + + +class OrdersTest(base.BaseKeyManagerTest): + """Orders API tests.""" + + def test_create_list_delete_orders(self): + # Confirm that there are no orders + body = self.order_client.list_orders() + self.assertEqual(0, body.get('total'), body) + self.assertEqual(0, len(body.get('orders')), body) + + # Create some orders + body = self.create_order( + type="key", + meta={ + "name": "order-key-1", + "algorithm": "AES", + "bit_length": 256, + "mode": "cbc", + "payload_content_type": "application/octet-stream" + } + ) + order_id_1 = base._get_uuid(body.get('order_ref')) + body = self.create_order( + type="key", + meta={ + "name": "order-key-2", + "algorithm": "AES", + "bit_length": 256, + "mode": "cbc", + "payload_content_type": "application/octet-stream" + } + ) + order_id_2 = base._get_uuid(body.get('order_ref')) + + # Verify that the orders can be found via generic listing. + body = self.order_client.list_orders() + self.assertEqual(2, body.get('total'), body) + self.assertEqual(2, len(body.get('orders')), body) + + orders = body.get('orders') + for order in orders: + self.assertIn( + base._get_uuid(order.get('order_ref')), + [order_id_1, order_id_2], + body + ) + self.assertIn( + 'secret_ref', + order.keys() + ) + + # Verify that the orders can be found via specific listing. + body = self.order_client.get_order(order_id_1) + self.assertEqual( + order_id_1, + base._get_uuid(body.get('order_ref')), + body + ) + self.assertIn('created', body, body) + self.assertIn('creator_id', body, body) + self.assertIn('meta', body, body) + + meta = body.get('meta') + self.assertEqual("order-key-1", meta.get('name'), meta) + self.assertEqual("AES", meta.get('algorithm'), meta) + self.assertEqual(256, meta.get('bit_length'), meta) + self.assertEqual("cbc", meta.get('mode'), meta) + self.assertEqual( + "application/octet-stream", + meta.get('payload_content_type'), + meta + ) + + self.assertIn('secret_ref', body, body) + self.assertEqual("ACTIVE", body.get('status'), body) + self.assertEqual("key", body.get('type'), body) + self.assertIn('updated', body, body) + + body = self.order_client.get_order(order_id_2) + self.assertEqual( + order_id_2, + base._get_uuid(body.get('order_ref')), + body + ) + self.assertIn('created', body, body) + self.assertIn('creator_id', body, body) + self.assertIn('meta', body, body) + + meta = body.get('meta') + self.assertEqual("order-key-2", meta.get('name'), meta) + self.assertEqual("AES", meta.get('algorithm'), meta) + self.assertEqual(256, meta.get('bit_length'), meta) + self.assertEqual("cbc", meta.get('mode'), meta) + self.assertEqual( + "application/octet-stream", + meta.get('payload_content_type'), + meta + ) + + self.assertIn('secret_ref', body, body) + self.assertEqual("ACTIVE", body.get('status'), body) + self.assertEqual("key", body.get('type'), body) + self.assertIn('updated', body, body) + + # Delete one order and confirm that it got deleted + self.delete_order(order_id_1) + + body = self.order_client.list_orders() + self.assertEqual(1, body.get('total'), body) + self.assertEqual(1, len(body.get('orders')), body) + + order = body.get('orders')[0] + self.assertEqual( + order_id_2, + base._get_uuid(order.get('order_ref')), + body + ) + + # Leave one order behind to get cleaned up by infra