diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py index 3cbd91f0..88121d58 100644 --- a/openstack_auth/backend.py +++ b/openstack_auth/backend.py @@ -77,11 +77,11 @@ class KeystoneBackend(object): # keystone client v3 does not support logging in on the v2 url any more if utils.get_keystone_version() >= 3: - if auth_url.find("v2.0") >= 0: + if utils.has_in_url_path(auth_url, "/v2.0"): LOG.warning("The settings.py file points to a v2.0 keystone " "endpoint, but v3 is specified as the API version " "to use. Using v3 endpoint for authentication.") - auth_url = auth_url.replace('v2.0', 'v3') + auth_url = utils.url_path_replace(auth_url, "/v2.0", "/v3", 1) keystone_client = utils.get_keystone_client() try: diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py index f6da16d1..a8c2ff50 100644 --- a/openstack_auth/utils.py +++ b/openstack_auth/utils.py @@ -141,15 +141,38 @@ def get_keystone_client(): return client_v3 +def has_in_url_path(url, sub): + """Test if the `sub` string is in the `url` path.""" + scheme, netloc, path, query, fragment = urlparse.urlsplit(url) + return sub in path + + +def url_path_replace(url, old, new, count=None): + """Return a copy of url with replaced path. + + Return a copy of url with all occurrences of old replaced by new in the url + path. If the optional argument count is given, only the first count + occurrences are replaced. + """ + args = [] + scheme, netloc, path, query, fragment = urlparse.urlsplit(url) + if count is not None: + args.append(count) + return urlparse.urlunsplit(( + scheme, netloc, path.replace(old, new, *args), query, fragment)) + + @memoize_by_keyword_arg(_PROJECT_CACHE, ('token', )) def get_project_list(*args, **kwargs): if get_keystone_version() < 3: - auth_url = kwargs.get('auth_url', '').replace('v3', 'v2.0') + auth_url = url_path_replace( + kwargs.get('auth_url', ''), '/v3', '/v2.0', 1) kwargs['auth_url'] = auth_url client = get_keystone_client().Client(*args, **kwargs) projects = client.tenants.list() else: - auth_url = kwargs.get('auth_url', '').replace('v2.0', 'v3') + auth_url = url_path_replace( + kwargs.get('auth_url', ''), '/v2.0', '/v3', 1) kwargs['auth_url'] = auth_url client = get_keystone_client().Client(*args, **kwargs) client.management_url = auth_url diff --git a/openstack_auth/views.py b/openstack_auth/views.py index 4ce09b7f..361d22f8 100644 --- a/openstack_auth/views.py +++ b/openstack_auth/views.py @@ -149,8 +149,8 @@ def switch(request, tenant_id, redirect_field_name=auth.REDIRECT_FIELD_NAME): endpoint = request.user.endpoint try: if utils.get_keystone_version() >= 3: - if 'v3' not in endpoint: - endpoint = endpoint.replace('v2.0', 'v3') + if not utils.has_in_url_path(endpoint, '/v3'): + endpoint = utils.url_path_replace(endpoint, '/v2.0', '/v3', 1) client = utils.get_keystone_client().Client( tenant_id=tenant_id, token=request.user.token.id,