summaryrefslogtreecommitdiff
path: root/keystoneclient
diff options
context:
space:
mode:
Diffstat (limited to 'keystoneclient')
-rw-r--r--keystoneclient/adapter.py37
-rw-r--r--keystoneclient/auth/base.py64
-rw-r--r--keystoneclient/auth/cli.py2
-rw-r--r--keystoneclient/auth/conf.py8
-rw-r--r--keystoneclient/auth/identity/base.py20
-rw-r--r--keystoneclient/auth/identity/generic/base.py3
-rw-r--r--keystoneclient/auth/identity/v3.py3
-rw-r--r--keystoneclient/client.py7
-rw-r--r--keystoneclient/common/cms.py19
-rw-r--r--keystoneclient/httpclient.py6
-rw-r--r--keystoneclient/session.py82
-rw-r--r--keystoneclient/tests/auth/test_cli.py20
-rw-r--r--keystoneclient/tests/auth/test_identity_common.py18
-rw-r--r--keystoneclient/tests/auth/test_identity_v3.py3
-rw-r--r--keystoneclient/tests/auth/test_token_endpoint.py10
-rw-r--r--keystoneclient/tests/auth/utils.py3
-rw-r--r--keystoneclient/tests/generic/test_client.py3
-rw-r--r--keystoneclient/tests/test_auth_token_middleware.py162
-rw-r--r--keystoneclient/tests/test_discovery.py135
-rw-r--r--keystoneclient/tests/test_s3_token_middleware.py12
-rw-r--r--keystoneclient/tests/test_session.py55
-rw-r--r--keystoneclient/tests/test_shell.py11
-rw-r--r--keystoneclient/tests/v2_0/test_certificates.py40
-rw-r--r--keystoneclient/tests/v2_0/test_client.py11
-rw-r--r--keystoneclient/tests/v2_0/test_shell.py29
-rw-r--r--keystoneclient/tests/v2_0/test_tokens.py7
-rw-r--r--keystoneclient/tests/v3/test_auth_saml2.py99
-rw-r--r--keystoneclient/tests/v3/test_client.py8
-rw-r--r--keystoneclient/tests/v3/test_discover.py6
-rw-r--r--keystoneclient/tests/v3/test_domains.py5
-rw-r--r--keystoneclient/tests/v3/test_federation.py6
-rw-r--r--keystoneclient/tests/v3/test_regions.py5
-rw-r--r--keystoneclient/tests/v3/test_services.py12
-rw-r--r--keystoneclient/tests/v3/utils.py27
-rw-r--r--keystoneclient/v2_0/certificates.py42
-rw-r--r--keystoneclient/v2_0/client.py2
-rwxr-xr-xkeystoneclient/v2_0/shell.py4
-rw-r--r--keystoneclient/v2_0/tokens.py10
-rw-r--r--keystoneclient/v3/domains.py2
-rw-r--r--keystoneclient/v3/regions.py4
-rw-r--r--keystoneclient/v3/services.py7
41 files changed, 646 insertions, 363 deletions
diff --git a/keystoneclient/adapter.py b/keystoneclient/adapter.py
index 3cb4dc4..e14ce7d 100644
--- a/keystoneclient/adapter.py
+++ b/keystoneclient/adapter.py
@@ -116,6 +116,9 @@ class Adapter(object):
:returns: An endpoint if available or None.
:rtype: string
"""
+ if self.endpoint_override:
+ return self.endpoint_override
+
self._set_endpoint_filter_kwargs(kwargs)
return self.session.get_endpoint(auth or self.auth, **kwargs)
@@ -123,6 +126,40 @@ class Adapter(object):
"""Invalidate an authentication plugin."""
return self.session.invalidate(auth or self.auth)
+ def get_user_id(self, auth=None):
+ """Return the authenticated user_id as provided by the auth plugin.
+
+ :param auth: The auth plugin to use for token. Overrides the plugin
+ on the session. (optional)
+ :type auth: keystoneclient.auth.base.BaseAuthPlugin
+
+ :raises keystoneclient.exceptions.AuthorizationFailure:
+ if a new token fetch fails.
+ :raises keystoneclient.exceptions.MissingAuthPlugin:
+ if a plugin is not available.
+
+ :returns: Current `user_id` or None if not supported by plugin.
+ :rtype: string
+ """
+ return self.session.get_user_id(auth or self.auth)
+
+ def get_project_id(self, auth=None):
+ """Return the authenticated project_id as provided by the auth plugin.
+
+ :param auth: The auth plugin to use for token. Overrides the plugin
+ on the session. (optional)
+ :type auth: keystoneclient.auth.base.BaseAuthPlugin
+
+ :raises keystoneclient.exceptions.AuthorizationFailure:
+ if a new token fetch fails.
+ :raises keystoneclient.exceptions.MissingAuthPlugin:
+ if a plugin is not available.
+
+ :returns: Current `project_id` or None if not supported by plugin.
+ :rtype: string
+ """
+ return self.session.get_project_id(auth or self.auth)
+
def get(self, url, **kwargs):
return self.request(url, 'GET', **kwargs)
diff --git a/keystoneclient/auth/base.py b/keystoneclient/auth/base.py
index 1f4ce29..9da90b7 100644
--- a/keystoneclient/auth/base.py
+++ b/keystoneclient/auth/base.py
@@ -34,6 +34,7 @@ def get_plugin_class(name):
:param str name: The name of the object to get.
:returns: An auth plugin class.
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
:raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be
created.
@@ -67,6 +68,8 @@ class BaseAuthPlugin(object):
Returning None will indicate that no token was able to be retrieved.
:param session: A session object so the plugin can make HTTP calls.
+ :type session: keystoneclient.session.Session
+
:return: A token to use.
:rtype: string
"""
@@ -84,8 +87,8 @@ class BaseAuthPlugin(object):
- ``interface``: what visibility the endpoint should have.
- ``region_name``: the region the endpoint exists in.
- :param Session session: The session object that the auth_plugin
- belongs to.
+ :param session: The session object that the auth_plugin belongs to.
+ :type session: keystoneclient.session.Session
:returns: The base URL that will be used to talk to the required
service or None if not available.
@@ -108,6 +111,36 @@ class BaseAuthPlugin(object):
"""
return False
+ def get_user_id(self, session, **kwargs):
+ """Return a unique user identifier of the plugin.
+
+ Wherever possible the user id should be inferred from the token however
+ there are certain URLs and other places that require access to the
+ currently authenticated user id.
+
+ :param session: A session object so the plugin can make HTTP calls.
+ :type session: keystoneclient.session.Session
+
+ :returns: A user identifier or None if one is not available.
+ :rtype: str
+ """
+ return None
+
+ def get_project_id(self, session, **kwargs):
+ """Return the project id that we are authenticated to.
+
+ Wherever possible the project id should be inferred from the token
+ however there are certain URLs and other places that require access to
+ the currently authenticated project id.
+
+ :param session: A session object so the plugin can make HTTP calls.
+ :type session: keystoneclient.session.Session
+
+ :returns: A project identifier or None if one is not available.
+ :rtype: str
+ """
+ return None
+
@classmethod
def get_options(cls):
"""Return the list of parameters associated with the auth plugin.
@@ -137,8 +170,8 @@ class BaseAuthPlugin(object):
Given a plugin class convert it's options into argparse arguments and
add them to a parser.
- :param AuthPlugin plugin: an auth plugin class.
- :param argparse.ArgumentParser: the parser to attach argparse options.
+ :param parser: the parser to attach argparse options.
+ :type parser: argparse.ArgumentParser
"""
# NOTE(jamielennox): ideally oslo.config would be smart enough to
@@ -155,14 +188,12 @@ class BaseAuthPlugin(object):
args.append('--os-%s' % o.name)
envs.append('OS_%s' % o.name.replace('-', '_').upper())
- default = opt.default
- if default is None:
- # select the first ENV that is not false-y or return None
- env_vars = (os.environ.get(e) for e in envs)
- default = six.next(six.moves.filter(None, env_vars), None)
+ # select the first ENV that is not false-y or return None
+ env_vars = (os.environ.get(e) for e in envs)
+ default = six.next(six.moves.filter(None, env_vars), None)
parser.add_argument(*args,
- default=default,
+ default=default or opt.default,
metavar=opt.metavar,
help=opt.help,
dest='os_%s' % opt.dest)
@@ -173,10 +204,11 @@ class BaseAuthPlugin(object):
Convert the results of a parse into the specified plugin.
- :param AuthPlugin plugin: an auth plugin class.
- :param Namespace namespace: The result from CLI parsing.
+ :param namespace: The result from CLI parsing.
+ :type namespace: argparse.Namespace
:returns: An auth plugin, or None if a name is not provided.
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
"""
for opt in cls.get_options():
val = getattr(namespace, 'os_%s' % opt.dest)
@@ -190,7 +222,8 @@ class BaseAuthPlugin(object):
def register_conf_options(cls, conf, group):
"""Register the oslo.config options that are needed for a plugin.
- :param conf: An oslo.config conf object.
+ :param conf: A config object.
+ :type conf: oslo.config.cfg.ConfigOpts
:param string group: The group name that options should be read from.
"""
plugin_opts = cls.get_options()
@@ -202,11 +235,12 @@ class BaseAuthPlugin(object):
Convert the options already registered into a real plugin.
- :param conf: An oslo.config conf object.
+ :param conf: A config object.
+ :type conf: oslo.config.cfg.ConfigOpts
:param string group: The group name that options should be read from.
:returns: An authentication Plugin.
- :rtype: plugin:
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
"""
plugin_opts = cls.get_options()
diff --git a/keystoneclient/auth/cli.py b/keystoneclient/auth/cli.py
index ce4f11f..40a81c1 100644
--- a/keystoneclient/auth/cli.py
+++ b/keystoneclient/auth/cli.py
@@ -30,6 +30,7 @@ def register_argparse_arguments(parser, argv, default=None):
if one isn't specified by the CLI. default: None.
:returns: The plugin class that will be loaded or None if not provided.
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
:raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be
created.
@@ -68,6 +69,7 @@ def load_from_argparse_arguments(namespace, **kwargs):
:param Namespace namespace: The result from CLI parsing.
:returns: An auth plugin, or None if a name is not provided.
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
:raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be
created.
diff --git a/keystoneclient/auth/conf.py b/keystoneclient/auth/conf.py
index 0b68184..fdd2aa4 100644
--- a/keystoneclient/auth/conf.py
+++ b/keystoneclient/auth/conf.py
@@ -60,7 +60,8 @@ def register_conf_options(conf, group):
taken. If section is not provided then the auth plugin options will be
taken from the same group as provided in the parameters.
- :param oslo.config.Cfg conf: config object to register with.
+ :param conf: config object to register with.
+ :type conf: oslo.config.cfg.ConfigOpts
:param string group: The ini group to register options in.
"""
conf.register_opt(_AUTH_SECTION_OPT, group=group)
@@ -85,11 +86,12 @@ def load_from_conf_options(conf, group, **kwargs):
The base options should have been registered with register_conf_options
before this function is called.
- :param conf: An oslo.config conf object.
+ :param conf: A conf object.
+ :type conf: oslo.config.cfg.ConfigOpts
:param string group: The group name that options should be read from.
:returns: An authentication Plugin or None if a name is not provided
- :rtype: plugin
+ :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
:raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be
created.
diff --git a/keystoneclient/auth/identity/base.py b/keystoneclient/auth/identity/base.py
index 94b0712..ad8adb0 100644
--- a/keystoneclient/auth/identity/base.py
+++ b/keystoneclient/auth/identity/base.py
@@ -74,6 +74,9 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
when invoked. If you are looking to just retrieve the current auth
data then you should use get_access.
+ :param session: A session object that can be used for communication.
+ :type session: keystoneclient.session.Session
+
:raises keystoneclient.exceptions.InvalidResponse: The response
returned wasn't
appropriate.
@@ -89,6 +92,9 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
If a valid token is not present then a new one will be fetched.
+ :param session: A session object that can be used for communication.
+ :type session: keystoneclient.session.Session
+
:raises keystoneclient.exceptions.HttpError: An error from an invalid
HTTP response.
@@ -125,6 +131,9 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
If a valid AccessInfo is present then it is returned otherwise a new
one will be fetched.
+ :param session: A session object that can be used for communication.
+ :type session: keystoneclient.session.Session
+
:raises keystoneclient.exceptions.HttpError: An error from an invalid
HTTP response.
@@ -164,6 +173,8 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
If a valid token is not present then a new one will be fetched using
the session and kwargs.
+ :param session: A session object that can be used for communication.
+ :type session: keystoneclient.session.Session
:param string service_type: The type of service to lookup the endpoint
for. This plugin will return None (failure)
if service_type is not provided.
@@ -236,6 +247,12 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
return url
+ def get_user_id(self, session, **kwargs):
+ return self.get_access(session).user_id
+
+ def get_project_id(self, session, **kwargs):
+ return self.get_access(session).project_id
+
@utils.positional()
def get_discovery(self, session, url, authenticated=None):
"""Return the discovery object for a URL.
@@ -247,7 +264,8 @@ class BaseIdentityPlugin(base.BaseAuthPlugin):
This function is expected to be used by subclasses and should not
be needed by users.
- :param Session session: A session object to discover with.
+ :param session: A session object to discover with.
+ :type session: keystoneclient.session.Session
:param str url: The url to lookup.
:param bool authenticated: Include a token in the discovery call.
(optional) Defaults to None (use a token
diff --git a/keystoneclient/auth/identity/generic/base.py b/keystoneclient/auth/identity/generic/base.py
index 4fa3c9c..7c5a80f 100644
--- a/keystoneclient/auth/identity/generic/base.py
+++ b/keystoneclient/auth/identity/generic/base.py
@@ -81,7 +81,8 @@ class BaseGenericPlugin(base.BaseIdentityPlugin):
params then it should return it. If not return None and then another
call will be made with other available URLs.
- :param Session session: A session object.
+ :param session: A session object.
+ :type session: keystoneclient.session.Session
:param tuple version: A tuple of the API version at the URL.
:param string url: The base URL for this version.
:param string raw_status: The status that was in the discovery field.
diff --git a/keystoneclient/auth/identity/v3.py b/keystoneclient/auth/identity/v3.py
index 8f723ff..cc3a62c 100644
--- a/keystoneclient/auth/identity/v3.py
+++ b/keystoneclient/auth/identity/v3.py
@@ -176,7 +176,8 @@ class AuthMethod(object):
def get_auth_data(self, session, auth, headers, **kwargs):
"""Return the authentication section of an auth plugin.
- :param Session session: The communication session.
+ :param session: The communication session.
+ :type session: keystoneclient.session.Session
:param Auth auth: The auth plugin calling the method.
:param dict headers: The headers that will be sent with the auth
request if a plugin needs to add to them.
diff --git a/keystoneclient/client.py b/keystoneclient/client.py
index 8b6a6b0..8de2963 100644
--- a/keystoneclient/client.py
+++ b/keystoneclient/client.py
@@ -28,9 +28,10 @@ def Client(version=None, unstable=False, session=None, **kwargs):
at least the specified minor version. For example to
specify the 3.1 API use (3, 1).
:param bool unstable: Accept endpoints not marked as 'stable'. (optional)
- :param Session session: A session object to be used for communication. If
- one is not provided it will be constructed from the
- provided kwargs. (optional)
+ :param session: A session object to be used for communication. If one is
+ not provided it will be constructed from the provided
+ kwargs. (optional)
+ :type session: keystoneclient.session.Session
:param kwargs: Additional arguments are passed through to the client
that is being created.
:returns: New keystone client object
diff --git a/keystoneclient/common/cms.py b/keystoneclient/common/cms.py
index d49a0c5..19390f2 100644
--- a/keystoneclient/common/cms.py
+++ b/keystoneclient/common/cms.py
@@ -23,6 +23,7 @@ import base64
import errno
import hashlib
import logging
+import textwrap
import zlib
import six
@@ -227,20 +228,10 @@ def pkiz_verify(signed_text, signing_cert_file_name, ca_file_name):
def token_to_cms(signed_text):
copy_of_text = signed_text.replace('-', '/')
- formatted = '-----BEGIN CMS-----\n'
- line_length = 64
- while len(copy_of_text) > 0:
- if (len(copy_of_text) > line_length):
- formatted += copy_of_text[:line_length]
- copy_of_text = copy_of_text[line_length:]
- else:
- formatted += copy_of_text
- copy_of_text = ''
- formatted += '\n'
-
- formatted += '-----END CMS-----\n'
-
- return formatted
+ lines = ['-----BEGIN CMS-----']
+ lines += textwrap.wrap(copy_of_text, 64)
+ lines.append('-----END CMS-----\n')
+ return '\n'.join(lines)
def verify_token(token, signing_cert_file_name, ca_file_name):
diff --git a/keystoneclient/httpclient.py b/keystoneclient/httpclient.py
index 458745f..84b314e 100644
--- a/keystoneclient/httpclient.py
+++ b/keystoneclient/httpclient.py
@@ -362,6 +362,12 @@ class HTTPClient(baseclient.Client, base.BaseAuthPlugin):
else:
return self.management_url
+ def get_user_id(self, session, **kwargs):
+ return self.auth_ref.user_id
+
+ def get_project_id(self, session, **kwargs):
+ return self.auth_ref.project_id
+
@auth_token.setter
def auth_token(self, value):
"""Override the auth_token.
diff --git a/keystoneclient/session.py b/keystoneclient/session.py
index d68e209..0c3edbb 100644
--- a/keystoneclient/session.py
+++ b/keystoneclient/session.py
@@ -53,6 +53,21 @@ def request(url, method='GET', **kwargs):
return Session().request(url, method=method, **kwargs)
+def remove_service_catalog(body):
+ try:
+ data = jsonutils.loads(body)
+ except ValueError:
+ return body
+ try:
+ if 'catalog' in data['token']:
+ data['token']['catalog'] = '<removed>'
+ return jsonutils.dumps(data)
+ else:
+ return body
+ except KeyError:
+ return body
+
+
class Session(object):
"""Maintains client communication state and common functionality.
@@ -182,7 +197,7 @@ class Session(object):
if not headers:
headers = response.headers
if not text:
- text = response.text
+ text = remove_service_catalog(response.text)
if json:
text = jsonutils.dumps(json)
@@ -534,6 +549,16 @@ class Session(object):
return cls(verify=verify, cert=cert, **kwargs)
+ def _auth_required(self, auth, msg):
+ if not auth:
+ auth = self.auth
+
+ if not auth:
+ msg_fmt = _('An auth plugin is required to %s')
+ raise exceptions.MissingAuthPlugin(msg_fmt % msg)
+
+ return auth
+
def get_token(self, auth=None):
"""Return a token as provided by the auth plugin.
@@ -549,11 +574,7 @@ class Session(object):
:returns: A valid token.
:rtype: string
"""
- if not auth:
- auth = self.auth
-
- if not auth:
- raise exceptions.MissingAuthPlugin(_("Token Required"))
+ auth = self._auth_required(auth, 'fetch a token')
try:
return auth.get_token(self)
@@ -574,14 +595,7 @@ class Session(object):
:returns: An endpoint if available or None.
:rtype: string
"""
- if not auth:
- auth = self.auth
-
- if not auth:
- raise exceptions.MissingAuthPlugin(
- _('An auth plugin is required to determine the endpoint '
- 'URL.'))
-
+ auth = self._auth_required(auth, 'determine endpoint URL')
return auth.get_endpoint(self, **kwargs)
def invalidate(self, auth=None):
@@ -592,14 +606,42 @@ class Session(object):
:type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin`
"""
- if not auth:
- auth = self.auth
+ auth = self._auth_required(auth, 'validate')
+ return auth.invalidate()
- if not auth:
- msg = _('Auth plugin not available to invalidate')
- raise exceptions.MissingAuthPlugin(msg)
+ def get_user_id(self, auth=None):
+ """Return the authenticated user_id as provided by the auth plugin.
- return auth.invalidate()
+ :param auth: The auth plugin to use for token. Overrides the plugin
+ on the session. (optional)
+ :type auth: keystoneclient.auth.base.BaseAuthPlugin
+
+ :raises keystoneclient.exceptions.AuthorizationFailure:
+ if a new token fetch fails.
+ :raises keystoneclient.exceptions.MissingAuthPlugin:
+ if a plugin is not available.
+
+ :returns string: Current user_id or None if not supported by plugin.
+ """
+ auth = self._auth_required(auth, 'get user_id')
+ return auth.get_user_id(self)
+
+ def get_project_id(self, auth=None):
+ """Return the authenticated project_id as provided by the auth plugin.
+
+ :param auth: The auth plugin to use for token. Overrides the plugin
+ on the session. (optional)
+ :type auth: keystoneclient.auth.base.BaseAuthPlugin
+
+ :raises keystoneclient.exceptions.AuthorizationFailure:
+ if a new token fetch fails.
+ :raises keystoneclient.exceptions.MissingAuthPlugin:
+ if a plugin is not available.
+
+ :returns string: Current project_id or None if not supported by plugin.
+ """
+ auth = self._auth_required(auth, 'get project_id')
+ return auth.get_project_id(self)
@utils.positional.classmethod()
def get_conf_options(cls, deprecated_opts=None):
diff --git a/keystoneclient/tests/auth/test_cli.py b/keystoneclient/tests/auth/test_cli.py
index fc09195..33c2868 100644
--- a/keystoneclient/tests/auth/test_cli.py
+++ b/keystoneclient/tests/auth/test_cli.py
@@ -13,6 +13,7 @@
import argparse
import uuid
+import fixtures
import mock
from oslo.config import cfg
@@ -43,6 +44,13 @@ class CliTests(utils.TestCase):
super(CliTests, self).setUp()
self.p = argparse.ArgumentParser()
+ def env(self, name, value=None):
+ if value is not None:
+ # environment variables are always strings
+ value = str(value)
+
+ return self.useFixture(fixtures.EnvironmentVariable(name, value))
+
def test_creating_with_no_args(self):
ret = cli.register_argparse_arguments(self.p, [])
self.assertIsNone(ret)
@@ -140,6 +148,18 @@ class CliTests(utils.TestCase):
self.assertIs(utils.MockPlugin, klass)
m.assert_called_once_with(name)
+ @utils.mock_plugin
+ def test_env_overrides_default_opt(self, m):
+ name = uuid.uuid4().hex
+ val = uuid.uuid4().hex
+ self.env('OS_A_STR', val)
+
+ klass = cli.register_argparse_arguments(self.p, [], default=name)
+ opts = self.p.parse_args([])
+ a = klass.load_from_argparse_arguments(opts)
+
+ self.assertEqual(val, a['a_str'])
+
def test_deprecated_cli_options(self):
TesterPlugin.register_argparse_arguments(self.p)
val = uuid.uuid4().hex
diff --git a/keystoneclient/tests/auth/test_identity_common.py b/keystoneclient/tests/auth/test_identity_common.py
index 4a0cf57..a7d9be6 100644
--- a/keystoneclient/tests/auth/test_identity_common.py
+++ b/keystoneclient/tests/auth/test_identity_common.py
@@ -65,6 +65,13 @@ class CommonIdentityTests(object):
def stub_auth_data(self, **kwargs):
token = self.get_auth_data(**kwargs)
+ self.user_id = token.user_id
+
+ try:
+ self.project_id = token.project_id
+ except AttributeError:
+ self.project_id = token.tenant_id
+
self.stub_auth(json=token)
@abc.abstractproperty
@@ -107,7 +114,7 @@ class CommonIdentityTests(object):
# register responses such that if the discovery URL is hit more than
# once then the response will be invalid and not point to COMPUTE_ADMIN
resps = [{'json': self.TEST_DISCOVERY}, {'status_code': 500}]
- self.requests.register_uri('GET', self.TEST_COMPUTE_ADMIN, resps)
+ self.requests.get(self.TEST_COMPUTE_ADMIN, resps)
body = 'SUCCESS'
self.stub_url('GET', ['path'], text=body)
@@ -132,7 +139,7 @@ class CommonIdentityTests(object):
# register responses such that if the discovery URL is hit more than
# once then the response will be invalid and not point to COMPUTE_ADMIN
resps = [{'json': self.TEST_DISCOVERY}, {'status_code': 500}]
- self.requests.register_uri('GET', self.TEST_COMPUTE_ADMIN, resps)
+ self.requests.get(self.TEST_COMPUTE_ADMIN, resps)
body = 'SUCCESS'
self.stub_url('GET', ['path'], text=body)
@@ -221,6 +228,13 @@ class CommonIdentityTests(object):
self.assertIsNone(a.auth_ref)
self.assertFalse(a.invalidate())
+ def test_get_auth_properties(self):
+ a = self.create_auth_plugin()
+ s = session.Session()
+
+ self.assertEqual(self.user_id, a.get_user_id(s))
+ self.assertEqual(self.project_id, a.get_project_id(s))
+
class V3(CommonIdentityTests, utils.TestCase):
diff --git a/keystoneclient/tests/auth/test_identity_v3.py b/keystoneclient/tests/auth/test_identity_v3.py
index bce4fa7..d869dba 100644
--- a/keystoneclient/tests/auth/test_identity_v3.py
+++ b/keystoneclient/tests/auth/test_identity_v3.py
@@ -431,8 +431,7 @@ class V3IdentityPlugin(utils.TestCase):
{'status_code': 200, 'json': self.TEST_RESPONSE_DICT,
'headers': {'X-Subject-Token': 'token2'}}]
- self.requests.register_uri('POST', '%s/auth/tokens' % self.TEST_URL,
- auth_responses)
+ self.requests.post('%s/auth/tokens' % self.TEST_URL, auth_responses)
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
password=self.TEST_PASS)
diff --git a/keystoneclient/tests/auth/test_token_endpoint.py b/keystoneclient/tests/auth/test_token_endpoint.py
index a9028e3..fa64b39 100644
--- a/keystoneclient/tests/auth/test_token_endpoint.py
+++ b/keystoneclient/tests/auth/test_token_endpoint.py
@@ -23,7 +23,7 @@ class TokenEndpointTest(utils.TestCase):
TEST_URL = 'http://server/prefix'
def test_basic_case(self):
- self.requests.register_uri('GET', self.TEST_URL, text='body')
+ self.requests.get(self.TEST_URL, text='body')
a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN)
s = session.Session(auth=a)
@@ -53,3 +53,11 @@ class TokenEndpointTest(utils.TestCase):
self.assertIn('token', opt_names)
self.assertIn('endpoint', opt_names)
+
+ def test_token_endpoint_user_id(self):
+ a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN)
+ s = session.Session()
+
+ # we can't know this information about this sort of plugin
+ self.assertIsNone(a.get_user_id(s))
+ self.assertIsNone(a.get_project_id(s))
diff --git a/keystoneclient/tests/auth/utils.py b/keystoneclient/tests/auth/utils.py
index c3dae8f..cfca379 100644
--- a/keystoneclient/tests/auth/utils.py
+++ b/keystoneclient/tests/auth/utils.py
@@ -30,6 +30,8 @@ class MockPlugin(base.BaseAuthPlugin):
INT_DESC = 'test int'
FLOAT_DESC = 'test float'
BOOL_DESC = 'test bool'
+ STR_DESC = 'test str'
+ STR_DEFAULT = uuid.uuid4().hex
def __init__(self, **kwargs):
self._data = kwargs
@@ -49,6 +51,7 @@ class MockPlugin(base.BaseAuthPlugin):
cfg.IntOpt('a-int', default='3', help=cls.INT_DESC),
cfg.BoolOpt('a-bool', help=cls.BOOL_DESC),
cfg.FloatOpt('a-float', help=cls.FLOAT_DESC),
+ cfg.StrOpt('a-str', help=cls.STR_DESC, default=cls.STR_DEFAULT),
]
diff --git a/keystoneclient/tests/generic/test_client.py b/keystoneclient/tests/generic/test_client.py
index 0f25f41..e5f8736 100644
--- a/keystoneclient/tests/generic/test_client.py
+++ b/keystoneclient/tests/generic/test_client.py
@@ -56,8 +56,7 @@ EXTENSION_LIST = _create_extension_list([EXTENSION_FOO, EXTENSION_BAR])
class ClientDiscoveryTests(utils.TestCase):
def test_discover_extensions_v2(self):
- self.requests.register_uri('GET', "%s/extensions" % V2_URL,
- text=EXTENSION_LIST)
+ self.requests.get("%s/extensions" % V2_URL, text=EXTENSION_LIST)
extensions = client.Client().discover_extensions(url=V2_URL)
self.assertIn(EXTENSION_ALIAS_FOO, extensions)
self.assertEqual(extensions[EXTENSION_ALIAS_FOO], EXTENSION_NAME_FOO)
diff --git a/keystoneclient/tests/test_auth_token_middleware.py b/keystoneclient/tests/test_auth_token_middleware.py
index 4e70b73..d36fc48 100644
--- a/keystoneclient/tests/test_auth_token_middleware.py
+++ b/keystoneclient/tests/test_auth_token_middleware.py
@@ -28,6 +28,7 @@ import mock
from oslo.serialization import jsonutils
from oslo.utils import timeutils
from requests_mock.contrib import fixture as mock_fixture
+import six
from six.moves.urllib import parse as urlparse
import testresources
import testtools
@@ -133,6 +134,22 @@ class TimezoneFixture(fixtures.Fixture):
time.tzset()
+class TimeFixture(fixtures.Fixture):
+
+ def __init__(self, new_time, normalize=True):
+ super(TimeFixture, self).__init__()
+ if isinstance(new_time, six.string_types):
+ new_time = timeutils.parse_isotime(new_time)
+ if normalize:
+ new_time = timeutils.normalize_time(new_time)
+ self.new_time = new_time
+
+ def setUp(self):
+ super(TimeFixture, self).setUp()
+ timeutils.set_time_override(self.new_time)
+ self.addCleanup(timeutils.clear_time_override)
+
+
class FakeApp(object):
"""This represents a WSGI app protected by the auth_token middleware."""
@@ -258,13 +275,11 @@ class MultiStepAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
# Get a token, then try to retrieve revocation list and get a 401.
# Get a new token, try to retrieve revocation list and return 200.
- self.requests.register_uri('POST', "%s/v2.0/tokens" % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
+ self.requests.post("%s/v2.0/tokens" % BASE_URI, text=FAKE_ADMIN_TOKEN)
text = self.examples.SIGNED_REVOCATION_LIST
- self.requests.register_uri('GET', "%s/v2.0/tokens/revoked" % BASE_URI,
- response_list=[{'status_code': 401},
- {'text': text}])
+ self.requests.get("%s/v2.0/tokens/revoked" % BASE_URI,
+ response_list=[{'status_code': 401}, {'text': text}])
fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list())
self.assertEqual(fetched_list, self.examples.REVOCATION_LIST)
@@ -291,17 +306,17 @@ class DiabloAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
super(DiabloAuthTokenMiddlewareTest, self).setUp(
expected_env=expected_env)
- self.requests.register_uri('GET', "%s/" % BASE_URI,
- text=VERSION_LIST_v2, status_code=300)
+ self.requests.get("%s/" % BASE_URI,
+ text=VERSION_LIST_v2,
+ status_code=300)
- self.requests.register_uri('POST', "%s/v2.0/tokens" % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
+ self.requests.post("%s/v2.0/tokens" % BASE_URI, text=FAKE_ADMIN_TOKEN)
self.token_id = self.examples.VALID_DIABLO_TOKEN
token_response = self.examples.JSON_TOKEN_RESPONSES[self.token_id]
url = '%s/v2.0/tokens/%s' % (BASE_URI, self.token_id)
- self.requests.register_uri('GET', url, text=token_response)
+ self.requests.get(url, text=token_response)
self.set_middleware()
@@ -856,8 +871,7 @@ class CommonAuthTokenMiddlewareTest(object):
self.assertEqual(self.middleware.token_revocation_list, in_memory_list)
def test_invalid_revocation_list_raises_service_error(self):
- self.requests.register_uri('GET', '%s/v2.0/tokens/revoked' % BASE_URI,
- text='{}')
+ self.requests.get('%s/v2.0/tokens/revoked' % BASE_URI, text='{}')
self.assertRaises(auth_token.ServiceError,
self.middleware.fetch_revocation_list)
@@ -872,8 +886,7 @@ class CommonAuthTokenMiddlewareTest(object):
# remember because we are testing the middleware we stub the connection
# to the keystone server, but this is not what gets returned
invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI
- self.requests.register_uri('GET', invalid_uri, text="",
- status_code=404)
+ self.requests.get(invalid_uri, text="", status_code=404)
req = webob.Request.blank('/')
req.headers['X-Auth-Token'] = 'invalid-token'
@@ -961,7 +974,7 @@ class CommonAuthTokenMiddlewareTest(object):
def test_memcache_set_invalid_uuid(self):
invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI
- self.requests.register_uri('GET', invalid_uri, status_code=404)
+ self.requests.get(invalid_uri, status_code=404)
req = webob.Request.blank('/')
token = 'invalid-token'
@@ -1007,16 +1020,15 @@ class CommonAuthTokenMiddlewareTest(object):
token = self.token_dict['signed_token_scoped']
req.headers['X-Auth-Token'] = token
req.environ.update(extra_environ)
- timeutils_utcnow = 'oslo.utils.timeutils.utcnow'
+
now = datetime.datetime.utcnow()
- with mock.patch(timeutils_utcnow) as mock_utcnow:
- mock_utcnow.return_value = now
- self.middleware(req.environ, self.start_fake_response)
- self.assertIsNotNone(self._get_cached_token(token))
- expired = now + datetime.timedelta(seconds=token_cache_time)
- with mock.patch(timeutils_utcnow) as mock_utcnow:
- mock_utcnow.return_value = expired
- self.assertIsNone(self._get_cached_token(token))
+ self.useFixture(TimeFixture(now))
+
+ self.middleware(req.environ, self.start_fake_response)
+ self.assertIsNotNone(self._get_cached_token(token))
+
+ timeutils.advance_time_seconds(token_cache_time)
+ self.assertIsNone(self._get_cached_token(token))
def test_swift_memcache_set_expired(self):
extra_conf = {'cache': 'swift.cache'}
@@ -1255,10 +1267,10 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
def test_request_no_token_dummy(self):
cms._ensure_subprocess()
- self.requests.register_uri('GET', "%s%s" % (BASE_URI, self.ca_path),
- status_code=404)
+ self.requests.get("%s%s" % (BASE_URI, self.ca_path),
+ status_code=404)
url = "%s%s" % (BASE_URI, self.signing_path)
- self.requests.register_uri('GET', url, status_code=404)
+ self.requests.get(url, status_code=404)
self.assertRaises(exceptions.CertificateConfigError,
self.middleware.verify_signed_token,
self.examples.SIGNED_TOKEN_SCOPED,
@@ -1267,7 +1279,7 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
def test_fetch_signing_cert(self):
data = 'FAKE CERT'
url = '%s%s' % (BASE_URI, self.signing_path)
- self.requests.register_uri('GET', url, text=data)
+ self.requests.get(url, text=data)
self.middleware.fetch_signing_cert()
with open(self.middleware.signing_cert_file_name, 'r') as f:
@@ -1277,8 +1289,7 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
def test_fetch_signing_ca(self):
data = 'FAKE CA'
- self.requests.register_uri('GET', "%s%s" % (BASE_URI, self.ca_path),
- text=data)
+ self.requests.get("%s%s" % (BASE_URI, self.ca_path), text=data)
self.middleware.fetch_ca_cert()
with open(self.middleware.signing_ca_file_name, 'r') as f:
@@ -1293,11 +1304,10 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.conf['auth_port'] = 1234
self.conf['auth_admin_prefix'] = '/newadmin/'
- self.requests.register_uri('GET',
- "%s/newadmin%s" % (BASE_HOST, self.ca_path),
- text='FAKECA')
+ self.requests.get("%s/newadmin%s" % (BASE_HOST, self.ca_path),
+ text='FAKECA')
url = "%s/newadmin%s" % (BASE_HOST, self.signing_path)
- self.requests.register_uri('GET', url, text='FAKECERT')
+ self.requests.get(url, text='FAKECERT')
self.set_middleware(conf=self.conf)
@@ -1316,11 +1326,9 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.conf['auth_port'] = 1234
self.conf['auth_admin_prefix'] = ''
- self.requests.register_uri('GET', "%s%s" % (BASE_HOST, self.ca_path),
- text='FAKECA')
- self.requests.register_uri('GET', "%s%s" % (BASE_HOST,
- self.signing_path),
- text='FAKECERT')
+ self.requests.get("%s%s" % (BASE_HOST, self.ca_path), text='FAKECA')
+ self.requests.get("%s%s" % (BASE_HOST, self.signing_path),
+ text='FAKECERT')
self.set_middleware(conf=self.conf)
@@ -1392,14 +1400,15 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.examples.REVOKED_TOKEN_HASH_SHA256,
}
- self.requests.register_uri('GET', "%s/" % BASE_URI,
- text=VERSION_LIST_v2, status_code=300)
+ self.requests.get("%s/" % BASE_URI,
+ text=VERSION_LIST_v2,
+ status_code=300)
- self.requests.register_uri('POST', "%s/v2.0/tokens" % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
+ self.requests.post("%s/v2.0/tokens" % BASE_URI,
+ text=FAKE_ADMIN_TOKEN)
- self.requests.register_uri('GET', "%s/v2.0/tokens/revoked" % BASE_URI,
- text=self.examples.SIGNED_REVOCATION_LIST)
+ self.requests.get("%s/v2.0/tokens/revoked" % BASE_URI,
+ text=self.examples.SIGNED_REVOCATION_LIST)
for token in (self.examples.UUID_TOKEN_DEFAULT,
self.examples.UUID_TOKEN_UNSCOPED,
@@ -1409,14 +1418,11 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.examples.SIGNED_TOKEN_SCOPED_KEY,
self.examples.SIGNED_TOKEN_SCOPED_PKIZ_KEY,):
text = self.examples.JSON_TOKEN_RESPONSES[token]
- self.requests.register_uri('GET',
- '%s/v2.0/tokens/%s' % (BASE_URI, token),
- text=text)
+ self.requests.get('%s/v2.0/tokens/%s' % (BASE_URI, token),
+ text=text)
- self.requests.register_uri('GET',
- '%s/v2.0/tokens/%s' % (BASE_URI,
- ERROR_TOKEN),
- text=network_error_response)
+ self.requests.get('%s/v2.0/tokens/%s' % (BASE_URI, ERROR_TOKEN),
+ text=network_error_response)
self.set_middleware()
@@ -1492,16 +1498,16 @@ class CrossVersionAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
'auth_version': 'v2.0'
}
- self.requests.register_uri('GET', '%s/' % BASE_URI,
- text=VERSION_LIST_v3, status_code=300)
+ self.requests.get('%s/' % BASE_URI,
+ text=VERSION_LIST_v3,
+ status_code=300)
- self.requests.register_uri('POST', '%s/v2.0/tokens' % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
+ self.requests.post('%s/v2.0/tokens' % BASE_URI, text=FAKE_ADMIN_TOKEN)
token = self.examples.UUID_TOKEN_DEFAULT
url = '%s/v2.0/tokens/%s' % (BASE_URI, token)
response_body = self.examples.JSON_TOKEN_RESPONSES[token]
- self.requests.register_uri('GET', url, text=response_body)
+ self.requests.get(url, text=response_body)
self.set_middleware(conf=conf)
@@ -1573,20 +1579,18 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.examples.REVOKED_v3_PKIZ_TOKEN_HASH,
}
- self.requests.register_uri('GET', BASE_URI,
- text=VERSION_LIST_v3, status_code=300)
+ self.requests.get(BASE_URI, text=VERSION_LIST_v3, status_code=300)
# TODO(jamielennox): auth_token middleware uses a v2 admin token
# regardless of the auth_version that is set.
- self.requests.register_uri('POST', '%s/v2.0/tokens' % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
+ self.requests.post('%s/v2.0/tokens' % BASE_URI, text=FAKE_ADMIN_TOKEN)
# TODO(jamielennox): there is no v3 revocation url yet, it uses v2
- self.requests.register_uri('GET', '%s/v2.0/tokens/revoked' % BASE_URI,
- text=self.examples.SIGNED_REVOCATION_LIST)
+ self.requests.get('%s/v2.0/tokens/revoked' % BASE_URI,
+ text=self.examples.SIGNED_REVOCATION_LIST)
- self.requests.register_uri('GET', '%s/v3/auth/tokens' % BASE_URI,
- text=self.token_response)
+ self.requests.get('%s/v3/auth/tokens' % BASE_URI,
+ text=self.token_response)
self.set_middleware()
@@ -1759,22 +1763,16 @@ class TokenExpirationTest(BaseAuthTokenMiddlewareTest):
auth_token.confirm_token_not_expired,
data)
- @mock.patch('oslo.utils.timeutils.utcnow')
- def test_v2_token_with_timezone_offset_not_expired(self, mock_utcnow):
- current_time = timeutils.parse_isotime('2000-01-01T00:01:10.000123Z')
- current_time = timeutils.normalize_time(current_time)
- mock_utcnow.return_value = current_time
+ def test_v2_token_with_timezone_offset_not_expired(self):
+ self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z'))
data = self.create_v2_token_fixture(
expires='2000-01-01T00:05:10.000123-05:00')
expected_expires = '2000-01-01T05:05:10.000123Z'
actual_expires = auth_token.confirm_token_not_expired(data)
self.assertEqual(actual_expires, expected_expires)
- @mock.patch('oslo.utils.timeutils.utcnow')
- def test_v2_token_with_timezone_offset_expired(self, mock_utcnow):
- current_time = timeutils.parse_isotime('2000-01-01T00:01:10.000123Z')
- current_time = timeutils.normalize_time(current_time)
- mock_utcnow.return_value = current_time
+ def test_v2_token_with_timezone_offset_expired(self):
+ self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z'))
data = self.create_v2_token_fixture(
expires='2000-01-01T00:05:10.000123+05:00')
data['access']['token']['expires'] = '2000-01-01T00:05:10.000123+05:00'
@@ -1794,11 +1792,8 @@ class TokenExpirationTest(BaseAuthTokenMiddlewareTest):
auth_token.confirm_token_not_expired,
data)
- @mock.patch('oslo.utils.timeutils.utcnow')
- def test_v3_token_with_timezone_offset_not_expired(self, mock_utcnow):
- current_time = timeutils.parse_isotime('2000-01-01T00:01:10.000123Z')
- current_time = timeutils.normalize_time(current_time)
- mock_utcnow.return_value = current_time
+ def test_v3_token_with_timezone_offset_not_expired(self):
+ self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z'))
data = self.create_v3_token_fixture(
expires='2000-01-01T00:05:10.000123-05:00')
expected_expires = '2000-01-01T05:05:10.000123Z'
@@ -1806,11 +1801,8 @@ class TokenExpirationTest(BaseAuthTokenMiddlewareTest):
actual_expires = auth_token.confirm_token_not_expired(data)
self.assertEqual(actual_expires, expected_expires)
- @mock.patch('oslo.utils.timeutils.utcnow')
- def test_v3_token_with_timezone_offset_expired(self, mock_utcnow):
- current_time = timeutils.parse_isotime('2000-01-01T00:01:10.000123Z')
- current_time = timeutils.normalize_time(current_time)
- mock_utcnow.return_value = current_time
+ def test_v3_token_with_timezone_offset_expired(self):
+ self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z'))
data = self.create_v3_token_fixture(
expires='2000-01-01T00:05:10.000123+05:00')
self.assertRaises(auth_token.InvalidUserToken,
diff --git a/keystoneclient/tests/test_discovery.py b/keystoneclient/tests/test_discovery.py
index a999a19..f9d3df2 100644
--- a/keystoneclient/tests/test_discovery.py
+++ b/keystoneclient/tests/test_discovery.py
@@ -242,7 +242,7 @@ class AvailableVersionsTests(utils.TestCase):
for path, text in six.iteritems(examples):
url = "%s%s" % (BASE_URL, path)
- self.requests.register_uri('GET', url, status_code=300, text=text)
+ self.requests.get(url, status_code=300, text=text)
versions = discover.available_versions(url)
for v in versions:
@@ -252,8 +252,7 @@ class AvailableVersionsTests(utils.TestCase):
matchers.Contains(n)))
def test_available_versions_individual(self):
- self.requests.register_uri('GET', V3_URL, status_code=200,
- text=V3_VERSION_ENTRY)
+ self.requests.get(V3_URL, status_code=200, text=V3_VERSION_ENTRY)
versions = discover.available_versions(V3_URL)
@@ -264,8 +263,7 @@ class AvailableVersionsTests(utils.TestCase):
self.assertIn('links', v)
def test_available_keystone_data(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
versions = discover.available_versions(BASE_URL)
self.assertEqual(2, len(versions))
@@ -280,7 +278,7 @@ class AvailableVersionsTests(utils.TestCase):
def test_available_cinder_data(self):
text = jsonutils.dumps(CINDER_EXAMPLES)
- self.requests.register_uri('GET', BASE_URL, status_code=300, text=text)
+ self.requests.get(BASE_URL, status_code=300, text=text)
versions = discover.available_versions(BASE_URL)
self.assertEqual(2, len(versions))
@@ -296,7 +294,7 @@ class AvailableVersionsTests(utils.TestCase):
def test_available_glance_data(self):
text = jsonutils.dumps(GLANCE_EXAMPLES)
- self.requests.register_uri('GET', BASE_URL, status_code=200, text=text)
+ self.requests.get(BASE_URL, status_code=200, text=text)
versions = discover.available_versions(BASE_URL)
self.assertEqual(5, len(versions))
@@ -313,10 +311,9 @@ class AvailableVersionsTests(utils.TestCase):
class ClientDiscoveryTests(utils.TestCase):
def assertCreatesV3(self, **kwargs):
- self.requests.register_uri('POST',
- '%s/auth/tokens' % V3_URL,
- text=V3_AUTH_RESPONSE,
- headers={'X-Subject-Token': V3_TOKEN})
+ self.requests.post('%s/auth/tokens' % V3_URL,
+ text=V3_AUTH_RESPONSE,
+ headers={'X-Subject-Token': V3_TOKEN})
kwargs.setdefault('username', 'foo')
kwargs.setdefault('password', 'bar')
@@ -325,8 +322,7 @@ class ClientDiscoveryTests(utils.TestCase):
return keystone
def assertCreatesV2(self, **kwargs):
- self.requests.register_uri('POST', "%s/tokens" % V2_URL,
- text=V2_AUTH_RESPONSE)
+ self.requests.post("%s/tokens" % V2_URL, text=V2_AUTH_RESPONSE)
kwargs.setdefault('username', 'foo')
kwargs.setdefault('password', 'bar')
@@ -349,89 +345,73 @@ class ClientDiscoveryTests(utils.TestCase):
client.Client, **kwargs)
def test_discover_v3(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
self.assertCreatesV3(auth_url=BASE_URL)
def test_discover_v2(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V2_VERSION_LIST)
- self.requests.register_uri('POST', "%s/tokens" % V2_URL,
- text=V2_AUTH_RESPONSE)
+ self.requests.get(BASE_URL, status_code=300, text=V2_VERSION_LIST)
+ self.requests.post("%s/tokens" % V2_URL, text=V2_AUTH_RESPONSE)
self.assertCreatesV2(auth_url=BASE_URL)
def test_discover_endpoint_v2(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V2_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V2_VERSION_LIST)
self.assertCreatesV2(endpoint=BASE_URL, token='fake-token')
def test_discover_endpoint_v3(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
self.assertCreatesV3(endpoint=BASE_URL, token='fake-token')
def test_discover_invalid_major_version(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
self.assertVersionNotAvailable(auth_url=BASE_URL, version=5)
def test_discover_200_response_fails(self):
- self.requests.register_uri('GET', BASE_URL,
- status_code=200, text='ok')
+ self.requests.get(BASE_URL, text='ok')
self.assertDiscoveryFailure(auth_url=BASE_URL)
def test_discover_minor_greater_than_available_fails(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
self.assertVersionNotAvailable(endpoint=BASE_URL, version=3.4)
def test_discover_individual_version_v2(self):
- self.requests.register_uri('GET', V2_URL, status_code=200,
- text=V2_VERSION_ENTRY)
+ self.requests.get(V2_URL, text=V2_VERSION_ENTRY)
self.assertCreatesV2(auth_url=V2_URL)
def test_discover_individual_version_v3(self):
- self.requests.register_uri('GET', V3_URL, status_code=200,
- text=V3_VERSION_ENTRY)
+ self.requests.get(V3_URL, text=V3_VERSION_ENTRY)
self.assertCreatesV3(auth_url=V3_URL)
def test_discover_individual_endpoint_v2(self):
- self.requests.register_uri('GET', V2_URL, status_code=200,
- text=V2_VERSION_ENTRY)
+ self.requests.get(V2_URL, text=V2_VERSION_ENTRY)
self.assertCreatesV2(endpoint=V2_URL, token='fake-token')
def test_discover_individual_endpoint_v3(self):
- self.requests.register_uri('GET', V3_URL, status_code=200,
- text=V3_VERSION_ENTRY)
+ self.requests.get(V3_URL, text=V3_VERSION_ENTRY)
self.assertCreatesV3(endpoint=V3_URL, token='fake-token')
def test_discover_fail_to_create_bad_individual_version(self):
- self.requests.register_uri('GET', V2_URL, status_code=200,
- text=V2_VERSION_ENTRY)
- self.requests.register_uri('GET', V3_URL, status_code=200,
- text=V3_VERSION_ENTRY)
+ self.requests.get(V2_URL, text=V2_VERSION_ENTRY)
+ self.requests.get(V3_URL, text=V3_VERSION_ENTRY)
self.assertVersionNotAvailable(auth_url=V2_URL, version=3)
self.assertVersionNotAvailable(auth_url=V3_URL, version=2)
def test_discover_unstable_versions(self):
version_list = fixture.DiscoveryList(BASE_URL, v3_status='beta')
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- json=version_list)
+ self.requests.get(BASE_URL, status_code=300, json=version_list)
self.assertCreatesV2(auth_url=BASE_URL)
self.assertVersionNotAvailable(auth_url=BASE_URL, version=3)
self.assertCreatesV3(auth_url=BASE_URL, unstable=True)
def test_discover_forwards_original_ip(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
ip = '192.168.1.1'
self.assertCreatesV3(auth_url=BASE_URL, original_ip=ip)
@@ -444,8 +424,7 @@ class ClientDiscoveryTests(utils.TestCase):
client.Client)
def test_discover_bad_response(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- json={'FOO': 'BAR'})
+ self.requests.get(BASE_URL, status_code=300, json={'FOO': 'BAR'})
self.assertDiscoveryFailure(auth_url=BASE_URL)
def test_discovery_ignore_invalid(self):
@@ -454,44 +433,40 @@ class ClientDiscoveryTests(utils.TestCase):
'media-types': V3_MEDIA_TYPES,
'status': 'stable',
'updated': UPDATED}]
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=_create_version_list(resp))
+ self.requests.get(BASE_URL, status_code=300,
+ text=_create_version_list(resp))
self.assertDiscoveryFailure(auth_url=BASE_URL)
def test_ignore_entry_without_links(self):
v3 = V3_VERSION.copy()
v3['links'] = []
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=_create_version_list([v3, V2_VERSION]))
+ self.requests.get(BASE_URL, status_code=300,
+ text=_create_version_list([v3, V2_VERSION]))
self.assertCreatesV2(auth_url=BASE_URL)
def test_ignore_entry_without_status(self):
v3 = V3_VERSION.copy()
del v3['status']
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=_create_version_list([v3, V2_VERSION]))
+ self.requests.get(BASE_URL, status_code=300,
+ text=_create_version_list([v3, V2_VERSION]))
self.assertCreatesV2(auth_url=BASE_URL)
def test_greater_version_than_required(self):
versions = fixture.DiscoveryList(BASE_URL, v3_id='v3.6')
- self.requests.register_uri('GET', BASE_URL, status_code=200,
- json=versions)
+ self.requests.get(BASE_URL, json=versions)
self.assertCreatesV3(auth_url=BASE_URL, version=(3, 4))
def test_lesser_version_than_required(self):
versions = fixture.DiscoveryList(BASE_URL, v3_id='v3.4')
- self.requests.register_uri('GET', BASE_URL, status_code=200,
- json=versions)
+ self.requests.get(BASE_URL, json=versions)
self.assertVersionNotAvailable(auth_url=BASE_URL, version=(3, 6))
def test_bad_response(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text="Ugly Duckling")
+ self.requests.get(BASE_URL, status_code=300, text="Ugly Duckling")
self.assertDiscoveryFailure(auth_url=BASE_URL)
def test_pass_client_arguments(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V2_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V2_VERSION_LIST)
kwargs = {'original_ip': '100', 'use_keyring': False,
'stale_duration': 15}
@@ -502,12 +477,11 @@ class ClientDiscoveryTests(utils.TestCase):
self.assertFalse(cl.use_keyring)
def test_overriding_stored_kwargs(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
- self.requests.register_uri('POST', "%s/auth/tokens" % V3_URL,
- text=V3_AUTH_RESPONSE,
- headers={'X-Subject-Token': V3_TOKEN})
+ self.requests.post("%s/auth/tokens" % V3_URL,
+ text=V3_AUTH_RESPONSE,
+ headers={'X-Subject-Token': V3_TOKEN})
disc = discover.Discover(auth_url=BASE_URL, debug=False,
username='foo')
@@ -520,8 +494,7 @@ class ClientDiscoveryTests(utils.TestCase):
self.assertEqual(client.password, 'bar')
def test_available_versions(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_ENTRY)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_ENTRY)
disc = discover.Discover(auth_url=BASE_URL)
versions = disc.available_versions()
@@ -536,8 +509,7 @@ class ClientDiscoveryTests(utils.TestCase):
'updated': UPDATED}
versions = fixture.DiscoveryList()
versions.add_version(V4_VERSION)
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- json=versions)
+ self.requests.get(BASE_URL, status_code=300, json=versions)
disc = discover.Discover(auth_url=BASE_URL)
self.assertRaises(exceptions.DiscoveryFailure,
@@ -545,16 +517,14 @@ class ClientDiscoveryTests(utils.TestCase):
def test_discovery_fail_for_missing_v3(self):
versions = fixture.DiscoveryList(v2=True, v3=False)
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- json=versions)
+ self.requests.get(BASE_URL, status_code=300, json=versions)
disc = discover.Discover(auth_url=BASE_URL)
self.assertRaises(exceptions.DiscoveryFailure,
disc.create_client, version=(3, 0))
def _do_discovery_call(self, token=None, **kwargs):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
if not token:
token = uuid.uuid4().hex
@@ -581,8 +551,7 @@ class ClientDiscoveryTests(utils.TestCase):
class DiscoverQueryTests(utils.TestCase):
def test_available_keystone_data(self):
- self.requests.register_uri('GET', BASE_URL, status_code=300,
- text=V3_VERSION_LIST)
+ self.requests.get(BASE_URL, status_code=300, text=V3_VERSION_LIST)
disc = discover.Discover(auth_url=BASE_URL)
versions = disc.version_data()
@@ -610,7 +579,7 @@ class DiscoverQueryTests(utils.TestCase):
def test_available_cinder_data(self):
text = jsonutils.dumps(CINDER_EXAMPLES)
- self.requests.register_uri('GET', BASE_URL, status_code=300, text=text)
+ self.requests.get(BASE_URL, status_code=300, text=text)
v1_url = "%sv1/" % BASE_URL
v2_url = "%sv2/" % BASE_URL
@@ -641,7 +610,7 @@ class DiscoverQueryTests(utils.TestCase):
def test_available_glance_data(self):
text = jsonutils.dumps(GLANCE_EXAMPLES)
- self.requests.register_uri('GET', BASE_URL, status_code=200, text=text)
+ self.requests.get(BASE_URL, text=text)
v1_url = "%sv1/" % BASE_URL
v2_url = "%sv2/" % BASE_URL
@@ -690,7 +659,7 @@ class DiscoverQueryTests(utils.TestCase):
'status': status,
'updated': UPDATED}]
text = jsonutils.dumps({'versions': version_list})
- self.requests.register_uri('GET', BASE_URL, status_code=200, text=text)
+ self.requests.get(BASE_URL, text=text)
disc = discover.Discover(auth_url=BASE_URL)
@@ -712,7 +681,7 @@ class DiscoverQueryTests(utils.TestCase):
'status': status,
'updated': UPDATED}]
text = jsonutils.dumps({'versions': version_list})
- self.requests.register_uri('GET', BASE_URL, status_code=200, text=text)
+ self.requests.get(BASE_URL, text=text)
disc = discover.Discover(auth_url=BASE_URL)
@@ -729,8 +698,7 @@ class DiscoverQueryTests(utils.TestCase):
status = 'abcdef'
version_list = fixture.DiscoveryList(BASE_URL, v2=False,
v3_status=status)
- self.requests.register_uri('GET', BASE_URL, status_code=200,
- json=version_list)
+ self.requests.get(BASE_URL, json=version_list)
disc = discover.Discover(auth_url=BASE_URL)
versions = disc.version_data()
@@ -759,8 +727,7 @@ class DiscoverQueryTests(utils.TestCase):
}]
text = jsonutils.dumps({'versions': version_list})
- self.requests.register_uri('GET', BASE_URL, status_code=200,
- text=text)
+ self.requests.get(BASE_URL, text=text)
disc = discover.Discover(auth_url=BASE_URL)
diff --git a/keystoneclient/tests/test_s3_token_middleware.py b/keystoneclient/tests/test_s3_token_middleware.py
index ab77b79..25fc29e 100644
--- a/keystoneclient/tests/test_s3_token_middleware.py
+++ b/keystoneclient/tests/test_s3_token_middleware.py
@@ -64,8 +64,7 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
super(S3TokenMiddlewareTestGood, self).setUp()
self.middleware = s3_token.S3Token(FakeApp(), self.conf)
- self.requests.register_uri('POST', self.TEST_URL,
- status_code=201, json=GOOD_RESPONSE)
+ self.requests.post(self.TEST_URL, status_code=201, json=GOOD_RESPONSE)
# Ignore the request and pass to the next middleware in the
# pipeline if no path has been specified.
@@ -99,8 +98,7 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
TEST_URL = 'http://%s:%d/v2.0/s3tokens' % (self.TEST_HOST,
self.TEST_PORT)
- self.requests.register_uri('POST', TEST_URL,
- status_code=201, json=GOOD_RESPONSE)
+ self.requests.post(TEST_URL, status_code=201, json=GOOD_RESPONSE)
self.middleware = (
s3_token.filter_factory({'auth_protocol': 'http',
@@ -153,8 +151,7 @@ class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase):
{"message": "EC2 access key not found.",
"code": 401,
"title": "Unauthorized"}}
- self.requests.register_uri('POST', self.TEST_URL,
- status_code=403, json=ret)
+ self.requests.post(self.TEST_URL, status_code=403, json=ret)
req = webob.Request.blank('/v1/AUTH_cfa/c/o')
req.headers['Authorization'] = 'access:signature'
req.headers['X-Storage-Token'] = 'token'
@@ -186,8 +183,7 @@ class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase):
self.assertEqual(resp.status_int, s3_invalid_req.status_int)
def test_bad_reply(self):
- self.requests.register_uri('POST', self.TEST_URL,
- status_code=201, text="<badreply>")
+ self.requests.post(self.TEST_URL, status_code=201, text="<badreply>")
req = webob.Request.blank('/v1/AUTH_cfa/c/o')
req.headers['Authorization'] = 'access:signature'
diff --git a/keystoneclient/tests/test_session.py b/keystoneclient/tests/test_session.py
index 8aa5a1e..d3d964c 100644
--- a/keystoneclient/tests/test_session.py
+++ b/keystoneclient/tests/test_session.py
@@ -321,6 +321,8 @@ class AuthPlugin(base.BaseAuthPlugin):
"""
TEST_TOKEN = 'aToken'
+ TEST_USER_ID = 'aUser'
+ TEST_PROJECT_ID = 'aProject'
SERVICE_URLS = {
'identity': {'public': 'http://identity-public:1111/v2.0',
@@ -348,6 +350,12 @@ class AuthPlugin(base.BaseAuthPlugin):
def invalidate(self):
return self._invalidate
+ def get_user_id(self, session):
+ return self.TEST_USER_ID
+
+ def get_project_id(self, session):
+ return self.TEST_PROJECT_ID
+
class CalledAuthPlugin(base.BaseAuthPlugin):
@@ -447,7 +455,7 @@ class SessionAuthTests(utils.TestCase):
def test_raises_exc_only_when_asked(self):
# A request that returns a HTTP error should by default raise an
# exception by default, if you specify raise_exc=False then it will not
- self.requests.register_uri('GET', self.TEST_URL, status_code=401)
+ self.requests.get(self.TEST_URL, status_code=401)
sess = client_session.Session()
self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL)
@@ -459,9 +467,8 @@ class SessionAuthTests(utils.TestCase):
passed = CalledAuthPlugin()
sess = client_session.Session()
- self.requests.register_uri('GET',
- CalledAuthPlugin.ENDPOINT + 'path',
- status_code=200)
+ self.requests.get(CalledAuthPlugin.ENDPOINT + 'path',
+ status_code=200)
endpoint_filter = {'service_type': 'identity'}
# no plugin with authenticated won't work
@@ -484,9 +491,8 @@ class SessionAuthTests(utils.TestCase):
sess = client_session.Session(fixed)
- self.requests.register_uri('GET',
- CalledAuthPlugin.ENDPOINT + 'path',
- status_code=200)
+ self.requests.get(CalledAuthPlugin.ENDPOINT + 'path',
+ status_code=200)
resp = sess.get('path', auth=passed,
endpoint_filter={'service_type': 'identity'})
@@ -518,9 +524,9 @@ class SessionAuthTests(utils.TestCase):
auth = CalledAuthPlugin(invalidate=True)
sess = client_session.Session(auth=auth)
- self.requests.register_uri('GET', self.TEST_URL,
- [{'text': 'Failed', 'status_code': 401},
- {'text': 'Hello', 'status_code': 200}])
+ self.requests.get(self.TEST_URL,
+ [{'text': 'Failed', 'status_code': 401},
+ {'text': 'Hello', 'status_code': 200}])
# allow_reauth=True is the default
resp = sess.get(self.TEST_URL, authenticated=True)
@@ -533,9 +539,9 @@ class SessionAuthTests(utils.TestCase):
auth = CalledAuthPlugin(invalidate=True)
sess = client_session.Session(auth=auth)
- self.requests.register_uri('GET', self.TEST_URL,
- [{'text': 'Failed', 'status_code': 401},
- {'text': 'Hello', 'status_code': 200}])
+ self.requests.get(self.TEST_URL,
+ [{'text': 'Failed', 'status_code': 401},
+ {'text': 'Hello', 'status_code': 200}])
self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL,
authenticated=True, allow_reauth=False)
@@ -550,7 +556,7 @@ class SessionAuthTests(utils.TestCase):
override_url = override_base + path
resp_text = uuid.uuid4().hex
- self.requests.register_uri('GET', override_url, text=resp_text)
+ self.requests.get(override_url, text=resp_text)
resp = sess.get(path,
endpoint_override=override_base,
@@ -570,7 +576,7 @@ class SessionAuthTests(utils.TestCase):
url = self.TEST_URL + path
resp_text = uuid.uuid4().hex
- self.requests.register_uri('GET', url, text=resp_text)
+ self.requests.get(url, text=resp_text)
resp = sess.get(url,
endpoint_override='http://someother.url',
@@ -582,6 +588,13 @@ class SessionAuthTests(utils.TestCase):
self.assertTrue(auth.get_token_called)
self.assertFalse(auth.get_endpoint_called)
+ def test_user_and_project_id(self):
+ auth = AuthPlugin()
+ sess = client_session.Session(auth=auth)
+
+ self.assertEqual(auth.TEST_USER_ID, sess.get_user_id())
+ self.assertEqual(auth.TEST_PROJECT_ID, sess.get_project_id())
+
class AdapterTest(utils.TestCase):
@@ -692,13 +705,15 @@ class AdapterTest(utils.TestCase):
adpt = adapter.Adapter(sess, endpoint_override=endpoint_override)
response = uuid.uuid4().hex
- self.requests.register_uri('GET', endpoint_url, text=response)
+ self.requests.get(endpoint_url, text=response)
resp = adpt.get(path)
self.assertEqual(response, resp.text)
self.assertEqual(endpoint_url, self.requests.last_request.url)
+ self.assertEqual(endpoint_override, adpt.get_endpoint())
+
def test_adapter_invalidate(self):
auth = CalledAuthPlugin()
sess = client_session.Session()
@@ -735,6 +750,14 @@ class AdapterTest(utils.TestCase):
self.assertThat(self.requests.request_history,
matchers.HasLength(retries + 1))
+ def test_user_and_project_id(self):
+ auth = AuthPlugin()
+ sess = client_session.Session()
+ adpt = adapter.Adapter(sess, auth=auth)
+
+ self.assertEqual(auth.TEST_USER_ID, adpt.get_user_id())
+ self.assertEqual(auth.TEST_PROJECT_ID, adpt.get_project_id())
+
class ConfLoadingTests(utils.TestCase):
diff --git a/keystoneclient/tests/test_shell.py b/keystoneclient/tests/test_shell.py
index 4be563b..65cba9d 100644
--- a/keystoneclient/tests/test_shell.py
+++ b/keystoneclient/tests/test_shell.py
@@ -37,6 +37,11 @@ DEFAULT_TENANT_NAME = 'tenant_name'
DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/'
+# Make a fake shell object, a helping wrapper to call it
+def shell(cmd):
+ openstack_shell.OpenStackIdentityShell().main(cmd.split())
+
+
class NoExitArgumentParser(argparse.ArgumentParser):
def error(self, message):
raise exceptions.CommandError(message)
@@ -68,12 +73,6 @@ class ShellTest(utils.TestCase):
self.useFixture(fixtures.EnvironmentVariable(var,
self.FAKE_ENV[var]))
- # Make a fake shell object, a helping wrapper to call it, and a quick
- # way of asserting that certain API calls were made.
- global shell, _shell, assert_called, assert_called_anytime
- _shell = openstack_shell.OpenStackIdentityShell()
- shell = lambda cmd: _shell.main(cmd.split())
-
def test_help_unknown_command(self):
self.assertRaises(exceptions.CommandError, shell, 'help %s'
% uuid.uuid4().hex)
diff --git a/keystoneclient/tests/v2_0/test_certificates.py b/keystoneclient/tests/v2_0/test_certificates.py
new file mode 100644
index 0000000..432a304
--- /dev/null
+++ b/keystoneclient/tests/v2_0/test_certificates.py
@@ -0,0 +1,40 @@
+# Copyright 2014 IBM Corp.
+# 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.
+
+import testresources
+
+from keystoneclient.tests import client_fixtures
+from keystoneclient.tests.v2_0 import utils
+
+
+class CertificateTests(utils.TestCase, testresources.ResourcedTestCase):
+
+ resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
+
+ def test_get_ca_certificate(self):
+ self.stub_url('GET', ['certificates', 'ca'],
+ headers={'Content-Type': 'text/html; charset=UTF-8'},
+ text=self.examples.SIGNING_CA)
+ res = self.client.certificates.get_ca_certificate()
+ self.assertEqual(self.examples.SIGNING_CA, res)
+
+ def test_get_signing_certificate(self):
+ self.stub_url('GET', ['certificates', 'signing'],
+ headers={'Content-Type': 'text/html; charset=UTF-8'},
+ text=self.examples.SIGNING_CERT)
+ res = self.client.certificates.get_signing_certificate()
+ self.assertEqual(self.examples.SIGNING_CERT, res)
+
+
+def load_tests(loader, tests, pattern):
+ return testresources.OptimisingTestSuite(tests)
diff --git a/keystoneclient/tests/v2_0/test_client.py b/keystoneclient/tests/v2_0/test_client.py
index 5fbedf4..d09f326 100644
--- a/keystoneclient/tests/v2_0/test_client.py
+++ b/keystoneclient/tests/v2_0/test_client.py
@@ -27,7 +27,8 @@ from keystoneclient.v2_0 import client
class KeystoneClientTest(utils.TestCase):
def test_unscoped_init(self):
- self.stub_auth(json=client_fixtures.unscoped_token())
+ token = client_fixtures.unscoped_token()
+ self.stub_auth(json=token)
c = client.Client(username='exampleuser',
password='password',
@@ -38,9 +39,12 @@ class KeystoneClientTest(utils.TestCase):
self.assertFalse(c.auth_ref.project_scoped)
self.assertIsNone(c.auth_ref.trust_id)
self.assertFalse(c.auth_ref.trust_scoped)
+ self.assertIsNone(c.get_project_id(session=None))
+ self.assertEqual(token.user_id, c.get_user_id(session=None))
def test_scoped_init(self):
- self.stub_auth(json=client_fixtures.project_scoped_token())
+ token = client_fixtures.project_scoped_token()
+ self.stub_auth(json=token)
c = client.Client(username='exampleuser',
password='password',
@@ -53,6 +57,9 @@ class KeystoneClientTest(utils.TestCase):
self.assertIsNone(c.auth_ref.trust_id)
self.assertFalse(c.auth_ref.trust_scoped)
+ self.assertEqual(token.tenant_id, c.get_project_id(session=None))
+ self.assertEqual(token.user_id, c.get_user_id(session=None))
+
def test_auth_ref_load(self):
self.stub_auth(json=client_fixtures.project_scoped_token())
diff --git a/keystoneclient/tests/v2_0/test_shell.py b/keystoneclient/tests/v2_0/test_shell.py
index 57bbe9d..44943a0 100644
--- a/keystoneclient/tests/v2_0/test_shell.py
+++ b/keystoneclient/tests/v2_0/test_shell.py
@@ -14,6 +14,7 @@ import os
import sys
import mock
+from oslo.serialization import jsonutils
import six
from testtools import matchers
@@ -268,16 +269,27 @@ class ShellTests(utils.TestCase):
self.run_command('tenant-delete 2')
self.assert_called('DELETE', '/tenants/2')
- def test_service_create(self):
+ def test_service_create_with_required_arguments_only(self):
self.stub_url('POST', ['OS-KSADM', 'services'],
json={'OS-KSADM:service': {}})
- self.run_command('service-create --name service1 --type compute')
+ self.run_command('service-create --type compute')
self.assert_called('POST', '/OS-KSADM/services')
json = {"OS-KSADM:service": {"type": "compute",
- "name": "service1",
+ "name": None,
"description": None}}
self.assertRequestBodyIs(json=json)
+ def test_service_create_with_all_arguments(self):
+ self.stub_url('POST', ['OS-KSADM', 'services'],
+ json={'OS-KSADM:service': {}})
+ self.run_command('service-create --type compute '
+ '--name service1 --description desc1')
+ self.assert_called('POST', '/OS-KSADM/services')
+ json = {"OS-KSADM:service": {"type": "compute",
+ "name": "service1",
+ "description": "desc1"}}
+ self.assertRequestBodyIs(json=json)
+
def test_service_get(self):
self.stub_url('GET', ['OS-KSADM', 'services', '1'],
json={'OS-KSADM:service': {'id': '1'}})
@@ -381,22 +393,21 @@ class ShellTests(utils.TestCase):
' --tenant-name new-tenant')
def called_anytime(method, path, json=None):
+ test_url = self.TEST_URL.strip('/')
for r in self.requests.request_history:
if not r.method == method:
continue
- if not r.url == self.TEST_URL + path:
+ if not r.url == test_url + path:
continue
if json:
- last_request_body = r.body.decode('utf-8')
- json_body = jsonutils.loads(last_request_body)
-
+ json_body = jsonutils.loads(r.body)
if not json_body == json:
continue
return True
- return False
+ raise AssertionError('URL never called')
called_anytime('POST', '/users', {'user': {'email': None,
'password': '1',
@@ -409,7 +420,7 @@ class ShellTests(utils.TestCase):
"description": None}})
called_anytime('POST', '/OS-KSADM/roles',
- {"role": {"name": "new-role"}})
+ {"role": {"name": "admin"}})
called_anytime('PUT', '/tenants/1/users/1/roles/OS-KSADM/1')
diff --git a/keystoneclient/tests/v2_0/test_tokens.py b/keystoneclient/tests/v2_0/test_tokens.py
index 688972b..3351273 100644
--- a/keystoneclient/tests/v2_0/test_tokens.py
+++ b/keystoneclient/tests/v2_0/test_tokens.py
@@ -160,3 +160,10 @@ class TokenTests(utils.TestCase):
self.assertIsInstance(token_ref, tokens.Token)
self.assertEqual(token_fixture.token_id, token_ref.id)
self.assertEqual(token_fixture.expires_str, token_ref.expires)
+
+ def test_get_revoked(self):
+ sample_revoked_response = {'signed': '-----BEGIN CMS-----\nMIIB...'}
+ self.stub_url('GET', ['tokens', 'revoked'],
+ json=sample_revoked_response)
+ resp = self.client.tokens.get_revoked()
+ self.assertEqual(sample_revoked_response, resp)
diff --git a/keystoneclient/tests/v3/test_auth_saml2.py b/keystoneclient/tests/v3/test_auth_saml2.py
index bdb7a87..f9a0776 100644
--- a/keystoneclient/tests/v3/test_auth_saml2.py
+++ b/keystoneclient/tests/v3/test_auth_saml2.py
@@ -128,8 +128,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
def test_initial_sp_call(self):
"""Test initial call, expect SOAP message."""
- self.requests.register_uri(
- 'GET',
+ self.requests.get(
self.FEDERATION_AUTH_URL,
content=make_oneline(saml2_fixtures.SP_SOAP_RESPONSE))
a = self.saml2plugin._send_service_provider_request(self.session)
@@ -154,8 +153,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
str(self.saml2plugin.sp_response_consumer_url)))
def test_initial_sp_call_when_saml_authenticated(self):
- self.requests.register_uri(
- 'GET',
+ self.requests.get(
self.FEDERATION_AUTH_URL,
json=saml2_fixtures.UNSCOPED_TOKEN,
headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER})
@@ -170,8 +168,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.saml2plugin.authenticated_response.headers['X-Subject-Token'])
def test_get_unscoped_token_when_authenticated(self):
- self.requests.register_uri(
- 'GET',
+ self.requests.get(
self.FEDERATION_AUTH_URL,
json=saml2_fixtures.UNSCOPED_TOKEN,
headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER,
@@ -184,9 +181,8 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
def test_initial_sp_call_invalid_response(self):
"""Send initial SP HTTP request and receive wrong server response."""
- self.requests.register_uri('GET',
- self.FEDERATION_AUTH_URL,
- text='NON XML RESPONSE')
+ self.requests.get(self.FEDERATION_AUTH_URL,
+ text='NON XML RESPONSE')
self.assertRaises(
exceptions.AuthorizationFailure,
@@ -194,9 +190,8 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.session)
def test_send_authn_req_to_idp(self):
- self.requests.register_uri('POST',
- self.IDENTITY_PROVIDER_URL,
- content=saml2_fixtures.SAML2_ASSERTION)
+ self.requests.post(self.IDENTITY_PROVIDER_URL,
+ content=saml2_fixtures.SAML2_ASSERTION)
self.saml2plugin.sp_response_consumer_url = self.SHIB_CONSUMER_URL
self.saml2plugin.saml2_authn_request = etree.XML(
@@ -213,9 +208,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.assertEqual(idp_response, saml2_assertion_oneline, error)
def test_fail_basicauth_idp_authentication(self):
- self.requests.register_uri('POST',
- self.IDENTITY_PROVIDER_URL,
- status_code=401)
+ self.requests.post(self.IDENTITY_PROVIDER_URL, status_code=401)
self.saml2plugin.sp_response_consumer_url = self.SHIB_CONSUMER_URL
self.saml2plugin.saml2_authn_request = etree.XML(
@@ -232,8 +225,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.IDENTITY_PROVIDER_URL)
def test_send_authn_response_to_sp(self):
- self.requests.register_uri(
- 'POST',
+ self.requests.post(
self.SHIB_CONSUMER_URL,
json=saml2_fixtures.UNSCOPED_TOKEN,
headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER})
@@ -263,7 +255,7 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.SHIB_CONSUMER_URL)
def test_consumer_url_mismatch(self):
- self.requests.register_uri('POST', self.SHIB_CONSUMER_URL)
+ self.requests.post(self.SHIB_CONSUMER_URL)
invalid_consumer_url = uuid.uuid4().hex
self.assertRaises(
exceptions.ValidationError,
@@ -272,15 +264,13 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
invalid_consumer_url)
def test_custom_302_redirection(self):
- self.requests.register_uri(
- 'POST',
+ self.requests.post(
self.SHIB_CONSUMER_URL,
text='BODY',
headers={'location': self.FEDERATION_AUTH_URL},
status_code=302)
- self.requests.register_uri(
- 'GET',
+ self.requests.get(
self.FEDERATION_AUTH_URL,
json=saml2_fixtures.UNSCOPED_TOKEN,
headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER})
@@ -299,17 +289,14 @@ class AuthenticateviaSAML2Tests(utils.TestCase):
self.assertEqual('GET', response.request.method)
def test_end_to_end_workflow(self):
- self.requests.register_uri(
- 'GET',
+ self.requests.get(
self.FEDERATION_AUTH_URL,
content=make_oneline(saml2_fixtures.SP_SOAP_RESPONSE))
- self.requests.register_uri('POST',
- self.IDENTITY_PROVIDER_URL,
- content=saml2_fixtures.SAML2_ASSERTION)
+ self.requests.post(self.IDENTITY_PROVIDER_URL,
+ content=saml2_fixtures.SAML2_ASSERTION)
- self.requests.register_uri(
- 'POST',
+ self.requests.post(
self.SHIB_CONSUMER_URL,
json=saml2_fixtures.UNSCOPED_TOKEN,
headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER,
@@ -476,8 +463,8 @@ class AuthenticateviaADFSTests(utils.TestCase):
def test_get_adfs_security_token(self):
"""Test ADFSUnscopedToken._get_adfs_security_token()."""
- self.requests.register_uri(
- 'POST', self.IDENTITY_PROVIDER_URL,
+ self.requests.post(
+ self.IDENTITY_PROVIDER_URL,
content=make_oneline(self.ADFS_SECURITY_TOKEN_RESPONSE),
status_code=200)
@@ -539,9 +526,9 @@ class AuthenticateviaADFSTests(utils.TestCase):
An exceptions.AuthorizationFailure should be raised including
error message from the XML message indicating where was the problem.
"""
- self.requests.register_uri(
- 'POST', self.IDENTITY_PROVIDER_URL,
- content=make_oneline(self.ADFS_FAULT), status_code=500)
+ self.requests.post(self.IDENTITY_PROVIDER_URL,
+ content=make_oneline(self.ADFS_FAULT),
+ status_code=500)
self.adfsplugin._prepare_adfs_request()
self.assertRaises(exceptions.AuthorizationFailure,
@@ -558,10 +545,9 @@ class AuthenticateviaADFSTests(utils.TestCase):
and correctly raise exceptions.InternalServerError once it cannot
parse XML fault message
"""
- self.requests.register_uri(
- 'POST', self.IDENTITY_PROVIDER_URL,
- content=b'NOT XML',
- status_code=500)
+ self.requests.post(self.IDENTITY_PROVIDER_URL,
+ content=b'NOT XML',
+ status_code=500)
self.adfsplugin._prepare_adfs_request()
self.assertRaises(exceptions.InternalServerError,
self.adfsplugin._get_adfs_security_token,
@@ -573,9 +559,9 @@ class AuthenticateviaADFSTests(utils.TestCase):
"""Test whether SP issues a cookie."""
cookie = uuid.uuid4().hex
- self.requests.register_uri('POST', self.SP_ENDPOINT,
- headers={"set-cookie": cookie},
- status_code=302)
+ self.requests.post(self.SP_ENDPOINT,
+ headers={"set-cookie": cookie},
+ status_code=302)
self.adfsplugin.adfs_token = self._build_adfs_request()
self.adfsplugin._prepare_sp_request()
@@ -584,8 +570,7 @@ class AuthenticateviaADFSTests(utils.TestCase):
self.assertEqual(1, len(self.session.session.cookies))
def test_send_assertion_to_service_provider_bad_status(self):
- self.requests.register_uri('POST', self.SP_ENDPOINT,
- status_code=500)
+ self.requests.post(self.SP_ENDPOINT, status_code=500)
self.adfsplugin.adfs_token = etree.XML(
self.ADFS_SECURITY_TOKEN_RESPONSE)
@@ -605,10 +590,9 @@ class AuthenticateviaADFSTests(utils.TestCase):
self.session)
def test_check_valid_token_when_authenticated(self):
- self.requests.register_uri(
- 'GET', self.FEDERATION_AUTH_URL,
- json=saml2_fixtures.UNSCOPED_TOKEN,
- headers=client_fixtures.AUTH_RESPONSE_HEADERS)
+ self.requests.get(self.FEDERATION_AUTH_URL,
+ json=saml2_fixtures.UNSCOPED_TOKEN,
+ headers=client_fixtures.AUTH_RESPONSE_HEADERS)
self.session.session.cookies = [object()]
self.adfsplugin._access_service_provider(self.session)
@@ -621,18 +605,15 @@ class AuthenticateviaADFSTests(utils.TestCase):
response.json()['token'])
def test_end_to_end_workflow(self):
- self.requests.register_uri(
- 'POST', self.IDENTITY_PROVIDER_URL,
- content=self.ADFS_SECURITY_TOKEN_RESPONSE,
- status_code=200)
- self.requests.register_uri(
- 'POST', self.SP_ENDPOINT,
- headers={"set-cookie": 'x'},
- status_code=302)
- self.requests.register_uri(
- 'GET', self.FEDERATION_AUTH_URL,
- json=saml2_fixtures.UNSCOPED_TOKEN,
- headers=client_fixtures.AUTH_RESPONSE_HEADERS)
+ self.requests.post(self.IDENTITY_PROVIDER_URL,
+ content=self.ADFS_SECURITY_TOKEN_RESPONSE,
+ status_code=200)
+ self.requests.post(self.SP_ENDPOINT,
+ headers={"set-cookie": 'x'},
+ status_code=302)
+ self.requests.get(self.FEDERATION_AUTH_URL,
+ json=saml2_fixtures.UNSCOPED_TOKEN,
+ headers=client_fixtures.AUTH_RESPONSE_HEADERS)
# NOTE(marek-denis): We need to mimic this until self.requests can
# issue cookies properly.
diff --git a/keystoneclient/tests/v3/test_client.py b/keystoneclient/tests/v3/test_client.py
index bf45032..e1a8542 100644
--- a/keystoneclient/tests/v3/test_client.py
+++ b/keystoneclient/tests/v3/test_client.py
@@ -40,6 +40,10 @@ class KeystoneClientTest(utils.TestCase):
'c4da488862bd435c9e6c0275a0d0e49a')
self.assertFalse(c.has_service_catalog())
+ self.assertEqual('c4da488862bd435c9e6c0275a0d0e49a',
+ c.get_user_id(session=None))
+ self.assertIsNone(c.get_project_id(session=None))
+
def test_domain_scoped_init(self):
self.stub_auth(json=client_fixtures.domain_scoped_token())
@@ -70,6 +74,10 @@ class KeystoneClientTest(utils.TestCase):
'c4da488862bd435c9e6c0275a0d0e49a')
self.assertEqual(c.auth_tenant_id,
'225da22d3ce34b15877ea70b2a575f58')
+ self.assertEqual('c4da488862bd435c9e6c0275a0d0e49a',
+ c.get_user_id(session=None))
+ self.assertEqual('225da22d3ce34b15877ea70b2a575f58',
+ c.get_project_id(session=None))
def test_auth_ref_load(self):
self.stub_auth(json=client_fixtures.project_scoped_token())
diff --git a/keystoneclient/tests/v3/test_discover.py b/keystoneclient/tests/v3/test_discover.py
index 08e5358..4a1dee3 100644
--- a/keystoneclient/tests/v3/test_discover.py
+++ b/keystoneclient/tests/v3/test_discover.py
@@ -61,9 +61,9 @@ class DiscoverKeystoneTests(utils.UnauthenticatedTestCase):
}
def test_get_version_local(self):
- self.requests.register_uri('GET', "http://localhost:35357/",
- status_code=300,
- json=self.TEST_RESPONSE_DICT)
+ self.requests.get("http://localhost:35357/",
+ status_code=300,
+ json=self.TEST_RESPONSE_DICT)
cs = client.Client()
versions = cs.discover()
diff --git a/keystoneclient/tests/v3/test_domains.py b/keystoneclient/tests/v3/test_domains.py
index e86971a..101d3f9 100644
--- a/keystoneclient/tests/v3/test_domains.py
+++ b/keystoneclient/tests/v3/test_domains.py
@@ -41,3 +41,8 @@ class DomainTests(utils.TestCase, utils.CrudTests):
expected_query = {'enabled': '0'}
super(DomainTests, self).test_list(expected_query=expected_query,
enabled=False)
+
+ def test_update_enabled_defaults_to_none(self):
+ req_ref = self.new_ref()
+ del req_ref['enabled']
+ super(DomainTests, self).test_update(req_ref=req_ref)
diff --git a/keystoneclient/tests/v3/test_federation.py b/keystoneclient/tests/v3/test_federation.py
index 503da47..eed6680 100644
--- a/keystoneclient/tests/v3/test_federation.py
+++ b/keystoneclient/tests/v3/test_federation.py
@@ -349,8 +349,7 @@ class FederationProjectTests(utils.TestCase):
projects_json = {
self.collection_key: [self.new_ref(), self.new_ref()]
}
- self.requests.register_uri('GET', self.URL,
- json=projects_json, status_code=200)
+ self.requests.get(self.URL, json=projects_json)
returned_list = self.manager.list()
self.assertEqual(len(projects_ref), len(returned_list))
@@ -381,8 +380,7 @@ class FederationDomainTests(utils.TestCase):
domains_json = {
self.collection_key: domains_ref
}
- self.requests.register_uri('GET', self.URL,
- json=domains_json, status_code=200)
+ self.requests.get(self.URL, json=domains_json)
returned_list = self.manager.list()
self.assertEqual(len(domains_ref), len(returned_list))
for domain in returned_list:
diff --git a/keystoneclient/tests/v3/test_regions.py b/keystoneclient/tests/v3/test_regions.py
index c539aa7..3574ece 100644
--- a/keystoneclient/tests/v3/test_regions.py
+++ b/keystoneclient/tests/v3/test_regions.py
@@ -31,3 +31,8 @@ class RegionTests(utils.TestCase, utils.CrudTests):
kwargs.setdefault('enabled', True)
kwargs.setdefault('id', uuid.uuid4().hex)
return kwargs
+
+ def test_update_enabled_defaults_to_none(self):
+ req_ref = self.new_ref()
+ del req_ref['enabled']
+ super(RegionTests, self).test_update(req_ref=req_ref)
diff --git a/keystoneclient/tests/v3/test_services.py b/keystoneclient/tests/v3/test_services.py
index d271afe..5367241 100644
--- a/keystoneclient/tests/v3/test_services.py
+++ b/keystoneclient/tests/v3/test_services.py
@@ -30,3 +30,15 @@ class ServiceTests(utils.TestCase, utils.CrudTests):
kwargs.setdefault('type', uuid.uuid4().hex)
kwargs.setdefault('enabled', True)
return kwargs
+
+ def test_list_filter_name(self):
+ filter_name = uuid.uuid4().hex
+ expected_query = {'name': filter_name}
+ super(ServiceTests, self).test_list(expected_query=expected_query,
+ name=filter_name)
+
+ def test_list_filter_type(self):
+ filter_type = uuid.uuid4().hex
+ expected_query = {'type': filter_type}
+ super(ServiceTests, self).test_list(expected_query=expected_query,
+ type=filter_type)
diff --git a/keystoneclient/tests/v3/utils.py b/keystoneclient/tests/v3/utils.py
index 0929403..d4c201b 100644
--- a/keystoneclient/tests/v3/utils.py
+++ b/keystoneclient/tests/v3/utils.py
@@ -244,27 +244,22 @@ class CrudTests(object):
ref_list = ref_list or [self.new_ref(), self.new_ref()]
expected_path = self._get_expected_path(expected_path)
- self.requests.register_uri('GET',
- urlparse.urljoin(self.TEST_URL,
- expected_path),
- json=self.encode(ref_list))
+ self.requests.get(urlparse.urljoin(self.TEST_URL, expected_path),
+ json=self.encode(ref_list))
returned_list = self.manager.list(**filter_kwargs)
self.assertEqual(len(ref_list), len(returned_list))
[self.assertIsInstance(r, self.model) for r in returned_list]
- # register_uri doesn't match the querystring component, so we have to
- # explicitly test the querystring component passed by the manager
- parts = urlparse.urlparse(self.requests.last_request.url)
- qs_args = urlparse.parse_qs(parts.query)
+ qs_args = self.requests.last_request.qs
qs_args_expected = expected_query or filter_kwargs
for key, value in six.iteritems(qs_args_expected):
self.assertIn(key, qs_args)
- # The httppretty.querystring value is a list
- # Note we convert the value to a string, as the query string
- # is always a string and the filter_kwargs may contain non-string
- # values, for example a boolean, causing the comaprison to fail.
- self.assertIn(str(value), qs_args[key])
+ # The querystring value is a list. Note we convert the value to a
+ # string and lower, as the query string is always a string and the
+ # filter_kwargs may contain non-string values, for example a
+ # boolean, causing the comaprison to fail.
+ self.assertIn(str(value).lower(), qs_args[key])
# Also check that no query string args exist which are not expected
for key in qs_args:
@@ -275,10 +270,8 @@ class CrudTests(object):
filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex}
expected_path = self._get_expected_path()
- self.requests.register_uri('GET',
- urlparse.urljoin(self.TEST_URL,
- expected_path),
- json=self.encode(ref_list))
+ self.requests.get(urlparse.urljoin(self.TEST_URL, expected_path),
+ json=self.encode(ref_list))
self.manager.list(**filter_kwargs)
self.assertQueryStringContains(**filter_kwargs)
diff --git a/keystoneclient/v2_0/certificates.py b/keystoneclient/v2_0/certificates.py
new file mode 100644
index 0000000..b8d2573
--- /dev/null
+++ b/keystoneclient/v2_0/certificates.py
@@ -0,0 +1,42 @@
+# Copyright 2014 IBM Corp.
+# 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.
+
+
+class CertificatesManager(object):
+ """Manager for certificates."""
+
+ def __init__(self, client):
+ self._client = client
+
+ def get_ca_certificate(self):
+ """Get CA certificate.
+
+ :returns: PEM-formatted string.
+ :rtype: str
+
+ """
+
+ resp, body = self._client.get('/certificates/ca', authenticated=False)
+ return resp.text
+
+ def get_signing_certificate(self):
+ """Get signing certificate.
+
+ :returns: PEM-formatted string.
+ :rtype: str
+
+ """
+
+ resp, body = self._client.get('/certificates/signing',
+ authenticated=False)
+ return resp.text
diff --git a/keystoneclient/v2_0/client.py b/keystoneclient/v2_0/client.py
index f7bf153..bba556e 100644
--- a/keystoneclient/v2_0/client.py
+++ b/keystoneclient/v2_0/client.py
@@ -19,6 +19,7 @@ from keystoneclient.auth.identity import v2 as v2_auth
from keystoneclient import exceptions
from keystoneclient import httpclient
from keystoneclient.i18n import _
+from keystoneclient.v2_0 import certificates
from keystoneclient.v2_0 import ec2
from keystoneclient.v2_0 import endpoints
from keystoneclient.v2_0 import extensions
@@ -131,6 +132,7 @@ class Client(httpclient.HTTPClient):
"""Initialize a new client for the Keystone v2.0 API."""
super(Client, self).__init__(**kwargs)
+ self.certificates = certificates.CertificatesManager(self._adapter)
self.endpoints = endpoints.EndpointManager(self._adapter)
self.extensions = extensions.ExtensionManager(self._adapter)
self.roles = roles.RoleManager(self._adapter)
diff --git a/keystoneclient/v2_0/shell.py b/keystoneclient/v2_0/shell.py
index a2cb1ab..9920555 100755
--- a/keystoneclient/v2_0/shell.py
+++ b/keystoneclient/v2_0/shell.py
@@ -248,11 +248,11 @@ def do_tenant_delete(kc, args):
kc.tenants.delete(tenant)
-@utils.arg('--name', metavar='<name>', required=True,
- help='Name of new service (must be unique).')
@utils.arg('--type', metavar='<type>', required=True,
help='Service type (one of: identity, compute, network, '
'image, object-store, or other service identifier string).')
+@utils.arg('--name', metavar='<name>',
+ help='Name of new service (must be unique).')
@utils.arg('--description', metavar='<service-description>',
help='Description of service.')
def do_service_create(kc, args):
diff --git a/keystoneclient/v2_0/tokens.py b/keystoneclient/v2_0/tokens.py
index fb48738..ed1c07e 100644
--- a/keystoneclient/v2_0/tokens.py
+++ b/keystoneclient/v2_0/tokens.py
@@ -72,3 +72,13 @@ class TokenManager(base.Manager):
def endpoints(self, token):
return self._get("/tokens/%s/endpoints" % base.getid(token), "token")
+
+ def get_revoked(self):
+ """Returns the revoked tokens response.
+
+ The response will be a dict containing 'signed' which is a CMS-encoded
+ document.
+
+ """
+ resp, body = self.client.get('/tokens/revoked')
+ return body
diff --git a/keystoneclient/v3/domains.py b/keystoneclient/v3/domains.py
index e0d082d..4439f41 100644
--- a/keystoneclient/v3/domains.py
+++ b/keystoneclient/v3/domains.py
@@ -60,7 +60,7 @@ class DomainManager(base.CrudManager):
@utils.positional(enforcement=utils.positional.WARN)
def update(self, domain, name=None,
- description=None, enabled=True, **kwargs):
+ description=None, enabled=None, **kwargs):
return super(DomainManager, self).update(
domain_id=base.getid(domain),
name=name,
diff --git a/keystoneclient/v3/regions.py b/keystoneclient/v3/regions.py
index de925e3..65cc6ab 100644
--- a/keystoneclient/v3/regions.py
+++ b/keystoneclient/v3/regions.py
@@ -65,7 +65,7 @@ class RegionManager(base.CrudManager):
return super(RegionManager, self).list(
**kwargs)
- def update(self, region, description=None, enabled=True,
+ def update(self, region, description=None, enabled=None,
parent_region=None, **kwargs):
"""Update a Catalog region.
@@ -75,7 +75,7 @@ class RegionManager(base.CrudManager):
pre-existing region in the backend. Allows for hierarchical
region organization.
:param enabled: determines whether the endpoint appears in the
- catalog. Defaults to True
+ catalog.
"""
return super(RegionManager, self).update(
diff --git a/keystoneclient/v3/services.py b/keystoneclient/v3/services.py
index e0fd2c8..d6d4c80 100644
--- a/keystoneclient/v3/services.py
+++ b/keystoneclient/v3/services.py
@@ -51,6 +51,13 @@ class ServiceManager(base.CrudManager):
service_id=base.getid(service))
@utils.positional(enforcement=utils.positional.WARN)
+ def list(self, name=None, type=None, **kwargs):
+ return super(ServiceManager, self).list(
+ name=name,
+ type=type,
+ **kwargs)
+
+ @utils.positional(enforcement=utils.positional.WARN)
def update(self, service, name=None, type=None, enabled=None,
description=None, **kwargs):
return super(ServiceManager, self).update(