Remove creds providers dependency from clients

We want to make cred providers a stable interface and move it to
lib but to do so it must not depend on modules outside of lib or
not generally stable otherwise. The last dependency left is
tempest.clients, which can be replaced by its tempest.lib
counterpart, tempest.lib.services.clients.

While clients does not depend on configuration directly, it uses
the client registry singleton. When this class is used as part of
tempest, it's populated with configuration values the first time
the CONF object is instantiated, so that Tempest configuration
values are still honoured.

When DynamicCredentialProvider is used by a consumer that does
not have a Tempest config file, all the settings defined in
__init__ will be honoured. To control more settings, the
client registry must be populated before the Credentials
Provider is used with the appropriate settings.

Change-Id: I7b262607a1fa9f67e6b1d3ec2c4cf1ccffb952a6
This commit is contained in:
Andrea Frittoli 2017-07-18 11:34:13 +01:00
parent 12972ae580
commit dcd9100d03
6 changed files with 72 additions and 30 deletions

View File

@ -40,8 +40,13 @@ to avoid circular dependencies."""
# Subset of the parameters of credential providers that depend on configuration
def _get_common_provider_params(identity_version):
if identity_version == 'v3':
identity_uri = CONF.identity.uri_v3
elif identity_version == 'v2':
identity_uri = CONF.identity.uri
return {
'identity_version': identity_version,
'identity_uri': identity_uri,
'credentials_domain': CONF.auth.default_credentials_domain_name,
'admin_role': CONF.identity.admin_role
}
@ -63,6 +68,10 @@ def get_dynamic_provider_params(identity_version, admin_creds=None):
_common_params = _get_common_provider_params(identity_version)
admin_creds = admin_creds or get_configured_admin_credentials(
fill_in=True, identity_version=identity_version)
if identity_version == 'v3':
endpoint_type = CONF.identity.v3_endpoint_type
elif identity_version == 'v2':
endpoint_type = CONF.identity.v2_admin_endpoint_type
return dict(_common_params, **dict([
('admin_creds', admin_creds),
('identity_admin_domain_scope', CONF.identity.admin_domain_scope),
@ -74,7 +83,8 @@ def get_dynamic_provider_params(identity_version, admin_creds=None):
('public_network_id', CONF.network.public_network_id),
('create_networks', (CONF.auth.create_isolated_networks and not
CONF.network.shared_physical_network)),
('resource_prefix', CONF.resources_prefix)
('resource_prefix', CONF.resources_prefix),
('identity_admin_endpoint_type', endpoint_type)
]))

View File

@ -18,11 +18,11 @@ import netaddr
from oslo_log import log as logging
import six
from tempest import clients
from tempest.lib.common import cred_client
from tempest.lib.common import cred_provider
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest.lib.services import clients
LOG = logging.getLogger(__name__)
@ -35,7 +35,8 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
identity_admin_role='admin', extra_roles=None,
neutron_available=False, create_networks=True,
project_network_cidr=None, project_network_mask_bits=None,
public_network_id=None, resource_prefix=None):
public_network_id=None, resource_prefix=None,
identity_admin_endpoint_type='public', identity_uri=None):
"""Creates credentials dynamically for tests
A credential provider that, based on an initial set of
@ -69,10 +70,14 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
:param project_network_mask_bits: The network mask bits to use for
created project networks
:param public_network_id: The id for the public network to use
:param identity_admin_endpoint_type: The endpoint type for identity
admin clients. Defaults to public.
:param identity_uri: Identity URI of the target cloud
"""
super(DynamicCredentialProvider, self).__init__(
identity_version=identity_version, admin_role=admin_role,
name=name, credentials_domain=credentials_domain,
identity_version=identity_version, identity_uri=identity_uri,
admin_role=admin_role, name=name,
credentials_domain=credentials_domain,
network_resources=network_resources)
self.network_resources = network_resources
self._creds = {}
@ -86,6 +91,7 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.default_admin_creds = admin_creds
self.identity_admin_domain_scope = identity_admin_domain_scope
self.identity_admin_role = identity_admin_role or 'admin'
self.identity_admin_endpoint_type = identity_admin_endpoint_type
self.extra_roles = extra_roles or []
(self.identity_admin_client,
self.tenants_admin_client,
@ -96,7 +102,8 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.routers_admin_client,
self.subnets_admin_client,
self.ports_admin_client,
self.security_groups_admin_client) = self._get_admin_clients()
self.security_groups_admin_client) = self._get_admin_clients(
identity_admin_endpoint_type)
# Domain where isolated credentials are provisioned (v3 only).
# Use that of the admin account is None is configured.
self.creds_domain_name = None
@ -112,32 +119,43 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.domains_admin_client,
self.creds_domain_name)
def _get_admin_clients(self):
def _get_admin_clients(self, endpoint_type):
"""Returns a tuple with instances of the following admin clients
(in this order):
identity
network
"""
os = clients.Manager(self.default_admin_creds)
os = clients.ServiceClients(self.default_admin_creds,
self.identity_uri)
params = {'endpoint_type': endpoint_type}
if self.identity_version == 'v2':
return (os.identity_client, os.tenants_client, os.users_client,
os.roles_client, None,
os.networks_client, os.routers_client, os.subnets_client,
os.ports_client, os.security_groups_client)
return (os.identity_v2.IdentityClient(**params),
os.identity_v2.TenantsClient(**params),
os.identity_v2.UsersClient(**params),
os.identity_v2.RolesClient(**params), None,
os.network.NetworksClient(),
os.network.RoutersClient(),
os.network.SubnetsClient(),
os.network.PortsClient(),
os.network.SecurityGroupsClient())
else:
# We use a dedicated client manager for identity client in case we
# need a different token scope for them.
scope = 'domain' if self.identity_admin_domain_scope else 'project'
identity_os = clients.Manager(self.default_admin_creds,
scope=scope)
return (identity_os.identity_v3_client,
identity_os.projects_client,
identity_os.users_v3_client, identity_os.roles_v3_client,
identity_os.domains_client,
os.networks_client, os.routers_client,
os.subnets_client, os.ports_client,
os.security_groups_client)
identity_os = clients.ServiceClients(self.default_admin_creds,
self.identity_uri,
scope=scope)
return (identity_os.identity_v3.IdentityClient(**params),
identity_os.identity_v3.ProjectsClient(**params),
identity_os.identity_v3.UsersClient(**params),
identity_os.identity_v3.RolesClient(**params),
identity_os.identity_v3.DomainsClient(**params),
os.network.NetworksClient(),
os.network.RoutersClient(),
os.network.SubnetsClient(),
os.network.PortsClient(),
os.network.SecurityGroupsClient())
def _create_creds(self, admin=False, roles=None):
"""Create credentials with random name.

