Make use of service clients interface

This change makes use of features provided by stable "ServiceClients"
interface that has been available in Tempest for some time. The
interface enhances tests with a convenient way to access available
service clients.

When a plugin uses "ServiceClients" interface, all stable Tempest
clients and all clients exposed by installed plugins will be
automatically available and pre-configured. Instead of explicitly
specifying parameters, such as "auth_provider", "build_timeout", etc.,
all these parameters will be read from the Tempest configuration and
then installed automatically in the clients.

Plugin adaptation was carried out in accordance with the requirements
described in Tempest documentation[1] and inspired by changes introduced
in other plugins[2][3].

[1] https://docs.openstack.org/tempest/latest/plugin.html#service-clients
[2] https://review.openstack.org/#/c/338486/
[3] https://review.openstack.org/#/c/334596/

Change-Id: I0fbb12fb93f4411f23d95d54d8d5a7904a372333
Signed-off-by: Bartosz Zurkowski <b.zurkowski@samsung.com>
This commit is contained in:
Bartosz Zurkowski 2018-08-01 14:37:19 +02:00
parent ea41b2f724
commit 36ee568e0a
4 changed files with 94 additions and 31 deletions

View File

@ -0,0 +1,34 @@
# Copyright 2018 Samsung Electronics
# 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 import config
from tempest.lib.services import clients
CONF = config.CONF
class Manager(clients.ServiceClients):
"""Service clients proxy.
Enhances tests with a convenient way to access available service clients
configured for a specified set of credentials.
"""
def __init__(self, credentials, service=None):
if CONF.identity.auth_version == 'v2':
identity_uri = CONF.identity.uri
else:
identity_uri = CONF.identity.uri_v3
super(Manager, self).__init__(credentials, identity_uri)

View File

@ -26,10 +26,15 @@ DatabaseGroup = [
cfg.StrOpt('catalog_type',
default='database',
help="Catalog type of the Database service."),
cfg.StrOpt('endpoint_type',
default='publicURL',
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the Database service."),
cfg.StrOpt('db_flavor_ref',
default="1",
help="Valid primary flavor to use in database tests."),
help="Valid primary flavor to use in Database tests."),
cfg.StrOpt('db_current_version',
default="v1.0",
help="Current database version to use in database tests."),
help="Current database version to use in Database tests."),
]

View File

@ -15,6 +15,7 @@
import os
from tempest import config
from tempest.test_discover import plugins
from trove_tempest_plugin import config as trove_config
@ -38,3 +39,18 @@ class TroveTempestPlugin(plugins.TempestPlugin):
def get_opt_lists(self):
return [('database', trove_config.DatabaseGroup),
('service_available', [trove_config.service_option])]
def get_service_clients(self):
service_config = config.service_client_config('database')
service_params = {
'name': 'database',
'service_version': 'database',
'module_path': 'trove_tempest_plugin.services.database',
'client_names': [
'FlavorsClient',
'LimitsClient',
'VersionsClient'
]
}
service_params.update(service_config)
return [service_params]

View File

@ -16,10 +16,7 @@
from tempest import config
import tempest.test
from trove_tempest_plugin.services.database import FlavorsClient
from trove_tempest_plugin.services.database import LimitsClient
from trove_tempest_plugin.services.database import VersionsClient
from trove_tempest_plugin import clients
CONF = config.CONF
@ -28,6 +25,7 @@ class BaseDatabaseTest(tempest.test.BaseTestCase):
"""Base test case class for all Database API tests."""
credentials = ['primary']
client_manager = clients.Manager
@classmethod
def skip_checks(cls):
@ -38,32 +36,42 @@ class BaseDatabaseTest(tempest.test.BaseTestCase):
@classmethod
def setup_clients(cls):
super(BaseDatabaseTest, cls).setup_clients()
default_params = config.service_client_config()
"""Setups service clients.
# NOTE: Tempest uses timeout values of compute API if project specific
# timeout values don't exist.
default_params_with_timeout_values = {
'build_interval': CONF.compute.build_interval,
'build_timeout': CONF.compute.build_timeout
}
default_params_with_timeout_values.update(default_params)
cls.database_flavors_client = FlavorsClient(
cls.os_primary.auth_provider,
CONF.database.catalog_type,
CONF.identity.region,
**default_params_with_timeout_values)
cls.os_flavors_client = cls.os_primary.flavors_client
cls.database_limits_client = LimitsClient(
cls.os_primary.auth_provider,
CONF.database.catalog_type,
CONF.identity.region,
**default_params_with_timeout_values)
cls.database_versions_client = VersionsClient(
cls.os_primary.auth_provider,
CONF.database.catalog_type,
CONF.identity.region,
**default_params_with_timeout_values)
Tempest provides a convenient fabrication interface, which can be used
to produce instances of clients configured with the required parameters
and a selected set of credentials. Thanks to this interface, the
complexity of client initialization is hidden from the developer. All
parameters such as "catalog_type", "auth_provider", "build_timeout"
etc. are read from Tempest configuration and then automatically
installed in the clients.
The fabrication interface is enabled through the client manager, which
is hooked to the class by the "client_manager" property.
To initialize a new client, one need to specify the set of credentials
(primary, admin) to be used and the category of client (eg compute,
image, database, etc.). Together, they constitute a proxy for the
fabricators of specific client classes from a given category.
For example, initializing a new flavors client from the database
category with primary privileges boils down to the following call:
flavors_client = cls.os_primary.database.FlavorsClient()
In order to initialize a new networks client from the compute category
with administrator privilages:
networks_client = cls.os_admin.compute.NetworksClient()
Note, that selected set of credentials must be declared in the
"credentials" property of this class.
"""
super(BaseDatabaseTest, cls).setup_clients()
cls.database_flavors_client = cls.os_primary.database.FlavorsClient()
cls.os_flavors_client = cls.os_primary.compute.FlavorsClient()
cls.database_limits_client = cls.os_primary.database.LimitsClient()
cls.database_versions_client = cls.os_primary.database.VersionsClient()
@classmethod
def resource_setup(cls):