diff --git a/ironicclient/client.py b/ironicclient/client.py index b5bea8196..be3fac647 100644 --- a/ironicclient/client.py +++ b/ironicclient/client.py @@ -124,6 +124,9 @@ def get_client(api_version, os_auth_token=None, ironic_url=None, if not endpoint: if session: try: + # Pass the endpoint, it will be used to get hostname + # and port that will be used for API version caching. It will + # be also set as endpoint_override. endpoint = session.get_endpoint( service_type=os_service_type, interface=os_endpoint_type, diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index 91c1e1c05..89b7b89ce 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -506,6 +506,12 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter): def _http_request(self, url, method, **kwargs): kwargs.setdefault('user_agent', USER_AGENT) kwargs.setdefault('auth', self.auth) + if isinstance(self.endpoint_override, six.string_types): + kwargs.setdefault( + 'endpoint_override', + _trim_endpoint_api_version(self.endpoint_override) + ) + if getattr(self, 'os_ironic_api_version', None): kwargs['headers'].setdefault('X-OpenStack-Ironic-API-Version', self.os_ironic_api_version) diff --git a/ironicclient/tests/unit/common/test_http.py b/ironicclient/tests/unit/common/test_http.py index 1c248f922..d3e1531b4 100644 --- a/ironicclient/tests/unit/common/test_http.py +++ b/ironicclient/tests/unit/common/test_http.py @@ -49,8 +49,8 @@ def _session_client(**kwargs): max_retries=5, retry_interval=2, auth=None, - interface=None, - service_type='publicURL', + interface='publicURL', + service_type='baremetal', region_name='', endpoint='http://%s:%s' % (DEFAULT_HOST, DEFAULT_PORT), @@ -503,6 +503,47 @@ class SessionClientTest(utils.BaseTestCase): result = client._parse_version_headers(fake_session) self.assertEqual(expected_result, result) + def _test_endpoint_override(self, endpoint): + fake_session = utils.FakeSession({'content-type': 'application/json'}, + status_code=http_client.NO_CONTENT) + request_mock = mock.Mock() + fake_session.request = request_mock + request_mock.return_value = utils.FakeSessionResponse( + headers={'content-type': 'application/json'}, + status_code=http_client.NO_CONTENT) + client = _session_client(session=fake_session, + endpoint_override=endpoint) + client.json_request('DELETE', '/v1/nodes/aa/maintenance') + expected_args_dict = { + 'headers': { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-OpenStack-Ironic-API-Version': '1.6' + }, + 'auth': None, 'user_agent': 'python-ironicclient', + 'endpoint_filter': { + 'interface': 'publicURL', + 'service_type': 'baremetal', + 'region_name': '' + } + } + if isinstance(endpoint, six.string_types): + trimmed = http._trim_endpoint_api_version(endpoint) + expected_args_dict['endpoint_override'] = trimmed + request_mock.assert_called_once_with( + '/v1/nodes/aa/maintenance', 'DELETE', raise_exc=False, + **expected_args_dict + ) + + def test_endpoint_override(self): + self._test_endpoint_override('http://1.0.0.1:6385') + + def test_endpoint_override_with_version(self): + self._test_endpoint_override('http://1.0.0.1:6385/v1') + + def test_endpoint_override_not_valid(self): + self._test_endpoint_override(True) + @mock.patch.object(time, 'sleep', lambda *_: None) class RetriesTestCase(utils.BaseTestCase): diff --git a/releasenotes/notes/session-client-endpoint-override-20f1d822b4430afa.yaml b/releasenotes/notes/session-client-endpoint-override-20f1d822b4430afa.yaml new file mode 100644 index 000000000..1d11aed2e --- /dev/null +++ b/releasenotes/notes/session-client-endpoint-override-20f1d822b4430afa.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - Fixes an issue when SessionClient ignores endpoint_override while doing + session requests, which leads to undeterministic results in multi-region + deployments.