Merge "Add ability to select keystone API version"
This commit is contained in:
commit
08f9418513
@ -16,6 +16,7 @@
|
|||||||
import abc
|
import abc
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from six.moves.urllib import parse
|
||||||
|
|
||||||
from rally.cli import envutils
|
from rally.cli import envutils
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
@ -94,9 +95,12 @@ class OSClient(plugin.Plugin):
|
|||||||
# version is a string object.
|
# version is a string object.
|
||||||
# For those clients which doesn't accept string value(for example
|
# For those clients which doesn't accept string value(for example
|
||||||
# zaqarclient), this method should be overridden.
|
# zaqarclient), this method should be overridden.
|
||||||
return str(version
|
version = (version
|
||||||
or self.api_info.get(self.get_name(), {}).get("version")
|
or self.api_info.get(self.get_name(), {}).get("version")
|
||||||
or self._meta_get("default_version"))
|
or self._meta_get("default_version"))
|
||||||
|
if version is not None:
|
||||||
|
version = str(version)
|
||||||
|
return version
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_versions(cls):
|
def get_supported_versions(cls):
|
||||||
@ -208,13 +212,14 @@ class OSClient(plugin.Plugin):
|
|||||||
return super(OSClient, cls).get(name, namespace)
|
return super(OSClient, cls).get(name, namespace)
|
||||||
|
|
||||||
|
|
||||||
@configure("keystone")
|
@configure("keystone", supported_versions=("2", "3"))
|
||||||
class Keystone(OSClient):
|
class Keystone(OSClient):
|
||||||
|
|
||||||
def keystone(self, *args, **kwargs):
|
def keystone(self, *args, **kwargs):
|
||||||
raise exceptions.RallyException(_("Method 'keystone' is restricted "
|
raise exceptions.RallyException(_("Method 'keystone' is restricted "
|
||||||
"for keystoneclient. :)"))
|
"for keystoneclient. :)"))
|
||||||
|
|
||||||
def _create_keystone_client(self, args):
|
def _create_keystone_client(self, args, version=None):
|
||||||
from keystoneclient.auth import identity
|
from keystoneclient.auth import identity
|
||||||
from keystoneclient import client
|
from keystoneclient import client
|
||||||
auth_arg_list = [
|
auth_arg_list = [
|
||||||
@ -223,7 +228,7 @@ class Keystone(OSClient):
|
|||||||
]
|
]
|
||||||
# NOTE(bigjools): If forcing a v2.0 URL then you cannot specify
|
# NOTE(bigjools): If forcing a v2.0 URL then you cannot specify
|
||||||
# domain-related info, or the service discovery will fail.
|
# 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(
|
auth_arg_list.extend(
|
||||||
["user_domain_name", "domain_name", "project_domain_name"])
|
["user_domain_name", "domain_name", "project_domain_name"])
|
||||||
auth_args = {key: args.get(key) for key in auth_arg_list}
|
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
|
# list which is why we need to ensure service_catalog is still
|
||||||
# present.
|
# present.
|
||||||
auth_ref = auth.get_access(session)
|
auth_ref = auth.get_access(session)
|
||||||
ks = client.Client(**args)
|
ks = client.Client(version=version, **args)
|
||||||
ks.auth_ref = auth_ref
|
ks.auth_ref = auth_ref
|
||||||
return ks
|
return ks
|
||||||
|
|
||||||
def create_client(self):
|
def _remove_url_version(self):
|
||||||
"""Return keystone client."""
|
"""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 = {
|
new_kw = {
|
||||||
"timeout": CONF.openstack_client_http_timeout,
|
"timeout": CONF.openstack_client_http_timeout,
|
||||||
"insecure": self.credential.insecure,
|
"insecure": self.credential.insecure,
|
||||||
@ -253,7 +282,9 @@ class Keystone(OSClient):
|
|||||||
}
|
}
|
||||||
kw = self.credential.to_dict()
|
kw = self.credential.to_dict()
|
||||||
kw.update(new_kw)
|
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")
|
@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
|
from keystoneclient import exceptions as keystone_exceptions
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from testtools import matchers
|
||||||
|
|
||||||
from rally.common import objects
|
from rally.common import objects
|
||||||
from rally import consts
|
from rally import consts
|
||||||
@ -125,7 +126,8 @@ class TestCreateKeystoneClient(test.TestCase):
|
|||||||
self.ksc_session.Session.assert_called_once_with(
|
self.ksc_session.Session.assert_called_once_with(
|
||||||
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
||||||
verify=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())
|
self.assertIs(client, self.ksc_client.Client())
|
||||||
|
|
||||||
def test_client_is_pre_authed(self):
|
def test_client_is_pre_authed(self):
|
||||||
@ -139,6 +141,27 @@ class TestCreateKeystoneClient(test.TestCase):
|
|||||||
client = keystone._create_keystone_client(all_kwargs)
|
client = keystone._create_keystone_client(all_kwargs)
|
||||||
auth_ref = getattr(client, "auth_ref", None)
|
auth_ref = getattr(client, "auth_ref", None)
|
||||||
self.assertIsNot(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):
|
def test_create_keystone_client_with_v2_url_omits_domain(self):
|
||||||
# NOTE(bigjools): Test that domain-related info is not present
|
# 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(
|
self.ksc_session.Session.assert_called_once_with(
|
||||||
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
auth=self.ksc_identity.Password(), timeout=mock.ANY,
|
||||||
verify=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())
|
self.assertIs(client, self.ksc_client.Client())
|
||||||
|
|
||||||
|
|
||||||
@ -260,7 +305,8 @@ class OSClientsTestCase(test.TestCase):
|
|||||||
"insecure": False, "cacert": None}
|
"insecure": False, "cacert": None}
|
||||||
kwargs = self.credential.to_dict()
|
kwargs = self.credential.to_dict()
|
||||||
kwargs.update(credential.items())
|
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"])
|
self.assertEqual(self.fake_keystone, self.clients.cache["keystone"])
|
||||||
|
|
||||||
@mock.patch("rally.osclients.Keystone.create_client")
|
@mock.patch("rally.osclients.Keystone.create_client")
|
||||||
|
Loading…
Reference in New Issue
Block a user