Merge "Prepare the Manager class for tempest.lib"
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index 18a50d0..a540da7 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -9,13 +9,11 @@
# 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.api.identity import base
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
from tempest.lib import auth
-from tempest import manager
from tempest import test
CONF = config.CONF
@@ -78,7 +76,7 @@
creds = auth.KeystoneV3Credentials(username=user_name,
password=user_name,
user_domain_name=dom_name)
- auth_provider = manager.get_auth_provider(creds)
+ auth_provider = clients.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
admin_client = clients.Manager(credentials=creds)
diff --git a/tempest/clients.py b/tempest/clients.py
index 3a1a3c0..ef03e80 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -20,10 +20,11 @@
from tempest.common import negative_rest_client
from tempest import config
from tempest import exceptions
+from tempest.lib import auth
from tempest.lib.services import compute
from tempest.lib.services import image
from tempest.lib.services import network
-from tempest import manager
+from tempest import service_clients
from tempest.services import baremetal
from tempest.services import data_processing
from tempest.services import identity
@@ -35,7 +36,7 @@
LOG = logging.getLogger(__name__)
-class Manager(manager.Manager):
+class Manager(service_clients.ServiceClients):
"""Top level manager for OpenStack tempest clients"""
default_params = {
@@ -61,7 +62,10 @@
:param service: Service name
:param scope: default scope for tokens produced by the auth provider
"""
- super(Manager, self).__init__(credentials=credentials, scope=scope)
+ _, identity_uri = get_auth_provider_class(credentials)
+ super(Manager, self).__init__(
+ credentials=credentials, identity_uri=identity_uri, scope=scope,
+ region=CONF.identity.region, **self.default_params)
self._set_compute_clients()
self._set_identity_clients()
self._set_volume_clients()
@@ -390,3 +394,30 @@
self.auth_provider, **params)
self.object_client = object_storage.ObjectClient(self.auth_provider,
**params)
+
+
+def get_auth_provider_class(credentials):
+ if isinstance(credentials, auth.KeystoneV3Credentials):
+ return auth.KeystoneV3AuthProvider, CONF.identity.uri_v3
+ else:
+ return auth.KeystoneV2AuthProvider, CONF.identity.uri
+
+
+def get_auth_provider(credentials, pre_auth=False, scope='project'):
+ 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
+ }
+ if credentials is None:
+ raise exceptions.InvalidCredentials(
+ 'Credentials must be specified')
+ auth_provider_class, auth_url = get_auth_provider_class(
+ credentials)
+ _auth_provider = auth_provider_class(credentials, auth_url,
+ scope=scope,
+ **default_params)
+ if pre_auth:
+ _auth_provider.set_auth()
+ return _auth_provider
diff --git a/tempest/manager.py b/tempest/manager.py
index f2659a8..3d495b6 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -13,61 +13,50 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_log import log as logging
+
+from tempest import clients
from tempest import config
-from tempest.lib import auth
-from tempest.lib import exceptions
+from tempest import service_clients
CONF = config.CONF
+LOG = logging.getLogger(__name__)
-class Manager(object):
- """Base manager class
+class Manager(service_clients.ServiceClients):
+ """Service client manager class for backward compatibility
- Manager objects are responsible for providing a configuration object
- and a client object for a test case to use in performing actions.
+ The former manager.Manager is not a stable interface in Tempest,
+ nonetheless it is consumed by a number of plugins already. This class
+ exists to provide some grace time for the move to tempest.lib.
"""
def __init__(self, credentials, scope='project'):
- """Initialization of base manager class
-
- Credentials to be used within the various client classes managed by the
- Manager object must be defined.
-
- :param credentials: An instance of `auth.Credentials`
- :param scope: default scope for tokens produced by the auth provider
- """
- 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
- # Creates an auth provider for the credentials
- self.auth_provider = get_auth_provider(
- self.credentials, pre_auth=True, scope=scope)
-
-
-def get_auth_provider_class(credentials):
- if isinstance(credentials, auth.KeystoneV3Credentials):
- return auth.KeystoneV3AuthProvider, CONF.identity.uri_v3
- else:
- return auth.KeystoneV2AuthProvider, CONF.identity.uri
+ msg = ("tempest.manager.Manager is not a stable interface and as such "
+ "it should not imported directly. It will be removed as "
+ "soon as the client manager becomes available in tempest.lib.")
+ LOG.warning(msg)
+ dscv = CONF.identity.disable_ssl_certificate_validation
+ _, uri = clients.get_auth_provider_class(credentials)
+ super(Manager, self).__init__(
+ credentials=credentials, scope=scope,
+ identity_uri=uri,
+ disable_ssl_certificate_validation=dscv,
+ ca_certs=CONF.identity.ca_certificates_file,
+ trace_requests=CONF.debug.trace_requests)
def get_auth_provider(credentials, pre_auth=False, scope='project'):
- 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
- }
- if credentials is None:
- raise exceptions.InvalidCredentials(
- 'Credentials must be specified')
- auth_provider_class, auth_url = get_auth_provider_class(
- credentials)
- _auth_provider = auth_provider_class(credentials, auth_url,
- scope=scope,
- **default_params)
- if pre_auth:
- _auth_provider.set_auth()
- return _auth_provider
+ """Shim to get_auth_provider in clients.py
+
+ get_auth_provider used to be hosted in this module, but it has been
+ moved to clients.py now as a more permanent location.
+ This module will be removed eventually, and this shim is only
+ maintained for the benefit of plugins already consuming this interface.
+ """
+ msg = ("tempest.manager.get_auth_provider is not a stable interface and "
+ "as such it should not imported directly. It will be removed as "
+ "the client manager becomes available in tempest.lib.")
+ LOG.warning(msg)
+ return clients.get_auth_provider(credentials=credentials,
+ pre_auth=pre_auth, scope=scope)
diff --git a/tempest/service_clients.py b/tempest/service_clients.py
new file mode 100644
index 0000000..3208c8d
--- /dev/null
+++ b/tempest/service_clients.py
@@ -0,0 +1,90 @@
+# Copyright 2012 OpenStack Foundation
+# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
+# All Rights Reserved.
+#
+# 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.lib import auth
+from tempest.lib import exceptions
+
+
+class ServiceClients(object):
+ """Service client provider class
+
+ The ServiceClients object provides a useful means for tests to access
+ service clients configured for a specified set of credentials.
+ It hides some of the complexity from the authorization and configuration
+ layers.
+
+ Examples:
+
+ >>> from tempest import service_clients
+ >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
+ >>> johndoe_clients = service_clients.ServiceClients(johndoe)
+ >>> johndoe_servers = johndoe_clients.servers_client.list_servers()
+
+ """
+ # NOTE(andreaf) This class does not depend on tempest configuration
+ # and its meant for direct consumption by external clients such as tempest
+ # plugins. Tempest provides a wrapper class, `clients.Manager`, that
+ # initialises this class using values from tempest CONF object. The wrapper
+ # class should only be used by tests hosted in Tempest.
+
+ def __init__(self, credentials, identity_uri, region=None,
+ scope='project', disable_ssl_certificate_validation=True,
+ ca_certs=None, trace_requests=''):
+ """Service Clients provider
+
+ Instantiate a `ServiceClients` object, from a set of credentials and an
+ identity URI. The identity version is inferred from the credentials
+ object. Optionally auth scope can be provided.
+ Parameters dscv, ca_certs and trace_requests all apply to the auth
+ provider as well as any service clients provided by this manager.
+
+ :param credentials: An instance of `auth.Credentials`
+ :param identity_uri: URI of the identity API. This should be a
+ mandatory parameter, and it will so soon.
+ :param region: Default value of region for service clients.
+ :param scope: default scope for tokens produced by the auth provider
+ :param disable_ssl_certificate_validation Applies to auth and to all
+ service clients.
+ :param ca_certs Applies to auth and to all service clients.
+ :param trace_requests Applies to auth and to all service clients.
+ """
+ self.credentials = credentials
+ self.identity_uri = identity_uri
+ if not identity_uri:
+ raise exceptions.InvalidCredentials(
+ 'Manager requires a non-empty identity_uri.')
+ self.region = region
+ # Check if passed or default credentials are valid
+ if not self.credentials.is_valid():
+ raise exceptions.InvalidCredentials()
+ # Get the identity classes matching the provided credentials
+ # TODO(andreaf) Define a new interface in Credentials to get
+ # the API version from an instance
+ identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in
+ auth.IDENTITY_VERSION.keys() if
+ isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
+ # Zero matches or more than one are both not valid.
+ if len(identity) != 1:
+ raise exceptions.InvalidCredentials()
+ self.auth_version, auth_provider_class = identity[0]
+ self.dscv = disable_ssl_certificate_validation
+ self.ca_certs = ca_certs
+ self.trace_requests = trace_requests
+ # Creates an auth provider for the credentials
+ self.auth_provider = auth_provider_class(
+ self.credentials, self.identity_uri, scope=scope,
+ disable_ssl_certificate_validation=self.dscv,
+ ca_certs=self.ca_certs, trace_requests=self.trace_requests)
diff --git a/tempest/tests/test_service_clients.py b/tempest/tests/test_service_clients.py
new file mode 100644
index 0000000..f67781c
--- /dev/null
+++ b/tempest/tests/test_service_clients.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2016 Hewlett-Packard Enterprise 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 testtools
+
+from tempest.lib import auth
+from tempest.lib import exceptions
+from tempest import service_clients
+from tempest.tests import base
+from tempest.tests.lib import fake_credentials
+
+
+class TestServiceClients(base.TestCase):
+
+ def test__init__creds_v2_uri(self):
+ # Verify that no API request is made, since no mock
+ # is required to run the test successfully
+ creds = fake_credentials.FakeKeystoneV2Credentials()
+ uri = 'fake_uri'
+ _manager = service_clients.ServiceClients(creds, identity_uri=uri)
+ self.assertIsInstance(_manager.auth_provider,
+ auth.KeystoneV2AuthProvider)
+
+ def test__init__creds_v3_uri(self):
+ # Verify that no API request is made, since no mock
+ # is required to run the test successfully
+ creds = fake_credentials.FakeKeystoneV3Credentials()
+ uri = 'fake_uri'
+ _manager = service_clients.ServiceClients(creds, identity_uri=uri)
+ self.assertIsInstance(_manager.auth_provider,
+ auth.KeystoneV3AuthProvider)
+
+ def test__init__base_creds_uri(self):
+ creds = fake_credentials.FakeCredentials()
+ uri = 'fake_uri'
+ with testtools.ExpectedException(exceptions.InvalidCredentials):
+ service_clients.ServiceClients(creds, identity_uri=uri)
+
+ def test__init__invalid_creds_uri(self):
+ creds = fake_credentials.FakeKeystoneV2Credentials()
+ delattr(creds, 'username')
+ uri = 'fake_uri'
+ with testtools.ExpectedException(exceptions.InvalidCredentials):
+ service_clients.ServiceClients(creds, identity_uri=uri)
+
+ def test__init__creds_uri_none(self):
+ creds = fake_credentials.FakeKeystoneV2Credentials()
+ msg = "Invalid Credentials\nDetails: Manager requires a non-empty"
+ with testtools.ExpectedException(exceptions.InvalidCredentials,
+ value_re=msg):
+ service_clients.ServiceClients(creds, None)