def test__http_request_client_fallback_success(self, mock_getcon, mock_negotiate): # Test when fallback to a supported version succeeds mock_negotiate.return_value = '1.6' error_body = _get_error_body() bad_resp = utils.FakeResponse( { 'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO(error_body), version=1, status=406) good_resp = utils.FakeResponse( { 'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO("We got some text"), version=1, status=200) client = http.HTTPClient('http://localhost/') mock_getcon.side_effect = iter( [utils.FakeConnection(bad_resp), utils.FakeConnection(good_resp)]) response, body_iter = client._http_request('/v1/resources', 'GET') self.assertEqual(200, response.status) self.assertEqual(1, mock_negotiate.call_count)
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_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 __init__(self, *args, **kwargs): """Initialize a new client for the Ironic v1 API.""" self.http_client = http.HTTPClient(*args, **kwargs) self.chassis = chassis.ChassisManager(self.http_client) self.node = node.NodeManager(self.http_client) self.port = port.PortManager(self.http_client) self.driver = driver.DriverManager(self.http_client)
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.FakeSessionResponse( {'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO(error_body), version=1, status_code=http_client.NOT_ACCEPTABLE) good_resp = utils.FakeSessionResponse( {'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO("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)
def test_log_curl_request_mask_password(self, mock_log): client = http.HTTPClient('http://localhost/') kwargs = {'headers': {'foo-header': 'bar-header'}, 'body': '{"password": "******"}'} client.log_curl_request('foo', 'http://127.0.0.1', kwargs) expected_log = ("curl -i -X foo -H 'foo-header: bar-header' " "-d '{\"password\": \"***\"}' http://127.0.0.1") mock_log.assert_called_once_with(expected_log)
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": "******"}' 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_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)
def test_server_https_request_ok(self): client = http.HTTPClient('https://localhost/') client.session = utils.FakeSession( {'Content-Type': 'application/json'}, six.StringIO("Body"), version=1, status_code=http_client.OK) client.json_request('GET', '/v1/resources')
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_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_http_max_retries_none(self, mock_getcon): error_body = _get_error_body() bad_resp = utils.FakeResponse({'content-type': 'text/plain'}, six.StringIO(error_body), version=1, status=409) client = http.HTTPClient('http://localhost/', max_retries=None) mock_getcon.return_value = utils.FakeConnection(bad_resp) self.assertRaises(exc.Conflict, client._http_request, '/v1/resources', 'GET') self.assertEqual(http.DEFAULT_MAX_RETRIES + 1, mock_getcon.call_count)
def test_401_unauthorized_exception(self): error_body = _get_error_body() client = http.HTTPClient('http://localhost/') client.session = utils.FakeSession( {'Content-Type': 'text/plain'}, six.StringIO(error_body), version=1, status_code=http_client.UNAUTHORIZED) self.assertRaises(exc.Unauthorized, client.json_request, 'GET', '/v1/resources')
def test_http_retry_connection_refused(self, mock_getcon): good_resp = utils.FakeResponse({'content-type': 'text/plain'}, six.StringIO("meow"), version=1, status=200) client = http.HTTPClient('http://localhost/') mock_getcon.side_effect = iter( (exc.ConnectionRefused(), utils.FakeConnection(good_resp))) response, body_iter = client._http_request('/v1/resources', 'GET') self.assertEqual(200, response.status) self.assertEqual(2, mock_getcon.call_count)
def test_401_unauthorized_exception(self): error_body = _get_error_body() fake_resp = utils.FakeResponse({'content-type': 'text/plain'}, six.StringIO(error_body), version=1, status=401) client = http.HTTPClient('http://localhost/') client.get_connection = ( lambda *a, **kw: utils.FakeConnection(fake_resp)) self.assertRaises(exc.Unauthorized, 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.FakeSession( {'Content-Type': 'application/json'}, six.StringIO(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_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])
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])
def test_server_exception_empty_body(self): error_body = _get_error_body() fake_resp = utils.FakeResponse({'content-type': 'application/json'}, six.StringIO(error_body), version=1, status=500) client = http.HTTPClient('http://localhost/') client.get_connection = ( lambda *a, **kw: utils.FakeConnection(fake_resp)) error = self.assertRaises(exc.InternalServerError, client.json_request, 'GET', '/v1/resources') self.assertEqual('Internal Server Error (HTTP 500)', str(error))
def test_server_https_empty_body(self): error_body = _get_error_body() client = http.HTTPClient('https://localhost/') client.session = utils.FakeSession( {'Content-Type': 'application/json'}, six.StringIO(error_body), version=1, status_code=http_client.INTERNAL_SERVER_ERROR) error = self.assertRaises(exc.InternalServerError, client.json_request, 'GET', '/v1/resources') self.assertEqual('Internal Server Error (HTTP 500)', str(error))
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])
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)
def test_http_no_retry(self): error_body = _get_error_body() bad_resp = utils.FakeSessionResponse( {'Content-Type': 'text/plain'}, six.StringIO(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__parse_version_headers(self): # Test parsing of version headers from HTTPClient error_body = _get_error_body() fake_resp = utils.FakeResponse( {'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO(error_body), version=1, status=406) expected_result = ('1.1', '1.6') client = http.HTTPClient('http://localhost/') result = client._parse_version_headers(fake_resp) self.assertEqual(expected_result, result)
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_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__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)
def test__http_request_client_fallback_fail(self, mock_getcon): # Test when fallback to a supported version fails error_body = _get_error_body() fake_resp = utils.FakeResponse( {'X-OpenStack-Ironic-API-Minimum-Version': '1.1', 'X-OpenStack-Ironic-API-Maximum-Version': '1.6', 'content-type': 'text/plain', }, six.StringIO(error_body), version=1, status=406) client = http.HTTPClient('http://localhost/') mock_getcon.return_value = utils.FakeConnection(fake_resp) self.assertRaises( exc.UnsupportedVersion, client._http_request, '/v1/resources', 'GET')
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)