Add a QuotaClient and quota API tests
This change adds a QuotaClient for testing the Barbican quota API.
It adds a quota test suite and integrates the QuotaClient with the
plugin testing infrastructure.
Change-Id: I3249fb879f519da63129e0ec5117377a21094974
Depends-On: I813648476a3a7b0b0e416a524d4629dffe36c92e
Implements: bp tempest-plugin
diff --git a/barbican_tempest_plugin/plugin.py b/barbican_tempest_plugin/plugin.py
index a0f4ca4..2c13b24 100644
--- a/barbican_tempest_plugin/plugin.py
+++ b/barbican_tempest_plugin/plugin.py
@@ -45,6 +45,7 @@
'ConsumerClient',
'ContainerClient',
'OrderClient',
+ 'QuotaClient',
'SecretClient',
'SecretMetadataClient'
],
diff --git a/barbican_tempest_plugin/services/key_manager/json/__init__.py b/barbican_tempest_plugin/services/key_manager/json/__init__.py
index b3ee41e..7bce46a 100644
--- a/barbican_tempest_plugin/services/key_manager/json/__init__.py
+++ b/barbican_tempest_plugin/services/key_manager/json/__init__.py
@@ -18,6 +18,8 @@
import ContainerClient
from barbican_tempest_plugin.services.key_manager.json.order_client \
import OrderClient
+from barbican_tempest_plugin.services.key_manager.json.quota_client \
+ import QuotaClient
from barbican_tempest_plugin.services.key_manager.json.secret_client \
import SecretClient
from barbican_tempest_plugin.services.key_manager.json.secret_metadata_client \
@@ -27,6 +29,7 @@
'ConsumerClient',
'ContainerClient',
'OrderClient',
+ 'QuotaClient',
'SecretClient',
'SecretMetadataClient'
]
diff --git a/barbican_tempest_plugin/services/key_manager/json/quota_client.py b/barbican_tempest_plugin/services/key_manager/json/quota_client.py
new file mode 100644
index 0000000..2f90546
--- /dev/null
+++ b/barbican_tempest_plugin/services/key_manager/json/quota_client.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2017 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 QuotaClient(rest_client.RestClient):
+
+ def list_quotas(self, **kwargs):
+ uri = "v1/project-quotas"
+ if kwargs:
+ uri += "?%s" % urllib.urlencode(kwargs)
+
+ response, body = self.get(uri)
+ self.expected_success(200, response.status)
+ return json.loads(body)
+
+ def get_default_project_quota(self):
+ uri = "v1/quotas"
+
+ response, body = self.get(uri)
+ self.expected_success(200, response.status)
+ return json.loads(body)
+
+ def get_project_quota(self, project_id):
+ uri = "v1/project-quotas/%s" % project_id
+
+ response, body = self.get(uri)
+ self.expected_success(200, response.status)
+ return json.loads(body)
+
+ def create_project_quota(self, project_id, **kwargs):
+ uri = "v1/project-quotas/%s" % project_id
+
+ response, body = self.put(uri, json.dumps(kwargs))
+ self.expected_success(204, response.status)
+ return
+
+ def delete_project_quota(self, project_id):
+ uri = "v1/project-quotas/%s" % project_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 abf1e83..7256a10 100644
--- a/barbican_tempest_plugin/tests/api/base.py
+++ b/barbican_tempest_plugin/tests/api/base.py
@@ -23,7 +23,7 @@
CONF = config.CONF
# NOTE(dane-fichter): We need to track resource types for cleanup.
-RESOURCE_TYPES = ['container', 'order', 'secret']
+RESOURCE_TYPES = ['container', 'order', 'quota', 'secret']
def _get_uuid(href):
@@ -45,6 +45,9 @@
secret_ref = order_metadata.get('secret_ref')
if secret_ref:
cls.created_objects['secret'].add(_get_uuid(secret_ref))
+ uuid = _get_uuid(resp['order_ref'])
+ if resource == 'quota':
+ uuid = _get_uuid(args[0])
if resource == 'secret':
uuid = _get_uuid(resp['secret_ref'])
cls.created_objects[resource].add(uuid)
@@ -57,7 +60,7 @@
"""Base class for all api tests."""
# Why do I have to be an admin to create secrets? No idea...
- credentials = ('admin', )
+ credentials = ('admin', ['service_admin', 'key-manager:service-admin'])
client_manager = clients.Clients
created_objects = {}
@@ -77,6 +80,9 @@
service='key-manager'
)
+ os = getattr(cls, 'os_roles_%s' % cls.credentials[1][0])
+ cls.quota_client = os.secret_v1.QuotaClient(service='key-manager')
+
@classmethod
def resource_setup(cls):
super(BaseKeyManagerTest, cls).resource_setup()
@@ -90,6 +96,8 @@
cls.delete_container(container_uuid)
for order_uuid in list(cls.created_objects['order']):
cls.delete_order(order_uuid)
+ for project_quota_uuid in list(cls.created_objects['quota']):
+ cls.delete_project_quota(project_quota_uuid)
for secret_uuid in list(cls.created_objects['secret']):
cls.delete_secret(secret_uuid)
finally:
@@ -120,6 +128,16 @@
return cls.order_client.delete_order(uuid)
@classmethod
+ @creates('quota')
+ def create_project_quota(cls, project_id, **kwargs):
+ return cls.quota_client.create_project_quota(project_id, **kwargs)
+
+ @classmethod
+ def delete_project_quota(cls, project_id):
+ cls.created_objects['quota'].remove(project_id)
+ return cls.quota_client.delete_project_quota(project_id)
+
+ @classmethod
@creates('secret')
def create_secret(cls, **kwargs):
return cls.secret_client.create_secret(**kwargs)
diff --git a/barbican_tempest_plugin/tests/api/test_quotas.py b/barbican_tempest_plugin/tests/api/test_quotas.py
new file mode 100644
index 0000000..882fbb1
--- /dev/null
+++ b/barbican_tempest_plugin/tests/api/test_quotas.py
@@ -0,0 +1,79 @@
+# 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
+
+from tempest import config
+
+CONF = config.CONF
+
+
+class QuotasTest(base.BaseKeyManagerTest):
+ """Quotas API tests."""
+
+ def test_create_get_delete_quota(self):
+ # Verify the default quota settings
+ body = self.quota_client.get_default_project_quota()
+ quotas = body.get('quotas')
+ self.assertEqual(-1, quotas.get('secrets'))
+ self.assertEqual(-1, quotas.get('cas'))
+ self.assertEqual(-1, quotas.get('orders'))
+ self.assertEqual(-1, quotas.get('containers'))
+ self.assertEqual(-1, quotas.get('consumers'))
+
+ # Confirm that there are no quotas
+ body = self.quota_client.list_quotas()
+ self.assertEqual(0, body.get('total'), body)
+ self.assertEqual(0, len(body.get('project_quotas')), body)
+
+ # Create a quota set for the test project
+ self.create_project_quota(
+ self.quota_client.tenant_id,
+ project_quotas={
+ 'secrets': 30,
+ 'orders': 10,
+ 'containers': 20
+ }
+ )
+
+ # Verify that the quotas can be found via generic listing.
+ body = self.quota_client.list_quotas()
+ self.assertEqual(1, body.get('total'), body)
+ self.assertEqual(1, len(body.get('project_quotas')), body)
+ project_quotas = body.get('project_quotas')[0]
+ self.assertEqual(
+ self.quota_client.tenant_id,
+ project_quotas.get('project_id'),
+ body
+ )
+ project_quotas = project_quotas.get('project_quotas')
+ self.assertEqual(30, project_quotas.get('secrets'), body)
+ self.assertEqual(10, project_quotas.get('orders'), body)
+ self.assertEqual(20, project_quotas.get('containers'), body)
+
+ # Verify that the quotas can be found via specific listing.
+ body = self.quota_client.get_project_quota(
+ self.quota_client.tenant_id
+ )
+ project_quotas = body.get('project_quotas')
+ self.assertEqual(30, project_quotas.get('secrets'), body)
+ self.assertEqual(10, project_quotas.get('orders'), body)
+ self.assertEqual(20, project_quotas.get('containers'), body)
+
+ # Delete the project quota and confirm that it got deleted
+ self.delete_project_quota(self.quota_client.tenant_id)
+
+ body = self.quota_client.list_quotas()
+ self.assertEqual(0, body.get('total'), body)
+ self.assertEqual(0, len(body.get('project_quotas')), body)