# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import socket import mock import testtools from karborclient.common.apiclient import exceptions as exc from karborclient.common import http from karborclient.tests.unit import fakes @mock.patch('karborclient.common.http.requests.request') class HttpClientTest(testtools.TestCase): # Patch os.environ to avoid required auth info. def setUp(self): super(HttpClientTest, self).setUp() def test_http_raw_request(self, mock_request): headers = {'User-Agent': 'python-karborclient'} mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {}, '') client = http.HTTPClient('http://example.com:8082') resp = client.raw_request('GET', '') self.assertEqual(200, resp.status_code) self.assertEqual('', ''.join([x for x in resp.content])) mock_request.assert_called_with('GET', 'http://example.com:8082', allow_redirects=False, headers=headers) def test_token_or_credentials(self, mock_request): # Record a 200 fake200 = fakes.FakeHTTPResponse( 200, 'OK', {}, '') mock_request.side_effect = [fake200, fake200, fake200] # Replay, create client, assert client = http.HTTPClient('http://example.com:8082') resp = client.raw_request('GET', '') self.assertEqual(200, resp.status_code) client.username = 'user' client.password = 'pass' resp = client.raw_request('GET', '') self.assertEqual(200, resp.status_code) client.auth_token = 'abcd1234' resp = client.raw_request('GET', '') self.assertEqual(200, resp.status_code) # no token or credentials mock_request.assert_has_calls([ mock.call('GET', 'http://example.com:8082', allow_redirects=False, headers={'User-Agent': 'python-karborclient'}), mock.call('GET', 'http://example.com:8082', allow_redirects=False, headers={'User-Agent': 'python-karborclient', 'X-Auth-Key': 'pass', 'X-Auth-User': 'user'}), mock.call('GET', 'http://example.com:8082', allow_redirects=False, headers={'User-Agent': 'python-karborclient', 'X-Auth-Token': 'abcd1234'}) ]) def test_region_name(self, mock_request): # Record a 200 fake200 = fakes.FakeHTTPResponse( 200, 'OK', {}, '') mock_request.return_value = fake200 client = http.HTTPClient('http://example.com:8082') client.region_name = 'RegionOne' resp = client.raw_request('GET', '') self.assertEqual(200, resp.status_code) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'X-Region-Name': 'RegionOne', 'User-Agent': 'python-karborclient'}) def test_http_json_request(self, mock_request): # Record a 200 mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082') resp, body = client.json_request('GET', '') self.assertEqual(200, resp.status_code) self.assertEqual({}, body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_json_request_argument_passed_to_requests(self, mock_request): """Check that we have sent the proper arguments to requests.""" # Record a 200 mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082') client.verify_cert = True client.cert_file = 'RANDOM_CERT_FILE' client.key_file = 'RANDOM_KEY_FILE' client.auth_url = 'http://AUTH_URL' resp, body = client.json_request('GET', '', data='text') self.assertEqual(200, resp.status_code) self.assertEqual({}, body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, cert=('RANDOM_CERT_FILE', 'RANDOM_KEY_FILE'), verify=True, data='"text"', headers={'Content-Type': 'application/json', 'X-Auth-Url': 'http://AUTH_URL', 'User-Agent': 'python-karborclient'}) def test_http_json_request_w_req_body(self, mock_request): # Record a 200 mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082') resp, body = client.json_request('GET', '', data='test-body') self.assertEqual(200, resp.status_code) self.assertEqual({}, body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', data='"test-body"', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_json_request_non_json_resp_cont_type(self, mock_request): # Record a 200 mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'not/json'}, '{}') client = http.HTTPClient('http://example.com:8082') resp, body = client.json_request('GET', '', data='test-data') self.assertEqual(200, resp.status_code) self.assertIsNone(body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', data='"test-data"', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_json_request_invalid_json(self, mock_request): # Record a 200 mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, 'invalid-json') client = http.HTTPClient('http://example.com:8082') resp, body = client.json_request('GET', '') self.assertEqual(200, resp.status_code) self.assertEqual('invalid-json', body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_manual_redirect_delete(self, mock_request): mock_request.side_effect = [ fakes.FakeHTTPResponse( 302, 'Found', {'location': 'http://example.com:8082/foo/bar'}, ''), fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}')] client = http.HTTPClient('http://example.com:8082/foo') resp, body = client.json_request('DELETE', '') self.assertEqual(200, resp.status_code) mock_request.assert_has_calls([ mock.call('DELETE', 'http://example.com:8082/foo', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}), mock.call('DELETE', 'http://example.com:8082/foo/bar', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) ]) def test_http_manual_redirect_post(self, mock_request): mock_request.side_effect = [ fakes.FakeHTTPResponse( 302, 'Found', {'location': 'http://example.com:8082/foo/bar'}, ''), fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}')] client = http.HTTPClient('http://example.com:8082/foo') resp, body = client.json_request('POST', '') self.assertEqual(200, resp.status_code) mock_request.assert_has_calls([ mock.call('POST', 'http://example.com:8082/foo', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}), mock.call('POST', 'http://example.com:8082/foo/bar', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) ]) def test_http_manual_redirect_put(self, mock_request): mock_request.side_effect = [ fakes.FakeHTTPResponse( 302, 'Found', {'location': 'http://example.com:8082/foo/bar'}, ''), fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}')] client = http.HTTPClient('http://example.com:8082/foo') resp, body = client.json_request('PUT', '') self.assertEqual(200, resp.status_code) mock_request.assert_has_calls([ mock.call('PUT', 'http://example.com:8082/foo', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}), mock.call('PUT', 'http://example.com:8082/foo/bar', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) ]) def test_http_manual_redirect_prohibited(self, mock_request): mock_request.return_value = \ fakes.FakeHTTPResponse( 302, 'Found', {'location': 'http://example.com:8082/'}, '') client = http.HTTPClient('http://example.com:8082/foo') self.assertRaises(exc.EndpointException, client.json_request, 'DELETE', '') mock_request.assert_called_once_with( 'DELETE', 'http://example.com:8082/foo', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_manual_redirect_error_without_location(self, mock_request): mock_request.return_value = \ fakes.FakeHTTPResponse( 302, 'Found', {}, '') client = http.HTTPClient('http://example.com:8082/foo') self.assertRaises(exc.EndpointException, client.json_request, 'DELETE', '') mock_request.assert_called_once_with( 'DELETE', 'http://example.com:8082/foo', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_json_request_redirect(self, mock_request): # Record the 302 mock_request.side_effect = [ fakes.FakeHTTPResponse( 302, 'Found', {'location': 'http://example.com:8082'}, ''), fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}')] client = http.HTTPClient('http://example.com:8082') resp, body = client.json_request('GET', '') self.assertEqual(200, resp.status_code) self.assertEqual({}, body) mock_request.assert_has_calls([ mock.call('GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}), mock.call('GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) ]) def test_http_404_json_request(self, mock_request): mock_request.return_value = \ fakes.FakeHTTPResponse( 404, 'Not Found', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082') e = self.assertRaises(exc.HTTPClientError, client.json_request, 'GET', '') # Assert that the raised exception can be converted to string self.assertIsNotNone(str(e)) # Record a 404 mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_http_300_json_request(self, mock_request): mock_request.return_value = \ fakes.FakeHTTPResponse( 300, 'OK', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082') e = self.assertRaises( exc.MultipleChoices, client.json_request, 'GET', '') # Assert that the raised exception can be converted to string self.assertIsNotNone(str(e)) # Record a 300 mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}) def test_fake_json_request(self, mock_request): headers = {'User-Agent': 'python-karborclient'} mock_request.side_effect = [socket.gaierror] client = http.HTTPClient('fake://example.com:8082') self.assertRaises(exc.EndpointException, client._http_request, "/", "GET") mock_request.assert_called_once_with('GET', 'fake://example.com:8082/', allow_redirects=False, headers=headers) def test_http_request_socket_error(self, mock_request): headers = {'User-Agent': 'python-karborclient'} mock_request.side_effect = [socket.gaierror] client = http.HTTPClient('http://example.com:8082') self.assertRaises(exc.EndpointException, client._http_request, "/", "GET") mock_request.assert_called_once_with('GET', 'http://example.com:8082/', allow_redirects=False, headers=headers) def test_http_request_socket_timeout(self, mock_request): headers = {'User-Agent': 'python-karborclient'} mock_request.side_effect = [socket.timeout] client = http.HTTPClient('http://example.com:8082') self.assertRaises(exc.ConnectionRefused, client._http_request, "/", "GET") mock_request.assert_called_once_with('GET', 'http://example.com:8082/', allow_redirects=False, headers=headers) def test_http_request_specify_timeout(self, mock_request): mock_request.return_value = \ fakes.FakeHTTPResponse( 200, 'OK', {'content-type': 'application/json'}, '{}') client = http.HTTPClient('http://example.com:8082', timeout='123') resp, body = client.json_request('GET', '') self.assertEqual(200, resp.status_code) self.assertEqual({}, body) mock_request.assert_called_once_with( 'GET', 'http://example.com:8082', allow_redirects=False, headers={'Content-Type': 'application/json', 'User-Agent': 'python-karborclient'}, timeout=float(123)) def test_get_system_ca_file(self, mock_request): chosen = '/etc/ssl/certs/ca-certificates.crt' with mock.patch('os.path.exists') as mock_os: mock_os.return_value = chosen ca = http.get_system_ca_file() self.assertEqual(chosen, ca) mock_os.assert_called_once_with(chosen) def test_insecure_verify_cert_None(self, mock_request): client = http.HTTPClient('https://foo', insecure=True) self.assertFalse(client.verify_cert) def test_passed_cert_to_verify_cert(self, mock_request): client = http.HTTPClient('https://foo', cacert="NOWHERE") self.assertEqual("NOWHERE", client.verify_cert) with mock.patch('karborclient.common.http.get_system_ca_file') as gsf: gsf.return_value = "SOMEWHERE" client = http.HTTPClient('https://foo') self.assertEqual("SOMEWHERE", client.verify_cert)