View File

@ -20,12 +20,12 @@ from oslo_log import log as logging
import six
import yaml
from tempest import clients
from tempest.common import fixed_network
from tempest import exceptions
from tempest.lib import auth
from tempest.lib.common import cred_provider
from tempest.lib import exceptions as lib_exc
from tempest.lib.services import clients
LOG = logging.getLogger(__name__)
@ -51,7 +51,7 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
def __init__(self, identity_version, test_accounts_file,
accounts_lock_dir, name=None, credentials_domain=None,
admin_role=None, object_storage_operator_role=None,
object_storage_reseller_admin_role=None):
object_storage_reseller_admin_role=None, identity_uri=None):
"""Credentials provider using pre-provisioned accounts
This credentials provider loads the details of pre-provisioned
@ -79,10 +79,12 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
(if no domain is configured)
:param object_storage_operator_role: name of the role
:param object_storage_reseller_admin_role: name of the role
:param identity_uri: Identity URI of the target cloud
"""
super(PreProvisionedCredentialProvider, self).__init__(
identity_version=identity_version, name=name,
admin_role=admin_role, credentials_domain=credentials_domain)
admin_role=admin_role, credentials_domain=credentials_domain,
identity_uri=identity_uri)
self.test_accounts_file = test_accounts_file
if test_accounts_file:
accounts = read_accounts_yaml(self.test_accounts_file)
@ -341,8 +343,9 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
auth_url=None, fill_in=False,
identity_version=self.identity_version, **creds_dict)
net_creds = cred_provider.TestResources(credential)
net_clients = clients.Manager(credentials=credential)
compute_network_client = net_clients.compute_networks_client
net_clients = clients.ServiceClients(credentials=credential,
identity_uri=self.identity_uri)
compute_network_client = net_clients.compute.NetworksClient()
net_name = self.hash_dict['networks'].get(hash, None)
try:
network = fixed_network.get_network_from_name(

View File

@ -22,8 +22,9 @@ from tempest.lib import exceptions
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
def __init__(self, identity_version, name=None, network_resources=None,
credentials_domain=None, admin_role=None):
def __init__(self, identity_version, name=None,
network_resources=None, credentials_domain=None,
admin_role=None, identity_uri=None):
"""A CredentialProvider supplies credentials to test classes.
:param identity_version: Identity version of the credentials provided
@ -33,8 +34,11 @@ class CredentialProvider(object):
credentials
:param credentials_domain: Domain credentials belong to
:param admin_role: Name of the role of the admin account
:param identity_uri: Identity URI of the target cloud. This *must* be
specified for anything to work.
"""
self.identity_version = identity_version
self.identity_uri = identity_uri
self.name = name or "test_creds"
self.network_resources = network_resources
self.credentials_domain = credentials_domain or 'Default'

View File

@ -46,7 +46,8 @@ class TestDynamicCredentialProvider(base.TestCase):
fixed_params = {'name': 'test class',
'identity_version': 'v2',
'admin_role': 'admin'}
'admin_role': 'admin',
'identity_uri': 'fake_uri'}
token_client = v2_token_client
iden_client = v2_iden_client
@ -619,7 +620,8 @@ class TestDynamicCredentialProviderV3(TestDynamicCredentialProvider):
fixed_params = {'name': 'test class',
'identity_version': 'v3',
'admin_role': 'admin'}
'admin_role': 'admin',
'identity_uri': 'fake_uri'}
token_client = v3_token_client
iden_client = v3_iden_client

View File

@ -38,6 +38,7 @@ class TestPreProvisionedCredentials(base.TestCase):
fixed_params = {'name': 'test class',
'identity_version': 'v2',
'identity_uri': 'fake_uri',
'test_accounts_file': 'fake_accounts_file',
'accounts_lock_dir': 'fake_locks_dir',
'admin_role': 'admin',
@ -91,6 +92,9 @@ class TestPreProvisionedCredentials(base.TestCase):
return_value=self.test_accounts))
self.useFixture(fixtures.MockPatch(
'os.path.isfile', return_value=True))
# NOTE(andreaf) Ensure config is loaded so service clients are
# registered in the registry before tests
config.service_client_config()
def tearDown(self):
super(TestPreProvisionedCredentials, self).tearDown()
@ -436,6 +440,7 @@ class TestPreProvisionedCredentialsV3(TestPreProvisionedCredentials):
fixed_params = {'name': 'test class',
'identity_version': 'v3',
'identity_uri': 'fake_uri',
'test_accounts_file': 'fake_accounts_file',
'accounts_lock_dir': 'fake_locks_dir_v3',
'admin_role': 'admin',