Factor up config dependent credential classes
Separate helpers methods to build credentials, credential providers and
client managers that depend on configuration. They are all moved to
the common.credentials module to achieve two objectives:
- prepare credential provider module to move to tempest-lib
- avoid circular dependencies
There are still dependencies to CONF in the credential providers,
removing all of them would make the patch too large; but there is
with this patch a single place where all relevant CONF parameters can
be looked up and passed into the credential providers.
Partially-implements: bp tempest-library
Change-Id: I351f86f0570070105bbf24f2d904e917feea6e57
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index f228040..2cc4b83 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -127,16 +127,16 @@
unexpected failures in some tests.
-Non-locking test accounts (aka credentials config options)
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+Legacy test accounts (aka credentials config options)
+"""""""""""""""""""""""""""""""""""""""""""""""""""""
**Starting in the Liberty release this mechanism was deprecated and will be
removed in a future release**
When Tempest was refactored to allow for locking test accounts, the original
non-tenant isolated case was converted to internally work similarly to the
-accounts.yaml file. This mechanism was then called the non-locking test accounts
-provider. To use the non-locking test accounts provider you can specify the sets
-of credentials in the configuration file like detailed above with following 9
+accounts.yaml file. This mechanism was then called the legacy test accounts
+provider. To use the legacy test accounts provider you can specify the sets of
+credentials in the configuration file like detailed above with following 9
options in the identity section:
#. username
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index fac8826..a8b0af9 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest import clients
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common.utils import data_utils
from tempest import config
from tempest import test
@@ -89,7 +89,7 @@
self.assertIsNotNone(self.trustee_user_id)
# Initialize a new client with the trustor credentials
- creds = cred_provider.get_credentials(
+ creds = common_creds.get_credentials(
identity_version='v3',
username=self.trustor_username,
password=self.trustor_password,
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 95826b0..526b44d 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -16,7 +16,7 @@
from oslo_log import log as logging
from tempest_lib import exceptions as lib_exc
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common.utils import data_utils
from tempest import config
import tempest.test
@@ -195,11 +195,11 @@
@property
def test_credentials(self):
- return cred_provider.get_credentials(username=self.test_user,
- user_id=self.user['id'],
- password=self.test_password,
- tenant_name=self.test_tenant,
- tenant_id=self.tenant['id'])
+ return common_creds.get_credentials(username=self.test_user,
+ user_id=self.user['id'],
+ password=self.test_password,
+ tenant_name=self.test_tenant,
+ tenant_id=self.tenant['id'])
def setup_test_user(self):
"""Set up a test user."""
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 070150d..bf28da4 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -16,7 +16,7 @@
import netaddr
from tempest.api.orchestration import base
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -38,7 +38,7 @@
@classmethod
def setup_credentials(cls):
super(NeutronResourcesTestJSON, cls).setup_credentials()
- cls.os = clients.Manager()
+ cls.os = credentials.ConfiguredUserManager()
@classmethod
def setup_clients(cls):
diff --git a/tempest/clients.py b/tempest/clients.py
index 84e8544..03e6930 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -38,7 +38,6 @@
from tempest_lib.services.identity.v2.token_client import TokenClient
from tempest_lib.services.identity.v3.token_client import V3TokenClient
-from tempest.common import cred_provider
from tempest.common import negative_rest_client
from tempest import config
from tempest import exceptions
@@ -174,7 +173,7 @@
}
default_params_with_timeout_values.update(default_params)
- def __init__(self, credentials=None, service=None):
+ def __init__(self, credentials, service=None):
super(Manager, self).__init__(credentials=credentials)
self._set_compute_clients()
@@ -475,17 +474,3 @@
self.account_client = AccountClient(self.auth_provider, **params)
self.container_client = ContainerClient(self.auth_provider, **params)
self.object_client = ObjectClient(self.auth_provider, **params)
-
-
-class AdminManager(Manager):
-
- """
- Manager object that uses the admin credentials for its
- managed client objects
- """
-
- def __init__(self, service=None):
- super(AdminManager, self).__init__(
- credentials=cred_provider.get_configured_credentials(
- 'identity_admin'),
- service=service)
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 4fa4302..5f421d6 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -58,7 +58,7 @@
from tempest import clients
from tempest.cmd import cleanup_service
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as credentials
from tempest import config
SAVED_STATE_JSON = "saved_state.json"
@@ -75,7 +75,7 @@
def take_action(self, parsed_args):
cleanup_service.init_conf()
self.options = parsed_args
- self.admin_mgr = clients.AdminManager()
+ self.admin_mgr = credentials.AdminManager()
self.dry_run_data = {}
self.json_data = {}
@@ -162,7 +162,7 @@
kwargs = {"username": CONF.auth.admin_username,
"password": CONF.auth.admin_password,
"tenant_name": tenant['name']}
- mgr = clients.Manager(credentials=cred_provider.get_credentials(
+ mgr = clients.Manager(credentials=credentials.get_credentials(
**kwargs))
kwargs = {'data': tenant_data,
'is_dry_run': is_dry_run,
@@ -235,7 +235,7 @@
LOG.debug("Remove admin user role for tenant: %s" % tenant_id)
# Must initialize AdminManager for each user role
# Otherwise authentication exception is thrown, weird
- id_cl = clients.AdminManager().identity_client
+ id_cl = credentials.AdminManager().identity_client
if (self._tenant_exists(tenant_id)):
try:
id_cl.remove_user_role(tenant_id, self.admin_id,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 1b5820b..362e52c 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -16,7 +16,7 @@
from oslo_log import log as logging
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest import test
@@ -82,7 +82,7 @@
def _get_network_id(net_name, tenant_name):
- am = clients.AdminManager()
+ am = credentials.AdminManager()
net_cl = am.networks_client
id_cl = am.identity_client
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 2811070..9c8e2a0 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -24,7 +24,7 @@
from six.moves.urllib import parse as urlparse
from tempest import clients
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 3575998..e5f24b3 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -18,83 +18,10 @@
import six
from tempest_lib import auth
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
LOG = logging.getLogger(__name__)
-# Type of credentials available from configuration
-CREDENTIAL_TYPES = {
- 'identity_admin': ('auth', 'admin'),
- 'user': ('identity', None),
- 'alt_user': ('identity', 'alt')
-}
-
-DEFAULT_PARAMS = {
- 'disable_ssl_certificate_validation':
- CONF.identity.disable_ssl_certificate_validation,
- 'ca_certs': CONF.identity.ca_certificates_file,
- 'trace_requests': CONF.debug.trace_requests
-}
-
-
-# Read credentials from configuration, builds a Credentials object
-# based on the specified or configured version
-def get_configured_credentials(credential_type, fill_in=True,
- identity_version=None):
- identity_version = identity_version or CONF.identity.auth_version
- if identity_version not in ('v2', 'v3'):
- raise exceptions.InvalidConfiguration(
- 'Unsupported auth version: %s' % identity_version)
- if credential_type not in CREDENTIAL_TYPES:
- raise exceptions.InvalidCredentials()
- conf_attributes = ['username', 'password', 'tenant_name']
- if identity_version == 'v3':
- conf_attributes.append('domain_name')
- # Read the parts of credentials from config
- params = DEFAULT_PARAMS.copy()
- section, prefix = CREDENTIAL_TYPES[credential_type]
- for attr in conf_attributes:
- _section = getattr(CONF, section)
- if prefix is None:
- params[attr] = getattr(_section, attr)
- else:
- params[attr] = getattr(_section, prefix + "_" + attr)
- # Build and validate credentials. We are reading configured credentials,
- # so validate them even if fill_in is False
- credentials = get_credentials(fill_in=fill_in,
- identity_version=identity_version, **params)
- if not fill_in:
- if not credentials.is_valid():
- msg = ("The %s credentials are incorrectly set in the config file."
- " Double check that all required values are assigned" %
- credential_type)
- raise exceptions.InvalidConfiguration(msg)
- return credentials
-
-
-# Wrapper around auth.get_credentials to use the configured identity version
-# is none is specified
-def get_credentials(fill_in=True, identity_version=None, **kwargs):
- params = dict(DEFAULT_PARAMS, **kwargs)
- identity_version = identity_version or CONF.identity.auth_version
- # In case of "v3" add the domain from config if not specified
- if identity_version == 'v3':
- domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
- if 'domain' in x)
- if not domain_fields.intersection(kwargs.keys()):
- domain_name = CONF.auth.default_credentials_domain_name
- params['user_domain_name'] = domain_name
-
- auth_url = CONF.identity.uri_v3
- else:
- auth_url = CONF.identity.uri
- return auth.get_credentials(auth_url,
- fill_in=fill_in,
- identity_version=identity_version,
- **params)
-
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
diff --git a/tempest/common/credentials.py b/tempest/common/credentials.py
deleted file mode 100644
index 76f8afe..0000000
--- a/tempest/common/credentials.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# 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 os
-
-from tempest.common import cred_provider
-from tempest.common import dynamic_creds
-from tempest.common import preprov_creds
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
-
-
-# Return the right implementation of CredentialProvider based on config
-# Dropping interface and password, as they are never used anyways
-# TODO(andreaf) Drop them from the CredentialsProvider interface completely
-def get_credentials_provider(name, network_resources=None,
- force_tenant_isolation=False,
- identity_version=None):
- # If a test requires a new account to work, it can have it via forcing
- # dynamic credentials. A new account will be produced only for that test.
- # In case admin credentials are not available for the account creation,
- # the test should be skipped else it would fail.
- identity_version = identity_version or CONF.identity.auth_version
- if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
- return dynamic_creds.DynamicCredentialProvider(
- name=name,
- network_resources=network_resources,
- identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role)
- else:
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- # Most params are not relevant for pre-created accounts
- return preprov_creds.PreProvisionedCredentialProvider(
- name=name, identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role)
- else:
- return preprov_creds.NonLockingCredentialProvider(
- name=name, identity_version=identity_version,
- admin_role=CONF.identity.admin_role)
-
-
-# We want a helper function here to check and see if admin credentials
-# are available so we can do a single call from skip_checks if admin
-# creds area available.
-# This depends on identity_version as there may be admin credentials
-# available for v2 but not for v3.
-def is_admin_available(identity_version):
- is_admin = True
- # If dynamic credentials is enabled admin will be available
- if CONF.auth.use_dynamic_credentials:
- return is_admin
- # Check whether test accounts file has the admin specified or not
- elif (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_admin',
- admin_role=CONF.identity.admin_role)
- if not check_accounts.admin_available():
- is_admin = False
- else:
- try:
- cred_provider.get_configured_credentials(
- 'identity_admin', fill_in=False,
- identity_version=identity_version)
- except exceptions.InvalidConfiguration:
- is_admin = False
- return is_admin
-
-
-# We want a helper function here to check and see if alt credentials
-# are available so we can do a single call from skip_checks if alt
-# creds area available.
-# This depends on identity_version as there may be alt credentials
-# available for v2 but not for v3.
-def is_alt_available(identity_version):
- # If dynamic credentials is enabled alt will be available
- if CONF.auth.use_dynamic_credentials:
- return True
- # Check whether test accounts file has the admin specified or not
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_alt',
- admin_role=CONF.identity.admin_role)
- else:
- check_accounts = preprov_creds.NonLockingCredentialProvider(
- identity_version=identity_version, name='check_alt',
- admin_role=CONF.identity.admin_role)
- try:
- if not check_accounts.is_multi_user():
- return False
- else:
- return True
- except exceptions.InvalidConfiguration:
- return False
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
new file mode 100644
index 0000000..486b7fd
--- /dev/null
+++ b/tempest/common/credentials_factory.py
@@ -0,0 +1,316 @@
+# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+# 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 os
+
+from oslo_log import log as logging
+from tempest_lib import auth
+
+from tempest import clients
+from tempest.common import cred_provider
+from tempest.common import dynamic_creds
+from tempest.common import preprov_creds
+from tempest import config
+from tempest import exceptions
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+"""This module provides factories of credential and credential providers
+
+Credentials providers and clients are (going to be) part of tempest-lib,
+and so they may not hold any dependency to tempest configuration.
+
+Methods in this module collect the relevant configuration details and pass
+them to credentials providers and clients, so that test can have easy
+access to these features.
+
+Client managers with hard-coded configured credentials are also moved here,
+to avoid circular dependencies."""
+
+# === Credential Providers
+
+
+class LegacyCredentialProvider(cred_provider.CredentialProvider):
+
+ def __init__(self, identity_version):
+ """Credentials provider which returns credentials from tempest.conf
+
+ Credentials provider which always returns the first and second
+ configured accounts as primary and alt users.
+ Credentials from tempest.conf are deprecated, and this credential
+ provider is also accordingly.
+
+ This credential provider can be used in case of serial test execution
+ to preserve the current behaviour of the serial tempest run.
+
+ :param identity_version: Version of the identity API
+ :return: CredentialProvider
+ """
+ super(LegacyCredentialProvider, self).__init__(
+ identity_version=identity_version)
+ self._creds = {}
+
+ def _unique_creds(self, cred_arg=None):
+ """Verify that the configured credentials are valid and distinct """
+ try:
+ user = self.get_primary_creds()
+ alt_user = self.get_alt_creds()
+ return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
+ except exceptions.InvalidCredentials as ic:
+ msg = "At least one of the configured credentials is " \
+ "not valid: %s" % ic.message
+ raise exceptions.InvalidConfiguration(msg)
+
+ def is_multi_user(self):
+ return self._unique_creds('username')
+
+ def is_multi_tenant(self):
+ return self._unique_creds('tenant_id')
+
+ def get_primary_creds(self):
+ if self._creds.get('primary'):
+ return self._creds.get('primary')
+ primary_credential = get_configured_credentials(
+ credential_type='user', fill_in=False,
+ identity_version=self.identity_version)
+ self._creds['primary'] = cred_provider.TestResources(
+ primary_credential)
+ return self._creds['primary']
+
+ def get_alt_creds(self):
+ if self._creds.get('alt'):
+ return self._creds.get('alt')
+ alt_credential = get_configured_credentials(
+ credential_type='alt_user', fill_in=False,
+ identity_version=self.identity_version)
+ self._creds['alt'] = cred_provider.TestResources(
+ alt_credential)
+ return self._creds['alt']
+
+ def clear_creds(self):
+ self._creds = {}
+
+ def get_admin_creds(self):
+ if self._creds.get('admin'):
+ return self._creds.get('admin')
+ creds = get_configured_credentials(
+ "identity_admin", fill_in=False)
+ self._creds['admin'] = cred_provider.TestResources(creds)
+ return self._creds['admin']
+
+ def get_creds_by_roles(self, roles, force_new=False):
+ msg = "Credentials being specified through the config file can not be"\
+ " used with tests that specify using credentials by roles. "\
+ "Either exclude/skip the tests doing this or use either an "\
+ "test_accounts_file or dynamic credentials."
+ raise exceptions.InvalidConfiguration(msg)
+
+ def is_role_available(self, role):
+ msg = "Credentials being specified through the config file can not be"\
+ " used with tests that specify using credentials by roles. "\
+ "Either exclude/skip the tests doing this or use either an "\
+ "test_accounts_file or dynamic credentials."
+ raise exceptions.InvalidConfiguration(msg)
+
+
+# Return the right implementation of CredentialProvider based on config
+# Dropping interface and password, as they are never used anyways
+# TODO(andreaf) Drop them from the CredentialsProvider interface completely
+def get_credentials_provider(name, network_resources=None,
+ force_tenant_isolation=False,
+ identity_version=None):
+ # If a test requires a new account to work, it can have it via forcing
+ # dynamic credentials. A new account will be produced only for that test.
+ # In case admin credentials are not available for the account creation,
+ # the test should be skipped else it would fail.
+ identity_version = identity_version or CONF.identity.auth_version
+ if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
+ admin_creds = get_configured_credentials(
+ 'identity_admin', fill_in=True, identity_version=identity_version)
+ return dynamic_creds.DynamicCredentialProvider(
+ name=name,
+ network_resources=network_resources,
+ identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role,
+ admin_creds=admin_creds)
+ else:
+ if (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ # Most params are not relevant for pre-created accounts
+ return preprov_creds.PreProvisionedCredentialProvider(
+ name=name, identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role)
+ else:
+ # Dynamic credentials are disabled, and the account file is not
+ # defined - we fall back on credentials configured in tempest.conf
+ return LegacyCredentialProvider(identity_version=identity_version)
+
+
+# We want a helper function here to check and see if admin credentials
+# are available so we can do a single call from skip_checks if admin
+# creds area available.
+# This depends on identity_version as there may be admin credentials
+# available for v2 but not for v3.
+def is_admin_available(identity_version):
+ is_admin = True
+ # If dynamic credentials is enabled admin will be available
+ if CONF.auth.use_dynamic_credentials:
+ return is_admin
+ # Check whether test accounts file has the admin specified or not
+ elif (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_admin',
+ admin_role=CONF.identity.admin_role)
+ if not check_accounts.admin_available():
+ is_admin = False
+ else:
+ try:
+ get_configured_credentials('identity_admin', fill_in=False,
+ identity_version=identity_version)
+ except exceptions.InvalidConfiguration:
+ is_admin = False
+ return is_admin
+
+
+# We want a helper function here to check and see if alt credentials
+# are available so we can do a single call from skip_checks if alt
+# creds area available.
+# This depends on identity_version as there may be alt credentials
+# available for v2 but not for v3.
+def is_alt_available(identity_version):
+ # If dynamic credentials is enabled alt will be available
+ if CONF.auth.use_dynamic_credentials:
+ return True
+ # Check whether test accounts file has the admin specified or not
+ if (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_alt',
+ admin_role=CONF.identity.admin_role)
+ else:
+ check_accounts = LegacyCredentialProvider(identity_version)
+ try:
+ if not check_accounts.is_multi_user():
+ return False
+ else:
+ return True
+ except exceptions.InvalidConfiguration:
+ return False
+
+# === Credentials
+
+# Type of credentials available from configuration
+CREDENTIAL_TYPES = {
+ 'identity_admin': ('auth', 'admin'),
+ 'user': ('identity', None),
+ 'alt_user': ('identity', 'alt')
+}
+
+DEFAULT_PARAMS = {
+ 'disable_ssl_certificate_validation':
+ CONF.identity.disable_ssl_certificate_validation,
+ 'ca_certs': CONF.identity.ca_certificates_file,
+ 'trace_requests': CONF.debug.trace_requests
+}
+
+
+# Read credentials from configuration, builds a Credentials object
+# based on the specified or configured version
+def get_configured_credentials(credential_type, fill_in=True,
+ identity_version=None):
+ identity_version = identity_version or CONF.identity.auth_version
+
+ if identity_version not in ('v2', 'v3'):
+ raise exceptions.InvalidConfiguration(
+ 'Unsupported auth version: %s' % identity_version)
+
+ if credential_type not in CREDENTIAL_TYPES:
+ raise exceptions.InvalidCredentials()
+ conf_attributes = ['username', 'password', 'tenant_name']
+
+ if identity_version == 'v3':
+ conf_attributes.append('domain_name')
+ # Read the parts of credentials from config
+ params = DEFAULT_PARAMS.copy()
+ section, prefix = CREDENTIAL_TYPES[credential_type]
+ for attr in conf_attributes:
+ _section = getattr(CONF, section)
+ if prefix is None:
+ params[attr] = getattr(_section, attr)
+ else:
+ params[attr] = getattr(_section, prefix + "_" + attr)
+ # Build and validate credentials. We are reading configured credentials,
+ # so validate them even if fill_in is False
+ credentials = get_credentials(fill_in=fill_in,
+ identity_version=identity_version, **params)
+ if not fill_in:
+ if not credentials.is_valid():
+ msg = ("The %s credentials are incorrectly set in the config file."
+ " Double check that all required values are assigned" %
+ credential_type)
+ raise exceptions.InvalidConfiguration(msg)
+ return credentials
+
+
+# Wrapper around auth.get_credentials to use the configured identity version
+# is none is specified
+def get_credentials(fill_in=True, identity_version=None, **kwargs):
+ params = dict(DEFAULT_PARAMS, **kwargs)
+ identity_version = identity_version or CONF.identity.auth_version
+ # In case of "v3" add the domain from config if not specified
+ if identity_version == 'v3':
+ domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
+ if 'domain' in x)
+ if not domain_fields.intersection(kwargs.keys()):
+ domain_name = CONF.auth.default_credentials_domain_name
+ params['user_domain_name'] = domain_name
+
+ auth_url = CONF.identity.uri_v3
+ else:
+ auth_url = CONF.identity.uri
+ return auth.get_credentials(auth_url,
+ fill_in=fill_in,
+ identity_version=identity_version,
+ **params)
+
+# === Credential / client managers
+
+
+class ConfiguredUserManager(clients.Manager):
+ """
+ Manager object that uses the `user` credentials for its
+ managed client objects
+ """
+
+ def __init__(self, service=None):
+ super(ConfiguredUserManager, self).__init__(
+ credentials=get_configured_credentials('user'),
+ service=service)
+
+
+class AdminManager(clients.Manager):
+
+ """
+ Manager object that uses the admin credentials for its
+ managed client objects
+ """
+
+ def __init__(self, service=None):
+ super(AdminManager, self).__init__(
+ credentials=get_configured_credentials('identity_admin'),
+ service=service)
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index e2df560..de65cf4 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -31,16 +31,32 @@
class DynamicCredentialProvider(cred_provider.CredentialProvider):
def __init__(self, identity_version, name=None, network_resources=None,
- credentials_domain=None, admin_role=None):
+ credentials_domain=None, admin_role=None, admin_creds=None):
+ """Creates credentials dynamically for tests
+
+ A credential provider that, based on an initial set of
+ admin credentials, creates new credentials on the fly for
+ tests to use and then discard.
+
+ :param str identity_version: identity API version to use `v2` or `v3`
+ :param str admin_role: name of the admin role added to admin users
+ :param str name: names of dynamic resources include this parameter
+ when specified
+ :param str credentials_domain: name of the domain where the users
+ are created. If not defined, the project
+ domain from admin_credentials is used
+ :param dict network_resources: network resources to be created for
+ the created credentials
+ :param Credentials admin_creds: initial admin credentials
+ """
super(DynamicCredentialProvider, self).__init__(
- identity_version=identity_version, name=name,
- network_resources=network_resources,
- credentials_domain=credentials_domain, admin_role=admin_role)
+ identity_version=identity_version, admin_role=admin_role,
+ name=name, credentials_domain=credentials_domain,
+ network_resources=network_resources)
+ self.network_resources = network_resources
self._creds = {}
self.ports = []
- self.default_admin_creds = cred_provider.get_configured_credentials(
- 'identity_admin', fill_in=True,
- identity_version=self.identity_version)
+ self.default_admin_creds = admin_creds
(self.identity_admin_client, self.network_admin_client,
self.networks_admin_client,
self.subnets_admin_client) = self._get_admin_clients()
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index dd27f08..f711302 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -310,64 +310,3 @@
if not user_domain_fields.intersection(set(creds_dict.keys())):
creds_dict['user_domain_name'] = self.credentials_domain
return creds_dict
-
-
-class NonLockingCredentialProvider(PreProvisionedCredentialProvider):
- """Credentials provider which always returns the first and second
- configured accounts as primary and alt users.
- This credential provider can be used in case of serial test execution
- to preserve the current behaviour of the serial tempest run.
- """
-
- def _unique_creds(self, cred_arg=None):
- """Verify that the configured credentials are valid and distinct """
- try:
- user = self.get_primary_creds()
- alt_user = self.get_alt_creds()
- return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
- except exceptions.InvalidCredentials as ic:
- msg = "At least one of the configured credentials is " \
- "not valid: %s" % ic.message
- raise exceptions.InvalidConfiguration(msg)
-
- def is_multi_user(self):
- return self._unique_creds('username')
-
- def is_multi_tenant(self):
- return self._unique_creds('tenant_id')
-
- def get_primary_creds(self):
- if self._creds.get('primary'):
- return self._creds.get('primary')
- primary_credential = cred_provider.get_configured_credentials(
- fill_in=False, credential_type='user',
- identity_version=self.identity_version)
- self._creds['primary'] = cred_provider.TestResources(
- primary_credential)
- return self._creds['primary']
-
- def get_alt_creds(self):
- if self._creds.get('alt'):
- return self._creds.get('alt')
- alt_credential = cred_provider.get_configured_credentials(
- fill_in=False, credential_type='alt_user',
- identity_version=self.identity_version)
- self._creds['alt'] = cred_provider.TestResources(
- alt_credential)
- return self._creds['alt']
-
- def clear_creds(self):
- self._creds = {}
-
- def get_admin_creds(self):
- creds = cred_provider.get_configured_credentials(
- "identity_admin", fill_in=False)
- self._creds['admin'] = cred_provider.TestResources(creds)
- return self._creds['admin']
-
- def get_creds_by_roles(self, roles, force_new=False):
- msg = "Credentials being specified through the config file can not be"\
- " used with tests that specify using credentials by roles. "\
- "Either exclude/skip the tests doing this or use either an "\
- "test_accounts_file or dynamic credentials."
- raise exceptions.InvalidConfiguration(msg)
diff --git a/tempest/manager.py b/tempest/manager.py
index d7c3128..b0541e8 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -31,22 +31,18 @@
and a client object for a test case to use in performing actions.
"""
- def __init__(self, credentials=None):
+ def __init__(self, credentials):
"""
- We allow overriding of the credentials used within the various
- client classes managed by the Manager object. Left as None, the
- standard username/password/tenant_name[/domain_name] is used.
+ Credentials to be used within the various client classes managed by the
+ Manager object must be defined.
- :param credentials: Override of the credentials
+ :param credentials: type Credentials or TestResources
"""
- self.auth_version = CONF.identity.auth_version
- if credentials is None:
- self.credentials = cred_provider.get_configured_credentials('user')
- else:
- self.credentials = credentials
+ self.credentials = credentials
# Check if passed or default credentials are valid
if not self.credentials.is_valid():
raise exceptions.InvalidCredentials()
+ self.auth_version = CONF.identity.auth_version
# Tenant isolation creates TestResources, but
# PreProvisionedCredentialProvider and some tests create Credentials
if isinstance(credentials, cred_provider.TestResources):
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 12509f7..16db18c 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -24,7 +24,7 @@
import testtools
from tempest import clients
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
CONF = config.CONF
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 1350d95..4c77b19 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -16,14 +16,14 @@
from oslo_log import log as logging
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest.common import waiters
LOG = logging.getLogger(__name__)
def cleanup():
- admin_manager = clients.AdminManager()
+ admin_manager = credentials.AdminManager()
body = admin_manager.servers_client.list_servers(all_tenants=True)
LOG.info("Cleanup::remove %s servers" % len(body['servers']))
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 7634d2c..eec52cb 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -26,6 +26,7 @@
from tempest import clients
from tempest.common import cred_client
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -122,7 +123,7 @@
"""
Workload driver. Executes an action function against a nova-cluster.
"""
- admin_manager = clients.AdminManager()
+ admin_manager = credentials.AdminManager()
ssh_user = CONF.stress.target_ssh_user
ssh_key = CONF.stress.target_private_key_path
@@ -145,7 +146,7 @@
if test.get('use_admin', False):
manager = admin_manager
else:
- manager = clients.Manager()
+ manager = credentials.ConfiguredUserManager()
for p_number in moves.xrange(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
username = data_utils.rand_name("stress_user")
diff --git a/tempest/test.py b/tempest/test.py
index b8ba5f4..4be6779 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -32,7 +32,7 @@
from tempest import clients
from tempest.common import cred_client
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest.common import fixed_network
import tempest.common.generator.valid_generator as valid
import tempest.common.validation_resources as vresources
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index a53ed5f..75401db 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -15,7 +15,7 @@
from oslo_config import cfg
from oslotest import mockpatch
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest.tests import base
from tempest.tests import fake_config
diff --git a/tempest/tests/common/test_alt_available.py b/tempest/tests/common/test_alt_available.py
index 6a86f73..db3f5ec 100644
--- a/tempest/tests/common/test_alt_available.py
+++ b/tempest/tests/common/test_alt_available.py
@@ -15,7 +15,7 @@
from oslo_config import cfg
from oslotest import mockpatch
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest.tests import base
from tempest.tests import fake_config
diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_configured_creds.py
similarity index 95%
rename from tempest/tests/common/test_cred_provider.py
rename to tempest/tests/common/test_configured_creds.py
index d404660..96b75fd 100644
--- a/tempest/tests/common/test_cred_provider.py
+++ b/tempest/tests/common/test_configured_creds.py
@@ -18,8 +18,7 @@
from tempest_lib.services.identity.v2 import token_client as v2_client
from tempest_lib.services.identity.v3 import token_client as v3_client
-
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common import tempest_fixtures as fixtures
from tempest import config
from tempest.tests import base
@@ -65,12 +64,12 @@
def _verify_credentials(self, credentials_class, filled=True,
identity_version=None):
- for ctype in cred_provider.CREDENTIAL_TYPES:
+ for ctype in common_creds.CREDENTIAL_TYPES:
if identity_version is None:
- creds = cred_provider.get_configured_credentials(
+ creds = common_creds.get_configured_credentials(
credential_type=ctype, fill_in=filled)
else:
- creds = cred_provider.get_configured_credentials(
+ creds = common_creds.get_configured_credentials(
credential_type=ctype, fill_in=filled,
identity_version=identity_version)
self._check(creds, credentials_class, filled)
diff --git a/tempest/tests/common/test_credentials.py b/tempest/tests/common/test_credentials.py
new file mode 100644
index 0000000..136ac02
--- /dev/null
+++ b/tempest/tests/common/test_credentials.py
@@ -0,0 +1,36 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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 tempest.common import credentials_factory as credentials
+from tempest import config
+from tempest import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class TestLegacyCredentialsProvider(base.TestCase):
+
+ fixed_params = {'identity_version': 'v2'}
+
+ def setUp(self):
+ super(TestLegacyCredentialsProvider, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+
+ def test_get_creds_roles_legacy_invalid(self):
+ test_accounts_class = credentials.LegacyCredentialProvider(
+ **self.fixed_params)
+ self.assertRaises(exceptions.InvalidConfiguration,
+ test_accounts_class.get_creds_by_roles,
+ ['fake_role'])
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index 59a5523..089d9be 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -17,6 +17,7 @@
from oslotest import mockpatch
from tempest_lib.services.identity.v2 import token_client as json_token_client
+from tempest.common import credentials_factory as credentials
from tempest.common import dynamic_creds
from tempest.common import service_client
from tempest import config
@@ -46,6 +47,8 @@
cfg.CONF.set_default('operator_role', 'FakeRole',
group='object-storage')
self._mock_list_ec2_credentials('fake_user_id', 'fake_tenant_id')
+ self.fixed_params.update(
+ admin_creds=self._get_fake_admin_creds())
def test_tempest_client(self):
creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
@@ -54,6 +57,13 @@
self.assertTrue(isinstance(creds.network_admin_client,
json_network_client.NetworkClient))
+ def _get_fake_admin_creds(self):
+ return credentials.get_credentials(
+ fill_in=False,
+ identity_version=self.fixed_params['identity_version'],
+ username='fake_username', password='fake_password',
+ tenant_name='fake_tenant')
+
def _mock_user_create(self, id, name):
user_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index 8a014af..36dd976 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -329,36 +329,3 @@
self.assertIn('id', network)
self.assertEqual('fake-id', network['id'])
self.assertEqual('network-2', network['name'])
-
-
-class TestNotLockingAccount(base.TestCase):
-
- fixed_params = {'name': 'test class',
- 'identity_version': 'v2',
- 'admin_role': 'admin'}
-
- def setUp(self):
- super(TestNotLockingAccount, self).setUp()
- self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.useFixture(lockutils_fixtures.ExternalLockFixture())
- self.test_accounts = [
- {'username': 'test_user1', 'tenant_name': 'test_tenant1',
- 'password': 'p'},
- {'username': 'test_user2', 'tenant_name': 'test_tenant2',
- 'password': 'p'},
- {'username': 'test_user3', 'tenant_name': 'test_tenant3',
- 'password': 'p'},
- ]
- self.useFixture(mockpatch.Patch(
- 'tempest.common.preprov_creds.read_accounts_yaml',
- return_value=self.test_accounts))
- cfg.CONF.set_default('test_accounts_file', '', group='auth')
- self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
-
- def test_get_creds_roles_nonlocking_invalid(self):
- test_accounts_class = preprov_creds.NonLockingCredentialProvider(
- **self.fixed_params)
- self.assertRaises(exceptions.InvalidConfiguration,
- test_accounts_class.get_creds_by_roles,
- ['fake_role'])
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 1ced180..05c47bb 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -27,7 +27,7 @@
from six.moves.urllib import parse as urlparse
from tempest_lib import exceptions as lib_exc
-import tempest.clients
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import file_utils
from tempest import config
from tempest import exceptions
@@ -67,7 +67,7 @@
raise Exception("Unknown (Authentication?) Error")
# NOTE(andreaf) Setting up an extra manager here is redundant,
# and should be removed.
- openstack = tempest.clients.Manager()
+ openstack = credentials.ConfiguredUserManager()
try:
if urlparse.urlparse(CONF.boto.ec2_url).hostname is None:
raise Exception("Failed to get hostname from the ec2_url")