From 14de75e5807cfd055bb2cd8ff09b283cf502d11d Mon Sep 17 00:00:00 2001 From: Hongbin Lu Date: Tue, 23 Oct 2018 03:35:01 +0000 Subject: [PATCH] Handle different endpoint format Depending on a specific deployment of Zun, the API endpoint could be of various formats. For example: 1. the classic (legacy) endpoint: http://{host}:{optional_port}/v1/ 2. under wsgi: http://{host}:{optional_port}/container/v1 3. other: https://container.example.com/ https://example.com/container We need to parse the url correctly in order to get the correct version URL which is used to determinate the API version. Change-Id: Ia69959431e2d751d228f4cfc1db74b774bd9d69e Closes-Bug: #1799343 --- zunclient/tests/unit/utils.py | 5 +++-- zunclient/tests/unit/v1/test_versions.py | 22 ++++++++++++---------- zunclient/v1/versions.py | 24 +++++++++++++++++++++--- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/zunclient/tests/unit/utils.py b/zunclient/tests/unit/utils.py index 09dfe454..f383249d 100644 --- a/zunclient/tests/unit/utils.py +++ b/zunclient/tests/unit/utils.py @@ -40,11 +40,12 @@ class BaseTestCase(testtools.TestCase): class FakeAPI(object): - def __init__(self, responses): + def __init__(self, responses, endpoint=None): self.responses = responses self.calls = [] self.api_version = api_versions.APIVersion( api_versions.MAX_API_VERSION) + self.endpoint = endpoint def _request(self, method, url, headers=None, body=None): call = (method, url, headers or {}, body) @@ -61,7 +62,7 @@ class FakeAPI(object): return FakeResponse(response[0]), response[1] def get_endpoint(self, *args, **kwargs): - return '/v1' + return self.endpoint or '/v1' class FakeConnection(object): diff --git a/zunclient/tests/unit/v1/test_versions.py b/zunclient/tests/unit/v1/test_versions.py index e22168b0..b8c2d80f 100644 --- a/zunclient/tests/unit/v1/test_versions.py +++ b/zunclient/tests/unit/v1/test_versions.py @@ -24,7 +24,7 @@ VERSION1 = {'status': 'CURRENT', } fake_responses = { - '/': + 'https://example.com': { 'GET': ( {}, @@ -36,15 +36,17 @@ fake_responses = { class VersionManagerTest(testtools.TestCase): - def setUp(self): - super(VersionManagerTest, self).setUp() - self.api = utils.FakeAPI(fake_responses) - self.mgr = versions.VersionManager(self.api) - def test_version_list(self): - versions = self.mgr.list() + self._test_version_list('https://example.com') + self._test_version_list('https://example.com/v1') + self._test_version_list('https://example.com/v1/') + + def _test_version_list(self, endpoint): + api = utils.FakeAPI(fake_responses, endpoint=endpoint) + mgr = versions.VersionManager(api) + api_versions = mgr.list() expect = [ - ('GET', '/', {}, None), + ('GET', 'https://example.com', {}, None), ] - self.assertEqual(expect, self.api.calls) - self.assertThat(versions, matchers.HasLength(1)) + self.assertEqual(expect, api.calls) + self.assertThat(api_versions, matchers.HasLength(1)) diff --git a/zunclient/v1/versions.py b/zunclient/v1/versions.py index 63c76570..80050b30 100644 --- a/zunclient/v1/versions.py +++ b/zunclient/v1/versions.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +from six.moves import urllib + from zunclient.common import base @@ -22,9 +24,25 @@ class VersionManager(base.Manager): resource_class = Version def list(self): - url = "%s" % self.api.get_endpoint() - url = "%s/" % url.rsplit("/", 1)[0] - return self._list(url, "versions") + endpoint = self.api.get_endpoint() + url = urllib.parse.urlparse(endpoint) + # NOTE(hongbin): endpoint URL has at least 2 formats: + # 1. the classic (legacy) endpoint: + # http://{host}:{optional_port}/v1/ + # 2. under wsgi: + # http://{host}:{optional_port}/container/v1 + if url.path.endswith("v1") or "/v1/" in url.path: + # this way should handle all 2 possible formats + path = url.path[:url.path.rfind("/v1")] + version_url = '%s://%s%s' % (url.scheme, url.netloc, path) + else: + # NOTE(hongbin): probably, it is one of the next cases: + # * https://container.example.com/ + # * https://example.com/container + # leave as is without cropping. + version_url = endpoint + + return self._list(version_url, "versions") def get_current(self): for version in self.list():