Merge "Give access to CredClient in tests"
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 54dd5f4..185b65d 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