Remove deprecated common.http.HTTPClient class

The class common.http.HTTPClient is deprecated and merked for
removal in Stein.
This patch removes it entirely, the class common.http.SessionClient
should be used instead.

Change-Id: I527d39d64c3ded9f61babcdf07d0492799b76fb9
Story: 2006422
Task: 36314
This commit is contained in:
Riccardo Pittau 2019-06-19 14:36:44 +02:00 committed by Julia Kreger
parent a3c71f06ad
commit 6fd8ee46e8
4 changed files with 27 additions and 699 deletions

View File

@ -13,9 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from distutils.version import StrictVersion
import hashlib
import logging
import os
import re
@ -27,8 +25,6 @@ import time
from keystoneauth1 import adapter
from keystoneauth1 import exceptions as kexc
from oslo_serialization import jsonutils
from oslo_utils import strutils
import requests
import six
from six.moves import http_client
import six.moves.urllib.parse as urlparse
@ -305,224 +301,6 @@ def with_retries(func):
return wrapper
class HTTPClient(VersionNegotiationMixin):
def __init__(self, endpoint, **kwargs):
LOG.warning('HTTPClient class is deprecated and will be removed '
'in Stein release, please use SessionClient instead.')
self.endpoint = endpoint
self.endpoint_trimmed = _trim_endpoint_api_version(endpoint)
self.auth_token = kwargs.get('token')
self.auth_ref = kwargs.get('auth_ref')
self.os_ironic_api_version = kwargs.get('os_ironic_api_version',
DEFAULT_VER)
self.api_version_select_state = kwargs.get(
'api_version_select_state', 'default')
self.conflict_max_retries = kwargs.pop('max_retries',
DEFAULT_MAX_RETRIES)
self.conflict_retry_interval = kwargs.pop('retry_interval',
DEFAULT_RETRY_INTERVAL)
self.session = requests.Session()
parts = urlparse.urlparse(endpoint)
if parts.scheme not in SUPPORTED_ENDPOINT_SCHEME:
msg = _('Unsupported scheme: %s') % parts.scheme
raise exc.EndpointException(msg)
if parts.scheme == 'https':
if kwargs.get('insecure') is True:
self.session.verify = False
elif kwargs.get('ca_file'):
self.session.verify = kwargs['ca_file']
self.session.cert = (kwargs.get('cert_file'),
kwargs.get('key_file'))
def _process_header(self, name, value):
"""Redacts any sensitive header
Redact a header that contains sensitive information, by returning an
updated header with the sha1 hash of that value. The redacted value is
prefixed by '{SHA1}' because that's the convention used within
OpenStack.
:returns: A tuple of (name, value)
name: the safe encoding format of name
value: the redacted value if name is x-auth-token,
or the safe encoding format of name
"""
if name in SENSITIVE_HEADERS:
v = value.encode('utf-8')
h = hashlib.sha1(v)
d = h.hexdigest()
return (name, "{SHA1}%s" % d)
else:
return (name, value)
def log_curl_request(self, method, url, kwargs):
curl = ['curl -i -X %s' % method]
for (key, value) in kwargs['headers'].items():
header = '-H \'%s: %s\'' % self._process_header(key, value)
curl.append(header)
if not self.session.verify:
curl.append('-k')
elif isinstance(self.session.verify, six.string_types):
curl.append('--cacert %s' % self.session.verify)
if self.session.cert:
curl.append('--cert %s' % self.session.cert[0])
curl.append('--key %s' % self.session.cert[1])
if 'body' in kwargs:
body = strutils.mask_password(kwargs['body'])
curl.append('-d \'%s\'' % body)
curl.append(self._make_connection_url(url))
LOG.debug(' '.join(curl))
@staticmethod
def log_http_response(resp, body=None):
# NOTE(aarefiev): resp.raw is urllib3 response object, it's used
# only to get 'version', response from request with 'stream = True'
# should be used for raw reading.
status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
dump = ['\nHTTP/%.1f %s %s' % status]
dump.extend(['%s: %s' % (k, v) for k, v in resp.headers.items()])
dump.append('')
if body:
body = strutils.mask_password(body)
dump.extend([body, ''])
LOG.debug('\n'.join(dump))
def _make_connection_url(self, url):
# NOTE(pas-ha) we already stripped trailing / from endpoint_trimmed
if not url.startswith('/'):
url = '/' + url
return self.endpoint_trimmed + url
def _parse_version_headers(self, resp):
return self._generic_parse_version_headers(resp.headers.get)
def _make_simple_request(self, conn, method, url):
return conn.request(method, self._make_connection_url(url))
@with_retries
def _http_request(self, url, method, **kwargs):
"""Send an http request with the specified characteristics.
Wrapper around request.Session.request to handle tasks such
as setting headers and error handling.
"""
# NOTE(TheJulia): self.os_ironic_api_version is reset in
# the self.negotiate_version() call if negotiation occurs.
if self.os_ironic_api_version and self._must_negotiate_version():
self.negotiate_version(self.session, None)
# Copy the kwargs so we can reuse the original in case of redirects
kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
kwargs['headers'].setdefault('User-Agent', USER_AGENT)
if self.os_ironic_api_version:
kwargs['headers'].setdefault('X-OpenStack-Ironic-API-Version',
self.os_ironic_api_version)
if self.auth_token:
kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)
self.log_curl_request(method, url, kwargs)
# NOTE(aarefiev): This is for backwards compatibility, request
# expected body in 'data' field, previously we used httplib,
# which expected 'body' field.
body = kwargs.pop('body', None)
if body:
kwargs['data'] = body
conn_url = self._make_connection_url(url)
try:
resp = self.session.request(method,
conn_url,
**kwargs)
# TODO(deva): implement graceful client downgrade when connecting
# to servers that did not support microversions. Details here:
# https://specs.openstack.org/openstack/ironic-specs/specs/kilo-implemented/api-microversions.html#use-case-3b-new-client-communicating-with-a-old-ironic-user-specified # noqa
if resp.status_code == http_client.NOT_ACCEPTABLE:
negotiated_ver = self.negotiate_version(self.session, resp)
kwargs['headers']['X-OpenStack-Ironic-API-Version'] = (
negotiated_ver)
return self._http_request(url, method, **kwargs)
except requests.exceptions.RequestException as e:
message = (_("Error has occurred while handling "
"request for %(url)s: %(e)s") %
dict(url=conn_url, e=e))
# NOTE(aarefiev): not valid request(invalid url, missing schema,
# and so on), retrying is not needed.
if isinstance(e, ValueError):
raise exc.ValidationError(message)
raise exc.ConnectionRefused(message)
body_str = None
if resp.headers.get('Content-Type') == 'application/octet-stream':
body_iter = resp.iter_content(chunk_size=CHUNKSIZE)
self.log_http_response(resp)
else:
# Read body into string if it isn't obviously image data
body_str = resp.text
self.log_http_response(resp, body_str)
body_iter = six.StringIO(body_str)
if resp.status_code >= http_client.BAD_REQUEST:
error_json = _extract_error_json(body_str)
raise exc.from_response(
resp, error_json.get('error_message'),
error_json.get('debuginfo'), method, url)
elif resp.status_code in (http_client.MOVED_PERMANENTLY,
http_client.FOUND,
http_client.USE_PROXY):
# Redirected. Reissue the request to the new location.
return self._http_request(resp['location'], method, **kwargs)
elif resp.status_code == http_client.MULTIPLE_CHOICES:
raise exc.from_response(resp, method=method, url=url)
return resp, body_iter
def json_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type', 'application/json')
kwargs['headers'].setdefault('Accept', 'application/json')
if 'body' in kwargs:
kwargs['body'] = jsonutils.dump_as_bytes(kwargs['body'])
resp, body_iter = self._http_request(url, method, **kwargs)
content_type = resp.headers.get('Content-Type')
if (resp.status_code in (http_client.NO_CONTENT,
http_client.RESET_CONTENT)
or content_type is None):
return resp, list()
if 'application/json' in content_type:
body = ''.join([chunk for chunk in body_iter])
try:
body = jsonutils.loads(body)
except ValueError:
LOG.error('Could not decode response body as JSON')
else:
body = None
return resp, body
def raw_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
'application/octet-stream')
return self._http_request(url, method, **kwargs)
class VerifiedHTTPSConnection(six.moves.http_client.HTTPSConnection):
"""httplib-compatible connection using client-side SSL authentication
@ -722,49 +500,30 @@ def _construct_http_client(session=None,
key_file=None,
insecure=None,
**kwargs):
if session:
kwargs.setdefault('service_type', 'baremetal')
kwargs.setdefault('user_agent', 'python-ironicclient')
kwargs.setdefault('interface', kwargs.pop('endpoint_type',
'publicURL'))
ignored = {'token': token,
'auth_ref': auth_ref,
'timeout': timeout != 600,
'ca_file': ca_file,
'cert_file': cert_file,
'key_file': key_file,
'insecure': insecure}
kwargs.setdefault('service_type', 'baremetal')
kwargs.setdefault('user_agent', 'python-ironicclient')
kwargs.setdefault('interface', kwargs.pop('endpoint_type',
'publicURL'))
dvars = [k for k, v in ignored.items() if v]
ignored = {'token': token,
'auth_ref': auth_ref,
'timeout': timeout != 600,
'ca_file': ca_file,
'cert_file': cert_file,
'key_file': key_file,
'insecure': insecure}
if dvars:
LOG.warning('The following arguments are ignored when using '
'the session to construct a client: %s',
', '.join(dvars))
dvars = [k for k, v in ignored.items() if v]
return SessionClient(session=session,
os_ironic_api_version=os_ironic_api_version,
api_version_select_state=api_version_select_state,
max_retries=max_retries,
retry_interval=retry_interval,
**kwargs)
else:
endpoint = None
if kwargs:
endpoint = kwargs.pop('endpoint_override', None)
LOG.warning('The following arguments are being ignored when '
'constructing the client: %s', ', '.join(kwargs))
if dvars:
LOG.warning('The following arguments are ignored when using '
'the session to construct a client: %s',
', '.join(dvars))
return HTTPClient(endpoint=endpoint,
token=token,
auth_ref=auth_ref,
os_ironic_api_version=os_ironic_api_version,
api_version_select_state=api_version_select_state,
max_retries=max_retries,
retry_interval=retry_interval,
timeout=timeout,
ca_file=ca_file,
cert_file=cert_file,
key_file=key_file,
insecure=insecure)
return SessionClient(session=session,
os_ironic_api_version=os_ironic_api_version,
api_version_select_state=api_version_select_state,
max_retries=max_retries,
retry_interval=retry_interval,
**kwargs)

View File

@ -17,7 +17,6 @@ import time
import mock
from oslo_serialization import jsonutils
import requests
import six
from six.moves import http_client
@ -348,296 +347,6 @@ class VersionNegotiationMixinTest(utils.BaseTestCase):
self.assertEqual((host, port), http.get_server(endpoint))
class HttpClientTest(utils.BaseTestCase):
@mock.patch.object(http.LOG, 'warning', autospec=True)
def test_http_client_deprecation(self, log_mock):
http.HTTPClient('http://localhost')
self.assertIn('deprecated', log_mock.call_args[0][0])
def test_url_generation_trailing_slash_in_base(self):
client = http.HTTPClient('http://localhost/')
url = client._make_connection_url('/v1/resources')
self.assertEqual('http://localhost/v1/resources', url)
def test_url_generation_without_trailing_slash_in_base(self):
client = http.HTTPClient('http://localhost')
url = client._make_connection_url('/v1/resources')
self.assertEqual('http://localhost/v1/resources', url)
def test_url_generation_without_prefix_slash_in_path(self):
client = http.HTTPClient('http://localhost')
url = client._make_connection_url('v1/resources')
self.assertEqual('http://localhost/v1/resources', url)
def test_server_https_request_with_application_octet_stream(self):
client = http.HTTPClient('https://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/octet-stream'},
"Body",
version=1,
status_code=http_client.OK)
response, body = client.json_request('GET', '/v1/resources')
self.assertEqual(client.session.request.return_value, response)
self.assertIsNone(body)
def test_server_exception_empty_body(self):
error_body = _get_error_body()
client = http.HTTPClient('http://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/json'},
error_body,
version=1,
status_code=http_client.INTERNAL_SERVER_ERROR)
self.assertRaises(exc.InternalServerError,
client.json_request,
'GET', '/v1/resources')
def test_server_exception_msg_only(self):
error_msg = 'test error msg'
error_body = _get_error_body(error_msg)
client = http.HTTPClient('http://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/json'},
error_body,
version=1,
status_code=http_client.INTERNAL_SERVER_ERROR)
self.assertRaises(exc.InternalServerError,
client.json_request,
'GET', '/v1/resources')
def test_server_exception_description_only(self):
error_msg = 'test error msg'
error_body = _get_error_body(description=error_msg)
client = http.HTTPClient('http://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/json'},
error_body,
version=1,
status_code=http_client.BAD_REQUEST)
self.assertRaisesRegex(exc.BadRequest, 'test error msg',
client.json_request,
'GET', '/v1/resources')
def test_server_https_request_ok(self):
client = http.HTTPClient('https://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/json'},
"Body",
version=1,
status_code=http_client.OK)
client.json_request('GET', '/v1/resources')
def test_server_https_empty_body(self):
error_body = _get_error_body()
client = http.HTTPClient('https://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'application/json'},
error_body,
version=1,
status_code=http_client.INTERNAL_SERVER_ERROR)
self.assertRaises(exc.InternalServerError,
client.json_request,
'GET', '/v1/resources')
def test_401_unauthorized_exception(self):
error_body = _get_error_body()
client = http.HTTPClient('http://localhost/')
client.session = utils.mockSession(
{'Content-Type': 'text/plain'},
error_body,
version=1,
status_code=http_client.UNAUTHORIZED)
self.assertRaises(exc.Unauthorized, client.json_request,
'GET', '/v1/resources')
def test_http_request_not_valid_request(self):
client = http.HTTPClient('http://localhost/')
client.session.request = mock.Mock(
side_effect=http.requests.exceptions.InvalidSchema)
self.assertRaises(exc.ValidationError, client._http_request,
'http://localhost/', 'GET')
def test__parse_version_headers(self):
# Test parsing of version headers from HTTPClient
error_body = _get_error_body()
expected_result = ('1.1', '1.6')
client = http.HTTPClient('http://localhost/')
fake_resp = utils.mockSessionResponse(
{'X-OpenStack-Ironic-API-Minimum-Version': '1.1',
'X-OpenStack-Ironic-API-Maximum-Version': '1.6',
'Content-Type': 'text/plain',
},
error_body,
version=1,
status_code=http_client.NOT_ACCEPTABLE)
result = client._parse_version_headers(fake_resp)
self.assertEqual(expected_result, result)
@mock.patch.object(filecache, 'save_data', autospec=True)
def test__http_request_client_fallback_fail(self, mock_save_data):
# Test when fallback to a supported version fails
host, port, latest_ver = 'localhost', '1234', '1.6'
error_body = _get_error_body()
client = http.HTTPClient('http://%s:%s/' % (host, port))
client.session = utils.mockSession(
{'X-OpenStack-Ironic-API-Minimum-Version': '1.1',
'X-OpenStack-Ironic-API-Maximum-Version': latest_ver,
'content-type': 'text/plain',
},
error_body,
version=1,
status_code=http_client.NOT_ACCEPTABLE)
self.assertRaises(
exc.UnsupportedVersion,
client._http_request,
'/v1/resources',
'GET')
mock_save_data.assert_called_once_with(host=host, data=latest_ver,
port=port)
@mock.patch.object(http.VersionNegotiationMixin, 'negotiate_version',
autospec=False)
def test__http_request_client_fallback_success(self, mock_negotiate):
# Test when fallback to a supported version succeeds
mock_negotiate.return_value = '1.6'
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'X-OpenStack-Ironic-API-Minimum-Version': '1.1',
'X-OpenStack-Ironic-API-Maximum-Version': '1.6',
'content-type': 'text/plain',
},
error_body,
version=1,
status_code=http_client.NOT_ACCEPTABLE)
good_resp = utils.mockSessionResponse(
{'X-OpenStack-Ironic-API-Minimum-Version': '1.1',
'X-OpenStack-Ironic-API-Maximum-Version': '1.6',
'content-type': 'text/plain',
},
"We got some text",
version=1,
status_code=http_client.OK)
client = http.HTTPClient('http://localhost/')
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.side_effect = iter([bad_resp, good_resp])
response, body_iter = client._http_request('/v1/resources', 'GET')
self.assertEqual(http_client.OK, response.status_code)
self.assertEqual(1, mock_negotiate.call_count)
@mock.patch.object(requests.Session, 'request', autospec=True)
@mock.patch.object(http.VersionNegotiationMixin, 'negotiate_version',
autospec=False)
def test__http_request_explicit_version(self, mock_negotiate,
mock_session):
headers = {'User-Agent': 'python-ironicclient',
'X-OpenStack-Ironic-API-Version': '1.28'}
kwargs = {'os_ironic_api_version': '1.30',
'api_version_select_state': 'negotiated'}
mock_session.return_value = utils.mockSessionResponse(
{}, status_code=http_client.NO_CONTENT, version=1)
client = http.HTTPClient('http://localhost/', **kwargs)
response, body_iter = client._http_request('/v1/resources', 'GET',
headers=headers)
mock_session.assert_called_once_with(mock.ANY, 'GET',
'http://localhost/v1/resources',
headers=headers)
@mock.patch.object(http.LOG, 'debug', autospec=True)
def test_log_curl_request_mask_password(self, mock_log):
client = http.HTTPClient('http://localhost/')
kwargs = {'headers': {'foo-header': 'bar-header'},
'body': '{"password": "foo"}'}
client.log_curl_request('foo', '/v1/nodes', kwargs)
expected_log = ("curl -i -X foo -H 'foo-header: bar-header' "
"-d '{\"password\": \"***\"}' "
"http://localhost/v1/nodes")
mock_log.assert_called_once_with(expected_log)
@mock.patch.object(http.LOG, 'debug', autospec=True)
def test_log_http_response_mask_password(self, mock_log):
client = http.HTTPClient('http://localhost/')
fake_response = utils.FakeResponse({}, version=1, reason='foo',
status=200)
body = '{"password": "foo"}'
client.log_http_response(fake_response, body=body)
expected_log = ("\nHTTP/0.1 200 foo\n\n{\"password\": \"***\"}\n")
mock_log.assert_called_once_with(expected_log)
def test__https_init_ssl_args_insecure(self):
client = http.HTTPClient('https://localhost/', insecure=True)
self.assertEqual(False, client.session.verify)
def test__https_init_ssl_args_secure(self):
client = http.HTTPClient('https://localhost/', ca_file='test_ca',
key_file='test_key', cert_file='test_cert')
self.assertEqual('test_ca', client.session.verify)
self.assertEqual(('test_cert', 'test_key'), client.session.cert)
@mock.patch.object(http.LOG, 'debug', autospec=True)
def test_log_curl_request_with_body_and_header(self, mock_log):
client = http.HTTPClient('http://test')
headers = {'header1': 'value1'}
body = 'example body'
client.log_curl_request('GET', '/v1/nodes',
{'headers': headers, 'body': body})
self.assertTrue(mock_log.called)
self.assertTrue(mock_log.call_args[0])
self.assertEqual("curl -i -X GET -H 'header1: value1'"
" -d 'example body' http://test/v1/nodes",
mock_log.call_args[0][0])
@mock.patch.object(http.LOG, 'debug', autospec=True)
def test_log_curl_request_with_certs(self, mock_log):
headers = {'header1': 'value1'}
client = http.HTTPClient('https://test', key_file='key',
cert_file='cert', cacert='cacert',
token='fake-token')
client.log_curl_request('GET', '/v1/test', {'headers': headers})
self.assertTrue(mock_log.called)
self.assertTrue(mock_log.call_args[0])
self.assertEqual("curl -i -X GET -H 'header1: value1' "
"--cert cert --key key https://test/v1/test",
mock_log.call_args[0][0])
@mock.patch.object(http.LOG, 'debug', autospec=True)
def test_log_curl_request_with_insecure_param(self, mock_log):
headers = {'header1': 'value1'}
http_client_object = http.HTTPClient('https://test', insecure=True,
token='fake-token')
http_client_object.log_curl_request('GET', '/v1/test',
{'headers': headers})
self.assertTrue(mock_log.called)
self.assertTrue(mock_log.call_args[0])
self.assertEqual("curl -i -X GET -H 'header1: value1' -k "
"--cert None --key None https://test/v1/test",
mock_log.call_args[0][0])
class SessionClientTest(utils.BaseTestCase):
@mock.patch.object(http.LOG, 'warning', autospec=True)
@ -750,136 +459,6 @@ class SessionClientTest(utils.BaseTestCase):
@mock.patch.object(time, 'sleep', lambda *_: None)
class RetriesTestCase(utils.BaseTestCase):
def test_http_no_retry(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'Content-Type': 'text/plain'},
error_body,
version=1,
status_code=http_client.CONFLICT)
client = http.HTTPClient('http://localhost/', max_retries=0)
with mock.patch.object(client.session, 'request', autospec=True,
return_value=bad_resp) as mock_request:
self.assertRaises(exc.Conflict, client._http_request,
'/v1/resources', 'GET')
self.assertEqual(1, mock_request.call_count)
def test_http_retry(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'Content-Type': 'text/plain'},
error_body,
version=1,
status_code=http_client.CONFLICT)
good_resp = utils.mockSessionResponse(
{'Content-Type': 'text/plain'},
"meow",
version=1,
status_code=http_client.OK)
client = http.HTTPClient('http://localhost/')
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.side_effect = iter([bad_resp, good_resp])
response, body_iter = client._http_request('/v1/resources', 'GET')
self.assertEqual(http_client.OK, response.status_code)
self.assertEqual(2, mock_session.request.call_count)
def test_http_retry_503(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'Content-Type': 'text/plain'},
error_body,
version=1,
status_code=http_client.SERVICE_UNAVAILABLE)
good_resp = utils.mockSessionResponse(
{'Content-Type': 'text/plain'},
"meow",
version=1,
status_code=http_client.OK)
client = http.HTTPClient('http://localhost/')
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.side_effect = iter([bad_resp, good_resp])
response, body_iter = client._http_request('/v1/resources', 'GET')
self.assertEqual(http_client.OK, response.status_code)
self.assertEqual(2, mock_session.request.call_count)
def test_http_retry_connection_refused(self):
good_resp = utils.mockSessionResponse(
{'content-type': 'text/plain'},
"meow",
version=1,
status_code=http_client.OK)
client = http.HTTPClient('http://localhost/')
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.side_effect = iter([exc.ConnectionRefused(),
good_resp])
response, body_iter = client._http_request('/v1/resources', 'GET')
self.assertEqual(http_client.OK, response.status_code)
self.assertEqual(2, mock_session.request.call_count)
def test_http_failed_retry(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'content-type': 'text/plain'},
error_body,
version=1,
status_code=http_client.CONFLICT)
client = http.HTTPClient('http://localhost/')
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.return_value = bad_resp
self.assertRaises(exc.Conflict, client._http_request,
'/v1/resources', 'GET')
self.assertEqual(http.DEFAULT_MAX_RETRIES + 1,
mock_session.request.call_count)
def test_http_max_retries_none(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'content-type': 'text/plain'},
error_body,
version=1,
status_code=http_client.CONFLICT)
client = http.HTTPClient('http://localhost/', max_retries=None)
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.return_value = bad_resp
self.assertRaises(exc.Conflict, client._http_request,
'/v1/resources', 'GET')
self.assertEqual(http.DEFAULT_MAX_RETRIES + 1,
mock_session.request.call_count)
def test_http_change_max_retries(self):
error_body = _get_error_body()
bad_resp = utils.mockSessionResponse(
{'content-type': 'text/plain'},
error_body,
version=1,
status_code=http_client.CONFLICT)
client = http.HTTPClient('http://localhost/',
max_retries=http.DEFAULT_MAX_RETRIES + 1)
with mock.patch.object(client, 'session',
autospec=True) as mock_session:
mock_session.request.return_value = bad_resp
self.assertRaises(exc.Conflict, client._http_request,
'/v1/resources', 'GET')
self.assertEqual(http.DEFAULT_MAX_RETRIES + 2,
mock_session.request.call_count)
def test_session_retry(self):
error_body = _get_error_body()

View File

@ -490,18 +490,3 @@ class ClientTest(utils.BaseTestCase):
'interface': None}
)
self.assertFalse(mock_ks_session.called)
def test_safe_header_with_auth_token(self):
(name, value) = ('X-Auth-Token', u'3b640e2e64d946ac8f55615aff221dc1')
expected_header = (u'X-Auth-Token',
'{SHA1}6de9fb3b0b89099030a54abfeb468e7b1b1f0f2b')
client = http.HTTPClient('http://localhost/')
header_redact = client._process_header(name, value)
self.assertEqual(expected_header, header_redact)
def test_safe_header_with_no_auth_token(self):
name, value = ('Accept', 'application/json')
header = ('Accept', 'application/json')
client = http.HTTPClient('http://localhost/')
header_redact = client._process_header(name, value)
self.assertEqual(header, header_redact)

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
Removes deprecated ``common.http.HTTPClient`` class.
The ``common.http.SessionClient`` class should be used instead.