diff --git a/keystoneclient/_discover.py b/keystoneclient/_discover.py index 5f5002710..7ea396f91 100644 --- a/keystoneclient/_discover.py +++ b/keystoneclient/_discover.py @@ -24,16 +24,18 @@ raw data specified in version discovery responses. import logging from keystoneclient import exceptions +from keystoneclient import utils _LOGGER = logging.getLogger(__name__) -def get_version_data(session, url): +@utils.positional() +def get_version_data(session, url, authenticated=None): """Retrieve raw version data from a url.""" headers = {'Accept': 'application/json'} - resp = session.get(url, headers=headers) + resp = session.get(url, headers=headers, authenticated=authenticated) try: body_resp = resp.json() @@ -131,8 +133,10 @@ class Discover(object): DEPRECATED_STATUSES = ('deprecated',) EXPERIMENTAL_STATUSES = ('experimental',) - def __init__(self, session, url): - self._data = get_version_data(session, url) + @utils.positional() + def __init__(self, session, url, authenticated=None): + self._data = get_version_data(session, url, + authenticated=authenticated) def raw_version_data(self, allow_experimental=False, allow_deprecated=True, allow_unknown=False): diff --git a/keystoneclient/auth/identity/base.py b/keystoneclient/auth/identity/base.py index 6ee7774b3..4b02f944b 100644 --- a/keystoneclient/auth/identity/base.py +++ b/keystoneclient/auth/identity/base.py @@ -19,6 +19,7 @@ import six from keystoneclient import _discover from keystoneclient.auth import base from keystoneclient import exceptions +from keystoneclient import utils LOG = logging.getLogger(__name__) @@ -192,7 +193,7 @@ class BaseIdentityPlugin(base.BaseAuthPlugin): return url try: - disc = self.get_discovery(session, url) + disc = self.get_discovery(session, url, authenticated=False) except (exceptions.DiscoveryFailure, exceptions.HTTPError, exceptions.ConnectionError): @@ -206,7 +207,8 @@ class BaseIdentityPlugin(base.BaseAuthPlugin): return url - def get_discovery(self, session, url): + @utils.positional() + def get_discovery(self, session, url, authenticated=None): """Return the discovery object for a URL. Check the session and the plugin cache to see if we have already @@ -218,6 +220,9 @@ class BaseIdentityPlugin(base.BaseAuthPlugin): :param Session session: A session object to discover with. :param str url: The url to lookup. + :param bool authenticated: Include a token in the discovery call. + (optional) Defaults to None (use a token + if a plugin is installed). :raises: DiscoveryFailure if for some reason the lookup fails. :raises: HttpError An error from an invalid HTTP response. @@ -241,7 +246,8 @@ class BaseIdentityPlugin(base.BaseAuthPlugin): if disc: break else: - disc = _discover.Discover(session, url) + disc = _discover.Discover(session, url, + authenticated=authenticated) self._endpoint_cache[url] = disc session_endpoint_cache[url] = disc diff --git a/keystoneclient/discover.py b/keystoneclient/discover.py index 7d8e1edf9..07de97dd4 100644 --- a/keystoneclient/discover.py +++ b/keystoneclient/discover.py @@ -17,6 +17,7 @@ import six from keystoneclient import _discover from keystoneclient import exceptions from keystoneclient import session as client_session +from keystoneclient import utils from keystoneclient.v2_0 import client as v2_client from keystoneclient.v3 import client as v3_client @@ -44,7 +45,8 @@ class Discover(_discover.Discover): operates upon the data that was retrieved. """ - def __init__(self, session=None, **kwargs): + @utils.positional(2) + def __init__(self, session=None, authenticated=None, **kwargs): """Construct a new discovery object. The connection parameters associated with this method are the same @@ -98,6 +100,10 @@ class Discover(_discover.Discover): service. default: False (optional) DEPRECATED: use the session object. This is ignored if a session is provided. + :param bool authenticated: Should a token be used to perform the + initial discovery operations. + default: None (attach a token if an auth + plugin is available). """ if not session: @@ -121,7 +127,8 @@ class Discover(_discover.Discover): 'auth_url or endpoint') self._client_kwargs = kwargs - super(Discover, self).__init__(session, url) + super(Discover, self).__init__(session, url, + authenticated=authenticated) def available_versions(self, **kwargs): """Return a list of identity APIs available on the server and the data diff --git a/keystoneclient/tests/test_discovery.py b/keystoneclient/tests/test_discovery.py index fc0f5518c..10f1c2f21 100644 --- a/keystoneclient/tests/test_discovery.py +++ b/keystoneclient/tests/test_discovery.py @@ -10,15 +10,19 @@ # License for the specific language governing permissions and limitations # under the License. +import uuid + import six from testtools import matchers from keystoneclient import _discover +from keystoneclient.auth import token_endpoint from keystoneclient import client from keystoneclient import discover from keystoneclient import exceptions from keystoneclient import fixture from keystoneclient.openstack.common import jsonutils +from keystoneclient import session from keystoneclient.tests import utils from keystoneclient.v2_0 import client as v2_client from keystoneclient.v3 import client as v3_client @@ -547,6 +551,31 @@ class ClientDiscoveryTests(utils.TestCase): 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) + + if not token: + token = uuid.uuid4().hex + + url = 'http://testurl' + a = token_endpoint.Token(url, token) + s = session.Session(auth=a) + + # will default to true as there is a plugin on the session + discover.Discover(s, auth_url=BASE_URL, **kwargs) + + self.assertEqual(BASE_URL, self.requests.last_request.url) + + def test_setting_authenticated_true(self): + token = uuid.uuid4().hex + self._do_discovery_call(token) + self.assertRequestHeaderEqual('X-Auth-Token', token) + + def test_setting_authenticated_false(self): + self._do_discovery_call(authenticated=False) + self.assertNotIn('X-Auth-Token', self.requests.last_request.headers) + class DiscoverQueryTests(utils.TestCase):