Give access to CredClient in tests
There are a couple of tests that rely on creating a new project and/or
user within the test that rely on the identity_client. This doesn't work
when we want to test with api_v2=False.
As part of the isolated credentials we already have an abstraction layer
for these identity operations. Extract the abstraction class into its
own file and add it to the base test class as identity_utils
(because I'm not sure what better name to call it).
Change-Id: I6b3a505936f04d41df18c9599ca3c0b2ffd26aea
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index ef96f9b..dbca6bb 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -97,58 +97,56 @@
# TODO(afazekas): merge these test cases
@test.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
def test_get_updated_quotas(self):
- # Verify that GET shows the updated quota set of tenant
- tenant_name = data_utils.rand_name('cpu_quota_tenant')
- tenant_desc = tenant_name + '-desc'
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(name=tenant_name,
- description=tenant_desc)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
+ # Verify that GET shows the updated quota set of project
+ project_name = data_utils.rand_name('cpu_quota_project')
+ project_desc = project_name + '-desc'
+ project = self.identity_utils.create_project(name=project_name,
+ description=project_desc)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
- self.adm_client.update_quota_set(tenant_id, ram='5120')
- quota_set = self.adm_client.show_quota_set(tenant_id)['quota_set']
+ self.adm_client.update_quota_set(project_id, ram='5120')
+ quota_set = self.adm_client.show_quota_set(project_id)['quota_set']
self.assertEqual(5120, quota_set['ram'])
# Verify that GET shows the updated quota set of user
user_name = data_utils.rand_name('cpu_quota_user')
password = data_utils.rand_name('password')
email = user_name + '@testmail.tm'
- user = identity_client.create_user(name=user_name,
- password=password,
- tenant_id=tenant_id,
- email=email)
+ user = self.identity_utils.create_user(username=user_name,
+ password=password,
+ project=project,
+ email=email)
if 'user' in user:
user = user['user']
user_id = user['id']
- self.addCleanup(identity_client.delete_user, user_id)
+ self.addCleanup(self.identity_utils.delete_user, user_id)
- self.adm_client.update_quota_set(tenant_id,
+ self.adm_client.update_quota_set(project_id,
user_id=user_id,
ram='2048')
quota_set = self.adm_client.show_quota_set(
- tenant_id, user_id=user_id)['quota_set']
+ project_id, user_id=user_id)['quota_set']
self.assertEqual(2048, quota_set['ram'])
@test.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
def test_delete_quota(self):
- # Admin can delete the resource quota set for a tenant
- tenant_name = data_utils.rand_name('ram_quota_tenant')
- tenant_desc = tenant_name + '-desc'
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(name=tenant_name,
- description=tenant_desc)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
- quota_set_default = (self.adm_client.show_quota_set(tenant_id)
+ # Admin can delete the resource quota set for a project
+ project_name = data_utils.rand_name('ram_quota_project')
+ project_desc = project_name + '-desc'
+ project = self.identity_utils.create_project(name=project_name,
+ description=project_desc)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
+ quota_set_default = (self.adm_client.show_quota_set(project_id)
['quota_set'])
ram_default = quota_set_default['ram']
- self.adm_client.update_quota_set(tenant_id, ram='5120')
+ self.adm_client.update_quota_set(project_id, ram='5120')
- self.adm_client.delete_quota_set(tenant_id)
+ self.adm_client.delete_quota_set(project_id)
- quota_set_new = self.adm_client.show_quota_set(tenant_id)['quota_set']
+ quota_set_new = self.adm_client.show_quota_set(project_id)['quota_set']
self.assertEqual(ram_default, quota_set_new['ram'])
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 63395cc..f5c5784 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -51,18 +51,17 @@
def _check_quotas(self, new_quotas):
# Add a tenant to conduct the test
- test_tenant = data_utils.rand_name('test_tenant_')
- test_description = data_utils.rand_name('desc_')
- tenant = self.identity_admin_client.create_tenant(
- name=test_tenant,
- description=test_description)
- tenant_id = tenant['id']
- self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+ project = data_utils.rand_name('test_project_')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(name=project,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
# Change quotas for tenant
- quota_set = self.admin_client.update_quotas(tenant_id,
+ quota_set = self.admin_client.update_quotas(project_id,
**new_quotas)['quota']
- self.addCleanup(self.admin_client.reset_quotas, tenant_id)
+ self.addCleanup(self.admin_client.reset_quotas, project_id)
for key, value in six.iteritems(new_quotas):
self.assertEqual(value, quota_set[key])
@@ -70,21 +69,21 @@
non_default_quotas = self.admin_client.list_quotas()
found = False
for qs in non_default_quotas['quotas']:
- if qs['tenant_id'] == tenant_id:
+ if qs['tenant_id'] == project_id:
found = True
self.assertTrue(found)
# Confirm from API quotas were changed as requested for tenant
- quota_set = self.admin_client.show_quotas(tenant_id)
+ quota_set = self.admin_client.show_quotas(project_id)
quota_set = quota_set['quota']
for key, value in six.iteritems(new_quotas):
self.assertEqual(value, quota_set[key])
# Reset quotas to default and confirm
- self.admin_client.reset_quotas(tenant_id)
+ self.admin_client.reset_quotas(project_id)
non_default_quotas = self.admin_client.list_quotas()
for q in non_default_quotas['quotas']:
- self.assertNotEqual(tenant_id, q['tenant_id'])
+ self.assertNotEqual(project_id, q['tenant_id'])
@test.idempotent_id('2390f766-836d-40ef-9aeb-e810d78207fb')
def test_quotas(self):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index aa3d274..ca5a868 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -85,21 +85,21 @@
self.assertEqual(show_body['router']['name'], updated_name)
@test.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
- def test_create_router_setting_tenant_id(self):
- # Test creating router from admin user setting tenant_id.
- test_tenant = data_utils.rand_name('test_tenant_')
- test_description = data_utils.rand_name('desc_')
- tenant = self.identity_admin_client.create_tenant(
- name=test_tenant, description=test_description)
- tenant_id = tenant['id']
- self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+ def test_create_router_setting_project_id(self):
+ # Test creating router from admin user setting project_id.
+ project = data_utils.rand_name('test_tenant_')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(name=project,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
name = data_utils.rand_name('router-')
create_body = self.admin_client.create_router(name,
- tenant_id=tenant_id)
+ tenant_id=project_id)
self.addCleanup(self.admin_client.delete_router,
create_body['router']['id'])
- self.assertEqual(tenant_id, create_body['router']['tenant_id'])
+ self.assertEqual(project_id, create_body['router']['tenant_id'])
@test.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
@test.requires_ext(extension='ext-gw-mode', service='network')
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index f9117ed..b2e52bb 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -98,21 +98,22 @@
@test.idempotent_id('874b35a9-51f1-4258-bec5-cd561b6690d3')
def test_delete_quota(self):
- # Admin can delete the resource quota set for a tenant
- tenant_name = data_utils.rand_name('quota_tenant')
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(tenant_name)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
+ # Admin can delete the resource quota set for a project
+ project_name = data_utils.rand_name('quota_tenant')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(project_name,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
quota_set_default = self.quotas_client.show_default_quota_set(
- tenant_id)['quota_set']
+ project_id)['quota_set']
volume_default = quota_set_default['volumes']
- self.quotas_client.update_quota_set(tenant_id,
+ self.quotas_client.update_quota_set(project_id,
volumes=(int(volume_default) + 5))
- self.quotas_client.delete_quota_set(tenant_id)
- quota_set_new = (self.quotas_client.show_quota_set(tenant_id)
+ self.quotas_client.delete_quota_set(project_id)
+ quota_set_new = (self.quotas_client.show_quota_set(project_id)
['quota_set'])
self.assertEqual(volume_default, quota_set_new['volumes'])
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
new file mode 100644
index 0000000..7c3a77f
--- /dev/null
+++ b/tempest/common/cred_client.py
@@ -0,0 +1,146 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import abc
+
+from oslo_log import log as logging
+import six
+from tempest_lib import exceptions as lib_exc
+
+from tempest.common import cred_provider
+from tempest import config
+from tempest import exceptions
+from tempest.services.identity.v2.json import identity_client as v2_identity
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CredsClient(object):
+ """This class is a wrapper around the identity clients, to provide a
+ single interface for managing credentials in both v2 and v3 cases.
+ It's not bound to created credentials, only to a specific set of admin
+ credentials used for generating credentials.
+ """
+
+ def __init__(self, identity_client):
+ # The client implies version and credentials
+ self.identity_client = identity_client
+ self.credentials = self.identity_client.auth_provider.credentials
+
+ def create_user(self, username, password, project, email):
+ user = self.identity_client.create_user(
+ username, password, project['id'], email)
+ if 'user' in user:
+ user = user['user']
+ return user
+
+ @abc.abstractmethod
+ def create_project(self, name, description):
+ pass
+
+ def _check_role_exists(self, role_name):
+ try:
+ roles = self._list_roles()
+ role = next(r for r in roles if r['name'] == role_name)
+ except StopIteration:
+ return None
+ return role
+
+ def create_user_role(self, role_name):
+ if not self._check_role_exists(role_name):
+ self.identity_client.create_role(role_name)
+
+ def assign_user_role(self, user, project, role_name):
+ role = self._check_role_exists(role_name)
+ if not role:
+ msg = 'No "%s" role found' % role_name
+ raise lib_exc.NotFound(msg)
+ try:
+ self.identity_client.assign_user_role(project['id'], user['id'],
+ role['id'])
+ except lib_exc.Conflict:
+ LOG.debug("Role %s already assigned on project %s for user %s" % (
+ role['id'], project['id'], user['id']))
+
+ @abc.abstractmethod
+ def get_credentials(self, user, project, password):
+ pass
+
+ def delete_user(self, user_id):
+ self.identity_client.delete_user(user_id)
+
+ def _list_roles(self):
+ roles = self.identity_client.list_roles()
+ return roles
+
+
+class V2CredsClient(CredsClient):
+
+ def create_project(self, name, description):
+ tenant = self.identity_client.create_tenant(
+ name=name, description=description)
+ return tenant
+
+ def get_credentials(self, user, project, password):
+ return cred_provider.get_credentials(
+ identity_version='v2',
+ username=user['name'], user_id=user['id'],
+ tenant_name=project['name'], tenant_id=project['id'],
+ password=password)
+
+ def delete_project(self, project_id):
+ self.identity_client.delete_tenant(project_id)
+
+
+class V3CredsClient(CredsClient):
+
+ def __init__(self, identity_client, domain_name):
+ super(V3CredsClient, self).__init__(identity_client)
+ try:
+ # Domain names must be unique, in any case a list is returned,
+ # selecting the first (and only) element
+ self.creds_domain = self.identity_client.list_domains(
+ params={'name': domain_name})['domains'][0]
+ except lib_exc.NotFound:
+ # TODO(andrea) we could probably create the domain on the fly
+ msg = "Configured domain %s could not be found" % domain_name
+ raise exceptions.InvalidConfiguration(msg)
+
+ def create_project(self, name, description):
+ project = self.identity_client.create_project(
+ name=name, description=description,
+ domain_id=self.creds_domain['id'])['project']
+ return project
+
+ def get_credentials(self, user, project, password):
+ return cred_provider.get_credentials(
+ identity_version='v3',
+ username=user['name'], user_id=user['id'],
+ project_name=project['name'], project_id=project['id'],
+ password=password,
+ project_domain_name=self.creds_domain['name'])
+
+ def delete_project(self, project_id):
+ self.identity_client.delete_project(project_id)
+
+ def _list_roles(self):
+ roles = self.identity_client.list_roles()['roles']
+ return roles
+
+
+def get_creds_client(identity_client, project_domain_name=None):
+ if isinstance(identity_client, v2_identity.IdentityClient):
+ return V2CredsClient(identity_client)
+ else:
+ return V3CredsClient(identity_client, project_domain_name)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 6dca3a3..a4081c9 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -12,144 +12,22 @@
# License for the specific language governing permissions and limitations
# under the License.
-import abc
import netaddr
from oslo_log import log as logging
import six
from tempest_lib import exceptions as lib_exc
from tempest import clients
+from tempest.common import cred_client
from tempest.common import cred_provider
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
-from tempest.services.identity.v2.json import identity_client as v2_identity
CONF = config.CONF
LOG = logging.getLogger(__name__)
-@six.add_metaclass(abc.ABCMeta)
-class CredsClient(object):
- """This class is a wrapper around the identity clients, to provide a
- single interface for managing credentials in both v2 and v3 cases.
- It's not bound to created credentials, only to a specific set of admin
- credentials used for generating credentials.
- """
-
- def __init__(self, identity_client):
- # The client implies version and credentials
- self.identity_client = identity_client
- self.credentials = self.identity_client.auth_provider.credentials
-
- def create_user(self, username, password, project, email):
- user = self.identity_client.create_user(
- username, password, project['id'], email)
- if 'user' in user:
- user = user['user']
- return user
-
- @abc.abstractmethod
- def create_project(self, name, description):
- pass
-
- def _check_role_exists(self, role_name):
- try:
- roles = self._list_roles()
- role = next(r for r in roles if r['name'] == role_name)
- except StopIteration:
- return None
- return role
-
- def create_user_role(self, role_name):
- if not self._check_role_exists(role_name):
- self.identity_client.create_role(role_name)
-
- def assign_user_role(self, user, project, role_name):
- role = self._check_role_exists(role_name)
- if not role:
- msg = 'No "%s" role found' % role_name
- raise lib_exc.NotFound(msg)
- try:
- self.identity_client.assign_user_role(project['id'], user['id'],
- role['id'])
- except lib_exc.Conflict:
- LOG.debug("Role %s already assigned on project %s for user %s" % (
- role['id'], project['id'], user['id']))
-
- @abc.abstractmethod
- def get_credentials(self, user, project, password):
- pass
-
- def delete_user(self, user_id):
- self.identity_client.delete_user(user_id)
-
- def _list_roles(self):
- roles = self.identity_client.list_roles()
- return roles
-
-
-class V2CredsClient(CredsClient):
-
- def create_project(self, name, description):
- tenant = self.identity_client.create_tenant(
- name=name, description=description)
- return tenant
-
- def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
- identity_version='v2',
- username=user['name'], user_id=user['id'],
- tenant_name=project['name'], tenant_id=project['id'],
- password=password)
-
- def delete_project(self, project_id):
- self.identity_client.delete_tenant(project_id)
-
-
-class V3CredsClient(CredsClient):
-
- def __init__(self, identity_client, domain_name):
- super(V3CredsClient, self).__init__(identity_client)
- try:
- # Domain names must be unique, in any case a list is returned,
- # selecting the first (and only) element
- self.creds_domain = self.identity_client.list_domains(
- params={'name': domain_name})['domains'][0]
- except lib_exc.NotFound:
- # TODO(andrea) we could probably create the domain on the fly
- msg = "Configured domain %s could not be found" % domain_name
- raise exceptions.InvalidConfiguration(msg)
-
- def create_project(self, name, description):
- project = self.identity_client.create_project(
- name=name, description=description,
- domain_id=self.creds_domain['id'])['project']
- return project
-
- def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
- identity_version='v3',
- username=user['name'], user_id=user['id'],
- project_name=project['name'], project_id=project['id'],
- password=password,
- project_domain_name=self.creds_domain['name'])
-
- def delete_project(self, project_id):
- self.identity_client.delete_project(project_id)
-
- def _list_roles(self):
- roles = self.identity_client.list_roles()['roles']
- return roles
-
-
-def get_creds_client(identity_client, project_domain_name=None):
- if isinstance(identity_client, v2_identity.IdentityClient):
- return V2CredsClient(identity_client)
- else:
- return V3CredsClient(identity_client, project_domain_name)
-
-
class IsolatedCreds(cred_provider.CredentialProvider):
def __init__(self, identity_version=None, name=None,
@@ -171,7 +49,7 @@
self.creds_domain_name = (
self.default_admin_creds.project_domain_name or
CONF.auth.default_credentials_domain_name)
- self.creds_client = get_creds_client(
+ self.creds_client = cred_client.get_creds_client(
self.identity_admin_client, self.creds_domain_name)
def _get_admin_clients(self):
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index bdb39d8..7634d2c 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -25,7 +25,7 @@
from tempest import clients
-from tempest.common import isolated_creds
+from tempest.common import cred_client
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -155,7 +155,7 @@
identity_client = admin_manager.identity_client
else:
identity_client = admin_manager.identity_v3_client
- credentials_client = isolated_creds.get_creds_client(
+ credentials_client = cred_client.get_creds_client(
identity_client)
project = credentials_client.create_project(
name=tenant_name, description=tenant_name)
diff --git a/tempest/test.py b/tempest/test.py
index df6b30d..e10f606 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -31,6 +31,7 @@
import testtools
from tempest import clients
+from tempest.common import cred_client
from tempest.common import credentials
from tempest.common import fixed_network
import tempest.common.generator.valid_generator as valid
@@ -432,6 +433,25 @@
def credentials_provider(self):
return self._get_credentials_provider()
+ @property
+ def identity_utils(self):
+ """A client that abstracts v2 and v3 identity operations.
+
+ This can be used for creating and tearing down projects in tests. It
+ should not be used for testing identity features.
+ """
+ if CONF.identity.auth_version == 'v2':
+ client = self.os_admin.identity_client
+ else:
+ client = self.os_admin.identity_v3_client
+
+ try:
+ domain = client.auth_provider.credentials.project_domain_name
+ except AttributeError:
+ domain = 'Default'
+
+ return cred_client.get_creds_client(client, domain)
+
@classmethod
def _get_credentials_provider(cls):
"""Returns a credentials provider