181 lines
5.6 KiB
ReStructuredText
181 lines
5.6 KiB
ReStructuredText
::
|
|
|
|
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
|
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
|
|
|
..
|
|
|
|
===================================================
|
|
Tempest support for multiple keystone API versions
|
|
===================================================
|
|
|
|
https://blueprints.launchpad.net/tempest/+spec/multi-keystone-api-version-tests
|
|
|
|
Decouple tempest from keystone version specifics and run tests with keystone v3
|
|
|
|
Problem description
|
|
===================
|
|
|
|
Tempest code is tightly coupled with keystone V2 specific implementations.
|
|
Common classes (such as rest client and tenant isolation), test base classes
|
|
and test themselves all assume the identity service is provided by a keystone
|
|
v2 endpoint.
|
|
Tempest shall be able to run with a keystone V3 identity service, and newer versions
|
|
as they become available.
|
|
|
|
Proposed change
|
|
===============
|
|
|
|
A new configuration flag is introduced to specify the auth version to be used.
|
|
The flag is defined as follows:
|
|
|
|
::
|
|
|
|
cfg.StrOpt('auth_version',
|
|
default='v2',
|
|
help="Identity API version to be used for authentication "
|
|
"for API tests."),
|
|
|
|
..
|
|
|
|
And it's used to select the matching version of Credentials and Auth Provider:
|
|
|
|
::
|
|
|
|
if CONF.identity.auth_version == 'v2':
|
|
credential_class = KeystoneV2Credentials
|
|
auth_provider_class = KeystoneV2AuthProvider
|
|
elif CONF.identity.auth_version == 'v3':
|
|
credential_class = KeystoneV3Credentials
|
|
auth_provider_class = KeystoneV3AuthProvider
|
|
else:
|
|
raise exceptions.InvalidConfiguration('Unsupported auth version')
|
|
|
|
..
|
|
|
|
A number of refactors are required to achieve this and make sure we don't need
|
|
to change test code again when moving to different keystone API versions.
|
|
|
|
Authentication are factored out in an authentication provider. Credentials are handled
|
|
via a dedicated class, provided to tests by a credential manager.
|
|
Clients managers receive credentials and are the sole responsible for instantiating
|
|
clients and provide them to tests. At the moment client managers instantiate all
|
|
available clients when created. This is unnecessary, and it leads to issues when not
|
|
all openstack services are available for test. Client managers are thus changed to
|
|
lazy instantiation of clients.
|
|
|
|
Manager __init__ method signature before and after refactor:
|
|
|
|
::
|
|
|
|
Before:
|
|
|
|
def __init__(self, username=None, password=None, tenant_name=None,
|
|
interface='json', service=None):
|
|
|
|
After:
|
|
|
|
def __init__(self, credentials=None, interface='json', service=None):
|
|
|
|
..
|
|
|
|
Authentication in rest client before and after refactor:
|
|
|
|
::
|
|
|
|
Before:
|
|
|
|
def request(self, method, url,
|
|
headers=None, body=None):
|
|
if (self.token is None) or (self.base_url is None):
|
|
self._set_auth()
|
|
|
|
if headers is None:
|
|
headers = {}
|
|
headers['X-Auth-Token'] = self.token
|
|
|
|
resp, resp_body = self._request(method, url,
|
|
headers=headers, body=body)
|
|
|
|
After:
|
|
|
|
def _request(self, method, url, headers=None, body=None):
|
|
# Authenticate the request with the auth provider
|
|
req_url, req_headers, req_body = self.auth_provider.auth_request(
|
|
method, url, headers, body, self.filters)
|
|
|
|
..
|
|
|
|
Access to credentials IDs from the tests, before and after refactor:
|
|
|
|
::
|
|
|
|
Before:
|
|
|
|
# Retrieve the ResellerAdmin tenant id
|
|
_, users = cls.os_admin.identity_client.get_users()
|
|
reseller_user_id = next(usr['id'] for usr in users if usr['name']
|
|
== cls.data.test_user)
|
|
|
|
# Retrieve the ResellerAdmin tenant id
|
|
_, tenants = cls.os_admin.identity_client.list_tenants()
|
|
reseller_tenant_id = next(tnt['id'] for tnt in tenants if tnt['name']
|
|
== cls.data.test_tenant)
|
|
|
|
After:
|
|
|
|
# Retrieve the ResellerAdmin user id
|
|
reseller_user_id = cls.data.test_credentials.user_id
|
|
|
|
# Retrieve the ResellerAdmin tenant id
|
|
reseller_tenant_id = cls.data.test_credentials.tenant_id
|
|
|
|
..
|
|
|
|
Areas affected by refactor:
|
|
|
|
- Rest client (tempest/common/rest_client.py): move auth code to an external auth provider
|
|
- Client managers (tempest/manager.py, tempest/clients.py, tempest/scenario/manager.py): work with a Credentials class. Lazy load of clients.
|
|
- Tests base classes (tempest/api/\*\*/base.py): adapt where needed to modified rest client, client manager and credentials
|
|
- Tests: adapt where needed to modified rest client, client manager and credentials
|
|
|
|
Alternatives
|
|
------------
|
|
|
|
We could change all the code in place - without refactoring - adding checks for the
|
|
configured auth version. This would still require touching a considerable chunk
|
|
of tempest code, without the benefit for future keystone versions.
|
|
|
|
Implementation
|
|
==============
|
|
|
|
Assignee(s)
|
|
-----------
|
|
Primary assignee:
|
|
Andrea Frittoli <andrea.frittoli@hp.com>
|
|
|
|
Milestones
|
|
----------
|
|
Target Milestone for completion:
|
|
Juno-1
|
|
|
|
Work Items
|
|
----------
|
|
- Move auth from rest_client to auth provider
|
|
- Provide unit tests for the new auth and credential classes
|
|
- Refactor Manager, Credentials class everywhere
|
|
- Client Manager provide client lazy load
|
|
- Tenant isolation support for V3
|
|
- Provide multi auth-version for API tests
|
|
- Provide multi auth-version for scenario tests
|
|
- Provide multi auth-version for CLI tests
|
|
- Provide multi auth-version for 3rd part tests
|
|
- Provide multi auth-version for stress framework
|
|
- Add experimental job with auth_version = v3
|
|
|
|
Dependencies
|
|
============
|
|
- Python bindings and CLI are not yet all V3 ready. Some of the work in this blueprint
|
|
will have to be postponed until this is fixed
|