From ba67867b1702e15d6e20d2abf429399971660d86 Mon Sep 17 00:00:00 2001 From: Sergey Nikitin Date: Thu, 25 Feb 2016 12:55:51 +0300 Subject: [PATCH] Added processing /compute URL for getting list of versions After implementing blueprint "Ability to run some Nova services under Apache2"( https://blueprints.launchpad.net/nova/+spec/run-nova-services-under-apache2) it becomes possible not to use separate ports for each openstack service but share 80 port with different URL prefixes. Mailing list thread with discussion the details of this feature: http://lists.openstack.org/pipermail/openstack-dev/2015-June/067147.html. Openstack wiki page with mapping urls to services: https://wiki.openstack.org/wiki/URLs. If nova-api service is started by Apache (or similar), using 'Alias' directive script name contains alias-prefix. We get things like: '/ALIAS/NAME/v2', '/ALIAS/NAME/v2.1' This change makes sure we compose correct url for getting list of versions. Co-Authored-By: Marian Horban Co-Authored-By: Pavel Kholkin Closes-Bug: #1471833 Change-Id: I2c78e22095975aef777bc62b19d46bcc8fea2d96 --- tempest/lib/auth.py | 16 ++++---- .../lib/services/compute/versions_client.py | 19 +++++---- tempest/tests/lib/fake_auth_provider.py | 5 ++- .../services/compute/test_versions_client.py | 39 +++++++++++++++++++ 4 files changed, 62 insertions(+), 17 deletions(-) diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py index 806acb5205..0586346b55 100644 --- a/tempest/lib/auth.py +++ b/tempest/lib/auth.py @@ -323,10 +323,10 @@ class KeystoneV2AuthProvider(KeystoneAuthProvider): parts = urlparse.urlparse(_base_url) if filters.get('api_version', None) is not None: - path = "/" + filters['api_version'] - noversion_path = "/".join(parts.path.split("/")[2:]) - if noversion_path != "": - path += "/" + noversion_path + path = re.sub(r'(^|/)+v\d+(?:\.\d+)?', + '/' + filters['api_version'], + parts.path, + count=1) _base_url = _base_url.replace(parts.path, path) if filters.get('skip_path', None) is not None and parts.path != '': _base_url = _base_url.replace(parts.path, "/") @@ -445,10 +445,10 @@ class KeystoneV3AuthProvider(KeystoneAuthProvider): parts = urlparse.urlparse(_base_url) if filters.get('api_version', None) is not None: - path = "/" + filters['api_version'] - noversion_path = "/".join(parts.path.split("/")[2:]) - if noversion_path != "": - path += "/" + noversion_path + path = re.sub(r'(^|/)+v\d+(?:\.\d+)?', + '/' + filters['api_version'], + parts.path, + count=1) _base_url = _base_url.replace(parts.path, path) if filters.get('skip_path', None) is not None: _base_url = _base_url.replace(parts.path, "/") diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py index 5898f9370e..ed82c74c51 100644 --- a/tempest/lib/services/compute/versions_client.py +++ b/tempest/lib/services/compute/versions_client.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import re + from oslo_serialization import jsonutils as json from six.moves import urllib @@ -22,14 +24,17 @@ from tempest.lib.common import rest_client class VersionsClient(rest_client.RestClient): def _get_base_version_url(self): - # NOTE: The URL which is gotten from keystone's catalog contains - # API version and project-id like "v2/{project-id}", but we need - # to access the URL which doesn't contain them for getting API - # versions. For that, here should use raw_request() instead of - # get(). + # NOTE: The URL which is got from keystone's catalog contains + # API version and project-id like "/app-name/v2/{project-id}" or + # "/v2/{project-id}", but we need to access the URL which doesn't + # contain API version for getting API versions. For that, here + # should use raw_request() instead of get(). endpoint = self.base_url - url = urllib.parse.urlparse(endpoint) - return '%s://%s/' % (url.scheme, url.netloc) + url = urllib.parse.urlsplit(endpoint) + new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0] + url = list(url) + url[2] = new_path + '/' + return urllib.parse.urlunsplit(url) def list_versions(self): version_url = self._get_base_version_url() diff --git a/tempest/tests/lib/fake_auth_provider.py b/tempest/tests/lib/fake_auth_provider.py index 7f00fb8ad0..8095453b9a 100644 --- a/tempest/tests/lib/fake_auth_provider.py +++ b/tempest/tests/lib/fake_auth_provider.py @@ -16,15 +16,16 @@ class FakeAuthProvider(object): - def __init__(self, creds_dict=None): + def __init__(self, creds_dict=None, fake_base_url=None): creds_dict = creds_dict or {} self.credentials = FakeCredentials(creds_dict) + self.fake_base_url = fake_base_url def auth_request(self, method, url, headers=None, body=None, filters=None): return url, headers, body def base_url(self, filters, auth_data=None): - return "https://example.com" + return self.fake_base_url or "https://example.com" class FakeCredentials(object): diff --git a/tempest/tests/lib/services/compute/test_versions_client.py b/tempest/tests/lib/services/compute/test_versions_client.py index 5ac2f2d89c..fc6c1d2087 100644 --- a/tempest/tests/lib/services/compute/test_versions_client.py +++ b/tempest/tests/lib/services/compute/test_versions_client.py @@ -94,3 +94,42 @@ class TestVersionsClient(base.BaseComputeServiceTest): def test_get_version_by_url_with_bytes_body(self): self._test_get_version_by_url(bytes_body=True) + + def _test_get_base_version_url(self, url, expected_base_url): + auth = fake_auth_provider.FakeAuthProvider(fake_base_url=url) + client = versions_client.VersionsClient(auth, 'compute', 'regionOne') + self.assertEqual(expected_base_url, client._get_base_version_url()) + + def test_get_base_version_url(self): + self._test_get_base_version_url('https://bar.org/v2/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org/v2.1/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org/v2.15/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org/v22.2/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org/v22/123', + 'https://bar.org/') + + def test_get_base_version_url_app_name(self): + self._test_get_base_version_url('https://bar.org/compute/v2/123', + 'https://bar.org/compute/') + self._test_get_base_version_url('https://bar.org/compute/v2.1/123', + 'https://bar.org/compute/') + self._test_get_base_version_url('https://bar.org/compute/v2.15/123', + 'https://bar.org/compute/') + self._test_get_base_version_url('https://bar.org/compute/v22.2/123', + 'https://bar.org/compute/') + self._test_get_base_version_url('https://bar.org/compute/v22/123', + 'https://bar.org/compute/') + + def test_get_base_version_url_double_slash(self): + self._test_get_base_version_url('https://bar.org//v2/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org//v2.1/123', + 'https://bar.org/') + self._test_get_base_version_url('https://bar.org/compute//v2/123', + 'https://bar.org/compute/') + self._test_get_base_version_url('https://bar.org/compute//v2.1/123', + 'https://bar.org/compute/')