Extend existing@openstack platform with cert keys
* add support for https_cert and https_key options * also fix some small issues which appeared after forsing using credentials object inside the osclients Change-Id: Icc885a8b21fd7725009f871c7713a5ce98b60ddb
This commit is contained in:
parent
faedcbcb18
commit
230ade51af
@ -23,6 +23,10 @@ Added
|
||||
~~~~~
|
||||
|
||||
* Support Python 3.7 environment.
|
||||
* ``https_cert`` and ``https_key`` options of the spec for
|
||||
``existing@openstack`` platform to represent client certificate bundle and
|
||||
key files. Also the support for appropriate system environment variables (
|
||||
``OS_CERT``, ``OS_KEY``) is added.
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
|
@ -14,7 +14,6 @@
|
||||
# under the License.
|
||||
|
||||
from rally.common import logging
|
||||
from rally_openstack import osclients
|
||||
|
||||
LOG = logging.getLogger(__file__)
|
||||
|
||||
@ -28,7 +27,7 @@ class OpenStackCredential(dict):
|
||||
region_name=None, endpoint_type=None,
|
||||
domain_name=None, endpoint=None, user_domain_name=None,
|
||||
project_domain_name=None,
|
||||
https_insecure=False, https_cacert=None,
|
||||
https_insecure=False, https_cacert=None, https_cert=None,
|
||||
profiler_hmac_key=None, profiler_conn_str=None, **kwargs):
|
||||
if kwargs:
|
||||
raise TypeError("%s" % kwargs)
|
||||
@ -49,6 +48,7 @@ class OpenStackCredential(dict):
|
||||
("project_domain_name", project_domain_name),
|
||||
("https_insecure", https_insecure),
|
||||
("https_cacert", https_cacert),
|
||||
("https_cert", https_cert),
|
||||
("profiler_hmac_key", profiler_hmac_key),
|
||||
("profiler_conn_str", profiler_conn_str)
|
||||
])
|
||||
@ -70,5 +70,7 @@ class OpenStackCredential(dict):
|
||||
# this method is mostly used by validation step. let's refactor it and
|
||||
# deprecated this
|
||||
def clients(self, api_info=None):
|
||||
from rally_openstack import osclients
|
||||
|
||||
return osclients.Clients(self, api_info=api_info,
|
||||
cache=self._clients_cache)
|
||||
|
23
rally_openstack/exceptions.py
Normal file
23
rally_openstack/exceptions.py
Normal file
@ -0,0 +1,23 @@
|
||||
# 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 rally import exceptions as rally_exceptions
|
||||
|
||||
RallyException = rally_exceptions.RallyException
|
||||
|
||||
|
||||
class AuthenticationFailed(rally_exceptions.InvalidArgumentsException):
|
||||
error_code = 220
|
||||
msg_fmt = ("Failed to authenticate to %(url)s for user '%(username)s'"
|
||||
" in project '%(project)s': %(etype)s: %(error)s")
|
@ -20,11 +20,11 @@ from rally.cli import envutils
|
||||
from rally.common import cfg
|
||||
from rally.common import logging
|
||||
from rally.common.plugin import plugin
|
||||
from rally.common import utils
|
||||
from rally import exceptions
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from rally_openstack import consts
|
||||
from rally_openstack import credential as oscred
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -105,12 +105,12 @@ def configure(name, default_version=None, default_service_type=None,
|
||||
|
||||
@plugin.base()
|
||||
class OSClient(plugin.Plugin):
|
||||
"""Base class for openstack clients"""
|
||||
"""Base class for OpenStack clients"""
|
||||
|
||||
def __init__(self, credential, api_info, cache_obj):
|
||||
self.credential = credential
|
||||
if isinstance(self.credential, dict):
|
||||
self.credential = utils.Struct(**self.credential)
|
||||
if not isinstance(self.credential, oscred.OpenStackCredential):
|
||||
self.credential = oscred.OpenStackCredential(**self.credential)
|
||||
self.api_info = api_info
|
||||
self.cache = cache_obj
|
||||
|
||||
@ -187,13 +187,6 @@ class OSClient(plugin.Plugin):
|
||||
return OSClient.get("keystone")(self.credential, self.api_info,
|
||||
self.cache)
|
||||
|
||||
def _get_session(self, auth_url=None, version=None):
|
||||
LOG.warning(
|
||||
"Method `rally.osclient.OSClient._get_session` is deprecated since"
|
||||
" Rally 0.6.0. Use "
|
||||
"`rally.osclient.OSClient.keystone.get_session` instead.")
|
||||
return self.keystone.get_session(version)
|
||||
|
||||
def _get_endpoint(self, service_type=None):
|
||||
kw = {"service_type": self.choose_service_type(service_type),
|
||||
"region_name": self.credential.region_name}
|
||||
@ -317,13 +310,13 @@ class Keystone(OSClient):
|
||||
temp_session = session.Session(
|
||||
verify=(self.credential.https_cacert or
|
||||
not self.credential.https_insecure),
|
||||
cert=self.credential.https_cert,
|
||||
timeout=CONF.openstack_client_http_timeout)
|
||||
version = str(discover.Discover(
|
||||
temp_session,
|
||||
password_args["auth_url"]).version_data()[0]["version"][0])
|
||||
|
||||
if "v2.0" not in password_args["auth_url"] and (
|
||||
version != "2"):
|
||||
if "v2.0" not in password_args["auth_url"] and version != "2":
|
||||
password_args.update({
|
||||
"user_domain_name": self.credential.user_domain_name,
|
||||
"domain_name": self.credential.domain_name,
|
||||
@ -334,6 +327,7 @@ class Keystone(OSClient):
|
||||
auth=identity_plugin,
|
||||
verify=(self.credential.https_cacert or
|
||||
not self.credential.https_insecure),
|
||||
cert=self.credential.https_cert,
|
||||
timeout=CONF.openstack_client_http_timeout)
|
||||
self.cache[key] = (sess, identity_plugin)
|
||||
return self.cache[key]
|
||||
|
@ -72,6 +72,8 @@ class OpenStack(platform.Platform):
|
||||
"endpoint_type": {"enum": ["public", "internal", "admin", None]},
|
||||
"https_insecure": {"type": "boolean"},
|
||||
"https_cacert": {"type": "string"},
|
||||
"https_cert": {"type": "string"},
|
||||
"https_key": {"type": "string"},
|
||||
"profiler_hmac_key": {"type": ["string", "null"]},
|
||||
"profiler_conn_str": {"type": ["string", "null"]},
|
||||
"admin": {"$ref": "#/definitions/user"},
|
||||
@ -114,6 +116,10 @@ class OpenStack(platform.Platform):
|
||||
admin = new_data.pop("admin", None)
|
||||
users = new_data.pop("users", [])
|
||||
|
||||
if new_data.get("https_cert") and new_data.get("https_key"):
|
||||
new_data["https_cert"] = (new_data["https_cert"],
|
||||
new_data.pop("https_key"))
|
||||
|
||||
if admin:
|
||||
if "project_name" in admin:
|
||||
admin["tenant_name"] = admin.pop("project_name")
|
||||
@ -240,6 +246,8 @@ class OpenStack(platform.Platform):
|
||||
"endpoint_type": endpoint_type,
|
||||
"region_name": sys_environ.get("OS_REGION_NAME", ""),
|
||||
"https_cacert": sys_environ.get("OS_CACERT", ""),
|
||||
"https_cert": sys_environ.get("OS_CERT", ""),
|
||||
"https_key": sys_environ.get("OS_KEY", ""),
|
||||
"https_insecure": strutils.bool_from_string(
|
||||
sys_environ.get("OS_INSECURE")),
|
||||
"profiler_hmac_key": sys_environ.get("OSPROFILER_HMAC_KEY"),
|
||||
|
@ -153,7 +153,7 @@
|
||||
- name: Check Environment works
|
||||
become: True
|
||||
become_user: stack
|
||||
command: "rally env check"
|
||||
command: "rally --debug env check"
|
||||
|
||||
- name: Print Environment info
|
||||
become: True
|
||||
|
@ -16,6 +16,7 @@ import mock
|
||||
|
||||
from rally import exceptions
|
||||
from rally_openstack.contexts.sahara import sahara_image
|
||||
from tests.unit import fakes
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
@ -42,7 +43,7 @@ class SaharaImageTestCase(test.ScenarioTestCase):
|
||||
for j in range(self.users_per_tenant):
|
||||
self.users_key.append({"id": "%s_%s" % (str(i), str(j)),
|
||||
"tenant_id": str(i),
|
||||
"credential": mock.MagicMock()})
|
||||
"credential": fakes.FakeCredential()})
|
||||
|
||||
@property
|
||||
def url_image_context(self):
|
||||
@ -59,7 +60,7 @@ class SaharaImageTestCase(test.ScenarioTestCase):
|
||||
"username": "test_user"
|
||||
}
|
||||
},
|
||||
"admin": {"credential": mock.MagicMock()},
|
||||
"admin": {"credential": fakes.FakeCredential()},
|
||||
"users": self.users_key,
|
||||
"tenants": self.tenants
|
||||
})
|
||||
@ -77,7 +78,7 @@ class SaharaImageTestCase(test.ScenarioTestCase):
|
||||
"image_uuid": "some_id"
|
||||
}
|
||||
},
|
||||
"admin": {"credential": mock.MagicMock()},
|
||||
"admin": {"credential": fakes.FakeCredential()},
|
||||
"users": self.users_key,
|
||||
"tenants": self.tenants,
|
||||
})
|
||||
|
@ -33,6 +33,7 @@ import six
|
||||
from swiftclient import exceptions as swift_exceptions
|
||||
|
||||
from rally_openstack import consts
|
||||
from rally_openstack import credential
|
||||
|
||||
|
||||
def generate_uuid():
|
||||
@ -83,12 +84,13 @@ def setup_dict(data, required=None, defaults=None):
|
||||
return defaults
|
||||
|
||||
|
||||
def fake_credential(**config):
|
||||
m = mock.Mock()
|
||||
m.to_dict.return_value = config
|
||||
for key, value in config.items():
|
||||
setattr(m, key, value)
|
||||
return m
|
||||
class FakeCredential(credential.OpenStackCredential):
|
||||
def __init__(self, **creds):
|
||||
creds.setdefault("auth_url", "https://example.com")
|
||||
creds.setdefault("username", "admin")
|
||||
creds.setdefault("password", "pass")
|
||||
super(FakeCredential, self).__init__(**creds)
|
||||
self.clients = mock.Mock()
|
||||
|
||||
|
||||
class FakeResource(object):
|
||||
@ -1610,7 +1612,7 @@ class FakeClients(object):
|
||||
self._ec2 = None
|
||||
self._senlin = None
|
||||
self._watcher = None
|
||||
self._credential = credential_ or fake_credential(
|
||||
self._credential = credential_ or FakeCredential(
|
||||
auth_url="http://fake.example.org:5000/v2.0/",
|
||||
username="fake_username",
|
||||
password="fake_password",
|
||||
@ -1827,7 +1829,7 @@ class FakeUserContext(FakeContext):
|
||||
|
||||
admin = {
|
||||
"id": "adminuuid",
|
||||
"credential": fake_credential(
|
||||
"credential": FakeCredential(
|
||||
auth_url="aurl",
|
||||
username="aname",
|
||||
password="apwd",
|
||||
@ -1835,7 +1837,7 @@ class FakeUserContext(FakeContext):
|
||||
}
|
||||
user = {
|
||||
"id": "uuid",
|
||||
"credential": fake_credential(
|
||||
"credential": FakeCredential(
|
||||
auth_url="url",
|
||||
username="name",
|
||||
password="pwd",
|
||||
|
@ -155,8 +155,10 @@ class ExistingPlatformTestCase(PlatformBaseTestCase):
|
||||
"OS_INTERFACE": "publicURL",
|
||||
"OS_REGION_NAME": "Region1",
|
||||
"OS_CACERT": "Cacert",
|
||||
"OS_CERT": "cert",
|
||||
"OS_KEY": "key",
|
||||
"OS_INSECURE": True,
|
||||
"OSPROFILER_HMAC_KEY": "key",
|
||||
"OSPROFILER_HMAC_KEY": "hmackey",
|
||||
"OSPROFILER_CONN_STR": "https://example2.com",
|
||||
}
|
||||
|
||||
@ -173,8 +175,10 @@ class ExistingPlatformTestCase(PlatformBaseTestCase):
|
||||
"endpoint_type": "public",
|
||||
"region_name": "Region1",
|
||||
"https_cacert": "Cacert",
|
||||
"https_cert": "cert",
|
||||
"https_key": "key",
|
||||
"https_insecure": True,
|
||||
"profiler_hmac_key": "key",
|
||||
"profiler_hmac_key": "hmackey",
|
||||
"profiler_conn_str": "https://example2.com"
|
||||
}, result["spec"])
|
||||
|
||||
@ -182,7 +186,7 @@ class ExistingPlatformTestCase(PlatformBaseTestCase):
|
||||
sys_env["OS_IDENTITY_API_VERSION"] = "3"
|
||||
|
||||
result = existing.OpenStack.create_spec_from_sys_environ(sys_env)
|
||||
print(json.dumps(result["spec"], indent=4))
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
"admin": {
|
||||
@ -196,8 +200,10 @@ class ExistingPlatformTestCase(PlatformBaseTestCase):
|
||||
"auth_url": "https://example.com",
|
||||
"region_name": "Region1",
|
||||
"https_cacert": "Cacert",
|
||||
"https_cert": "cert",
|
||||
"https_key": "key",
|
||||
"https_insecure": True,
|
||||
"profiler_hmac_key": "key",
|
||||
"profiler_hmac_key": "hmackey",
|
||||
"profiler_conn_str": "https://example2.com"
|
||||
}, result["spec"])
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import mock
|
||||
|
||||
from rally_openstack import credential
|
||||
from rally_openstack.scenarios.cinder import utils
|
||||
from tests.unit import test
|
||||
|
||||
@ -23,13 +24,17 @@ class CinderBasicTestCase(test.ScenarioTestCase):
|
||||
|
||||
def _get_context(self):
|
||||
context = test.get_test_context()
|
||||
|
||||
cred = credential.OpenStackCredential(auth_url="url",
|
||||
username="user",
|
||||
password="pass")
|
||||
context.update({
|
||||
"admin": {
|
||||
"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()
|
||||
"credential": cred
|
||||
},
|
||||
"user": {"id": "fake_user_id",
|
||||
"credential": mock.MagicMock()},
|
||||
"credential": cred},
|
||||
"tenant": {"id": "fake", "name": "fake",
|
||||
"volumes": [{"id": "uuid", "size": 1}],
|
||||
"servers": [1]}})
|
||||
|
@ -39,6 +39,7 @@ class OpenStackCredentialTestCase(test.TestCase):
|
||||
"endpoint_type": None,
|
||||
"https_insecure": False,
|
||||
"https_cacert": None,
|
||||
"https_cert": None,
|
||||
"project_domain_name": None,
|
||||
"user_domain_name": None,
|
||||
"profiler_hmac_key": None,
|
||||
|
@ -85,12 +85,13 @@ class OSClientTestCase(test.TestCase, OSClientTestCaseUtils):
|
||||
def test_choose_service_type(self):
|
||||
default_service_type = "default_service_type"
|
||||
|
||||
@osclients.configure("test_choose_service_type",
|
||||
@osclients.configure(self.id(),
|
||||
default_service_type=default_service_type)
|
||||
class FakeClient(osclients.OSClient):
|
||||
create_client = mock.MagicMock()
|
||||
|
||||
fake_client = FakeClient(mock.MagicMock(), {}, {})
|
||||
fake_client = FakeClient({"auth_url": "url", "username": "user",
|
||||
"password": "pass"}, {}, {})
|
||||
self.assertEqual(default_service_type,
|
||||
fake_client.choose_service_type())
|
||||
self.assertEqual("foo",
|
||||
@ -122,40 +123,33 @@ class OSClientTestCase(test.TestCase, OSClientTestCaseUtils):
|
||||
mock_url_for.assert_called_once_with(**call_args)
|
||||
mock_choose_service_type.assert_called_once_with(service_type)
|
||||
|
||||
@mock.patch("%s.Keystone.get_session" % PATH)
|
||||
def test__get_session(self, mock_keystone_get_session):
|
||||
osclient = osclients.OSClient(None, None, None)
|
||||
auth_url = "auth_url"
|
||||
version = "version"
|
||||
import warnings
|
||||
with mock.patch.object(warnings, "warn") as mock_warn:
|
||||
self.assertEqual(mock_keystone_get_session.return_value,
|
||||
osclient._get_session(auth_url, version))
|
||||
self.assertFalse(mock_warn.called)
|
||||
mock_keystone_get_session.assert_called_once_with(version)
|
||||
|
||||
|
||||
class CachedTestCase(test.TestCase):
|
||||
|
||||
def test_cached(self):
|
||||
clients = osclients.Clients(mock.MagicMock())
|
||||
client_name = "CachedTestCase.test_cached"
|
||||
fake_client = osclients.configure(client_name)(osclients.OSClient)(
|
||||
clients.credential, clients.api_info, clients.cache)
|
||||
clients = osclients.Clients({"auth_url": "url", "username": "user",
|
||||
"password": "pass"})
|
||||
|
||||
@osclients.configure(self.id())
|
||||
class SomeClient(osclients.OSClient):
|
||||
pass
|
||||
|
||||
fake_client = SomeClient(clients.credential, clients.api_info,
|
||||
clients.cache)
|
||||
fake_client.create_client = mock.MagicMock()
|
||||
|
||||
self.assertEqual({}, clients.cache)
|
||||
fake_client()
|
||||
self.assertEqual(
|
||||
{client_name: fake_client.create_client.return_value},
|
||||
{self.id(): fake_client.create_client.return_value},
|
||||
clients.cache)
|
||||
fake_client.create_client.assert_called_once_with()
|
||||
fake_client()
|
||||
fake_client.create_client.assert_called_once_with()
|
||||
fake_client("2")
|
||||
self.assertEqual(
|
||||
{client_name: fake_client.create_client.return_value,
|
||||
"%s('2',)" % client_name: fake_client.create_client.return_value},
|
||||
{self.id(): fake_client.create_client.return_value,
|
||||
"%s('2',)" % self.id(): fake_client.create_client.return_value},
|
||||
clients.cache)
|
||||
clients.clear()
|
||||
self.assertEqual({}, clients.cache)
|
||||
@ -258,12 +252,12 @@ class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
|
||||
domain_name=None, project_domain_name=None,
|
||||
user_domain_name=None)
|
||||
self.ksa_session.Session.assert_has_calls(
|
||||
[mock.call(timeout=180.0, verify=True),
|
||||
[mock.call(timeout=180.0, verify=True, cert=None),
|
||||
mock.call(auth=self.ksa_identity_plugin, timeout=180.0,
|
||||
verify=True)])
|
||||
verify=True, cert=None)])
|
||||
|
||||
def test_keystone_property(self):
|
||||
keystone = osclients.Keystone(None, None, None)
|
||||
keystone = osclients.Keystone(self.credential, None, None)
|
||||
self.assertRaises(exceptions.RallyException, lambda: keystone.keystone)
|
||||
|
||||
@mock.patch("%s.Keystone.get_session" % PATH)
|
||||
@ -272,7 +266,7 @@ class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
|
||||
auth_plugin = mock.MagicMock()
|
||||
mock_keystone_get_session.return_value = (session, auth_plugin)
|
||||
cache = {}
|
||||
keystone = osclients.Keystone(None, None, cache)
|
||||
keystone = osclients.Keystone(self.credential, None, cache)
|
||||
|
||||
self.assertEqual(auth_plugin.get_access.return_value,
|
||||
keystone.auth_ref)
|
||||
|
@ -48,7 +48,7 @@ class TempestConfigfileManagerTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(TempestConfigfileManagerTestCase, self).setUp()
|
||||
deployment = fakes.FakeDeployment(uuid="fake_deployment",
|
||||
admin=fakes.fake_credential(**CRED))
|
||||
admin=fakes.FakeCredential(**CRED))
|
||||
self.tempest = config.TempestConfigfileManager(deployment)
|
||||
|
||||
def test__configure_auth(self):
|
||||
|
@ -55,7 +55,7 @@ class TempestContextTestCase(test.TestCase):
|
||||
self.mock_isfile = mock.patch("os.path.isfile",
|
||||
return_value=True).start()
|
||||
|
||||
self.cred = fakes.fake_credential(**CRED)
|
||||
self.cred = fakes.FakeCredential(**CRED)
|
||||
self.deployment = fakes.FakeDeployment(
|
||||
uuid="fake_deployment", admin=self.cred)
|
||||
cfg = {"verifier": mock.Mock(deployment=self.deployment),
|
||||
|
Loading…
x
Reference in New Issue
Block a user