diff --git a/keystoneauth1/discover.py b/keystoneauth1/discover.py index cfcf4ac1..4e07e0a7 100644 --- a/keystoneauth1/discover.py +++ b/keystoneauth1/discover.py @@ -367,10 +367,28 @@ def _combine_relative_url(discovery_url, version_url): parsed_version_url = urllib.parse.urlparse(url) parsed_discovery_url = urllib.parse.urlparse(discovery_url) + # The services can override the version_url with some config options.(for + # example, In Keystone, Cinder and Glance, the option is "public_endpoint", + # and "compute_link_prefix", "network_link_prefix" in Nova and Neutron. + # In this case, it's hard to distinguish which part in version_url is + # useful for discovery_url , so here we just get the version from + # version_url and then add it into the discovery_url if needed. + path = parsed_version_url.path + if parsed_discovery_url.netloc != parsed_version_url.netloc: + version = version_url.rstrip('/').split('/')[-1] + url_path = parsed_discovery_url.path.rstrip('/') + if not url_path.endswith(version): + path = url_path + '/' + version + if version_url.endswith('/'): + # add '/' back to keep backward compatibility. + path = path + '/' + else: + path = parsed_discovery_url.path + return urllib.parse.ParseResult( parsed_discovery_url.scheme, parsed_discovery_url.netloc, - parsed_version_url.path, + path, parsed_version_url.params, parsed_version_url.query, parsed_version_url.fragment).geturl() diff --git a/keystoneauth1/tests/unit/identity/test_identity_common.py b/keystoneauth1/tests/unit/identity/test_identity_common.py index 93f1a707..054f975a 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_common.py +++ b/keystoneauth1/tests/unit/identity/test_identity_common.py @@ -329,7 +329,7 @@ class CommonIdentityTests(object): sb = session.Session() discovery_cache = {} - expected_url = urllib.parse.urljoin(self.TEST_COMPUTE_ADMIN, '/v2.0') + expected_url = self.TEST_COMPUTE_ADMIN + '/v2.0' for sess in (sa, sb): disc = discover.get_discovery( diff --git a/keystoneauth1/tests/unit/test_discovery.py b/keystoneauth1/tests/unit/test_discovery.py index c7bab41e..22d7e89c 100644 --- a/keystoneauth1/tests/unit/test_discovery.py +++ b/keystoneauth1/tests/unit/test_discovery.py @@ -480,6 +480,38 @@ class VersionDataTests(utils.TestCase): self.assertTrue(mock.called_once) + def test_version_data_override_version_url(self): + # if the request url is versioned already, just return it. + self.requests_mock.get( + V3_URL, status_code=200, + json={'version': fixture.V3Discovery('http://override/identity/v3') + } + ) + + disc = discover.Discover(self.session, V3_URL) + version_data = disc.version_data() + + for v in version_data: + self.assertEqual(v['version'], (3, 0)) + self.assertEqual(v['raw_status'], 'stable') + self.assertEqual(v['url'], V3_URL) + + # if the request url is not versioned, just add version info to it.( + # do not changed the url's netloc or path) + self.requests_mock.get( + BASE_URL, status_code=200, + json={'version': fixture.V3Discovery('http://override/identity/v3') + } + ) + + disc = discover.Discover(self.session, BASE_URL) + version_data = disc.version_data() + + for v in version_data: + self.assertEqual(v['version'], (3, 0)) + self.assertEqual(v['raw_status'], 'stable') + self.assertEqual(v['url'], V3_URL) + def test_version_data_individual(self): mock = self.requests_mock.get(V3_URL, status_code=200, diff --git a/releasenotes/notes/bug-1733052-1b4af3b3fe1b05bb.yaml b/releasenotes/notes/bug-1733052-1b4af3b3fe1b05bb.yaml new file mode 100644 index 00000000..56a11f85 --- /dev/null +++ b/releasenotes/notes/bug-1733052-1b4af3b3fe1b05bb.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - > + [`bug 1733052 `_] + Now the version discovery mechanism only fetches the version info from + server side if the versioned url has been overrode. So that the request + url's path won't be changed completely.