Merge "Add ability to select keystone API version"
This commit is contained in:
commit
08f9418513
@ -16,6 +16,7 @@
|
||||
import abc
|
||||
|
||||
from oslo_config import cfg
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from rally.cli import envutils
|
||||
from rally.common.i18n import _
|
||||
@ -94,9 +95,12 @@ class OSClient(plugin.Plugin):
|
||||
# version is a string object.
|
||||
# For those clients which doesn't accept string value(for example
|
||||
# zaqarclient), this method should be overridden.
|
||||
return str(version
|
||||
version = (version
|
||||
or self.api_info.get(self.get_name(), {}).get("version")
|
||||
or self._meta_get("default_version"))
|
||||
if version is not None:
|
||||
version = str(version)
|
||||
return version
|
||||
|
||||
@classmethod
|
||||
def get_supported_versions(cls):
|
||||
@ -208,13 +212,14 @@ class OSClient(plugin.Plugin):
|
||||
return super(OSClient, cls).get(name, namespace)
|
||||
|
||||
|
||||
@configure("keystone")
|
||||
@configure("keystone", supported_versions=("2", "3"))
|
||||
class Keystone(OSClient):
|
||||
|
||||
def keystone(self, *args, **kwargs):
|
||||
raise exceptions.RallyException(_("Method 'keystone' is restricted "
|
||||
"for keystoneclient. :)"))
|
||||
|
||||
def _create_keystone_client(self, args):
|
||||
def _create_keystone_client(self, args, version=None):
|
||||
from keystoneclient.auth import identity
|
||||
from keystoneclient import client
|
||||
auth_arg_list = [
|
||||
@ -223,7 +228,7 @@ class Keystone(OSClient):
|
||||
]
|
||||
# NOTE(bigjools): If forcing a v2.0 URL then you cannot specify
|
||||
# domain-related info, or the service discovery will fail.
|
||||
if "v2.0" not in args["auth_url"]:
|
||||
if "v2.0" not in args["auth_url"] and version != "2":
|
||||
auth_arg_list.extend(
|
||||
["user_domain_name", "domain_name", "project_domain_name"])
|
||||
auth_args = {key: args.get(key) for key in auth_arg_list}
|
||||
@ -240,12 +245,36 @@ class Keystone(OSClient):
|
||||
# list which is why we need to ensure service_catalog is still
|
||||
# present.
|
||||
auth_ref = auth.get_access(session)
|
||||
ks = client.Client(**args)
|
||||
ks = client.Client(version=version, **args)
|
||||
ks.auth_ref = auth_ref
|
||||
return ks
|
||||
|
||||
def create_client(self):
|
||||
"""Return keystone client."""
|
||||
def _remove_url_version(self):
|
||||
"""Remove any version from the auth_url.
|
||||
|
||||
The keystone Client code requires that auth_url be the root url
|
||||
if a version override is used.
|
||||
"""
|
||||
url = parse.urlparse(self.credential.auth_url)
|
||||
# NOTE(bigjools): This assumes that non-versioned URLs have no
|
||||
# path component at all.
|
||||
parts = (url.scheme, url.netloc, "/", url.params, url.query,
|
||||
url.fragment)
|
||||
return parse.urlunparse(parts)
|
||||
|
||||
def create_client(self, version=None):
|
||||
"""Return a keystone client.
|
||||
|
||||
:param version: Keystone API version, can be one of:
|
||||
("2", "3")
|
||||
|
||||
If this object was constructed with a version in the api_info
|
||||
then that will be used unless the version parameter is passed.
|
||||
"""
|
||||
# Use the version in the api_info if provided, otherwise fall
|
||||
# back to the passed version (which may be None, in which case
|
||||
# keystoneclient chooses).
|
||||
version = self.choose_version(version)
|
||||
new_kw = {
|
||||
"timeout": CONF.openstack_client_http_timeout,
|
||||
"insecure": self.credential.insecure,
|
||||
@ -253,7 +282,9 @@ class Keystone(OSClient):
|
||||
}
|
||||
kw = self.credential.to_dict()
|
||||
kw.update(new_kw)
|
||||
return self._create_keystone_client(kw)
|
||||
if version is not None:
|
||||
kw["auth_url"] = self._remove_url_version()
|
||||
return self._create_keystone_client(kw, version=version)
|
||||
|
||||
|
||||
@configure("nova", default_version="2", default_service_type="compute")
|
||||
|
@ -18,6 +18,7 @@ from keystoneclient.auth import token_endpoint
|
||||
from keystoneclient import exceptions as keystone_exceptions
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from testtools import matchers
|
||||
|
||||
from rally.common import objects
|
||||
from rally import consts
|
||||
@ -125,7 +126,8 @@ class TestCreateKeystoneClient(test.TestCase):
|
||||
self.ksc_session.Session.assert_called_once_with(
|
||||
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
||||
verify=mock.ANY)
|
||||
self.ksc_client.Client.assert_called_once_with(**all_kwargs)
|
||||
self.ksc_client.Client.assert_called_once_with(
|
||||
version=None, **all_kwargs)
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
|
||||
def test_client_is_pre_authed(self):
|
||||
@ -139,6 +141,27 @@ class TestCreateKeystoneClient(test.TestCase):
|
||||
client = keystone._create_keystone_client(all_kwargs)
|
||||
auth_ref = getattr(client, "auth_ref", None)
|
||||
self.assertIsNot(auth_ref, None)
|
||||
self.ksc_client.Client.assert_called_once_with(
|
||||
version=None, **all_kwargs)
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
|
||||
def test_create_client_removes_url_path_if_version_specified(self):
|
||||
# If specifying a version on the client creation call, ensure
|
||||
# the auth_url is versionless and the version required is passed
|
||||
# into the Client() call.
|
||||
self.set_up_keystone_mocks()
|
||||
auth_kwargs, all_kwargs = self.make_auth_args()
|
||||
credential = objects.Credential(
|
||||
"http://auth_url/v2.0", "user", "pass", "tenant")
|
||||
keystone = osclients.Keystone(
|
||||
credential, {}, mock.MagicMock())
|
||||
client = keystone.create_client(version="3")
|
||||
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
called_with = self.ksc_client.Client.call_args_list[0][1]
|
||||
self.expectThat(
|
||||
called_with["auth_url"], matchers.Equals("http://auth_url/"))
|
||||
self.expectThat(called_with["version"], matchers.Equals("3"))
|
||||
|
||||
def test_create_keystone_client_with_v2_url_omits_domain(self):
|
||||
# NOTE(bigjools): Test that domain-related info is not present
|
||||
@ -160,7 +183,29 @@ class TestCreateKeystoneClient(test.TestCase):
|
||||
self.ksc_session.Session.assert_called_once_with(
|
||||
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
||||
verify=mock.ANY)
|
||||
self.ksc_client.Client.assert_called_once_with(**all_kwargs)
|
||||
self.ksc_client.Client.assert_called_once_with(
|
||||
version=None, **all_kwargs)
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
|
||||
def test_create_keystone_client_with_v2_version_omits_domain(self):
|
||||
self.set_up_keystone_mocks()
|
||||
auth_kwargs, all_kwargs = self.make_auth_args()
|
||||
|
||||
all_kwargs["auth_url"] = "http://auth_url/"
|
||||
auth_kwargs["auth_url"] = all_kwargs["auth_url"]
|
||||
keystone = osclients.Keystone(
|
||||
mock.MagicMock(), mock.sentinel, mock.sentinel)
|
||||
client = keystone._create_keystone_client(all_kwargs, version="2")
|
||||
|
||||
auth_kwargs.pop("user_domain_name")
|
||||
auth_kwargs.pop("project_domain_name")
|
||||
auth_kwargs.pop("domain_name")
|
||||
self.ksc_password.assert_called_once_with(**auth_kwargs)
|
||||
self.ksc_session.Session.assert_called_once_with(
|
||||
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
||||
verify=mock.ANY)
|
||||
self.ksc_client.Client.assert_called_once_with(
|
||||
version="2", **all_kwargs)
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
|
||||
|
||||
@ -260,7 +305,8 @@ class OSClientsTestCase(test.TestCase):
|
||||
"insecure": False, "cacert": None}
|
||||
kwargs = self.credential.to_dict()
|
||||
kwargs.update(credential.items())
|
||||
self.mock_create_keystone_client.assert_called_once_with(kwargs)
|
||||
self.mock_create_keystone_client.assert_called_once_with(
|
||||
kwargs, version=None)
|
||||
self.assertEqual(self.fake_keystone, self.clients.cache["keystone"])
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.create_client")
|
||||
|
Loading…
Reference in New Issue
Block a user