From 6bf8f0a2284e4b9be477be7ebb497f9d2381d393 Mon Sep 17 00:00:00 2001 From: Maxime Belanger Date: Thu, 31 Mar 2016 14:13:34 -0400 Subject: [PATCH] Added more Ubersmith exceptions: - Timeout Exceptions - Connection Errors --- tests/api_test.py | 120 +++------------------------ tests/ubersmith_request_get_test.py | 76 +++++++++++++++++ tests/ubersmith_request_post_test.py | 87 +++++++++++++++++++ ubersmith_client/exceptions.py | 11 +++ ubersmith_client/ubersmith_api.py | 10 ++- 5 files changed, 195 insertions(+), 109 deletions(-) create mode 100644 tests/ubersmith_request_get_test.py create mode 100644 tests/ubersmith_request_post_test.py diff --git a/tests/api_test.py b/tests/api_test.py index 5bd2bb9..82e11f8 100644 --- a/tests/api_test.py +++ b/tests/api_test.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. import unittest -from mock import patch, MagicMock +from hamcrest import assert_that, raises, calling +from mock import Mock +from requests.exceptions import ConnectionError, Timeout -from hamcrest import assert_that, equal_to, raises, calling - -from tests.ubersmith_json.response_data_structure import a_response_data import ubersmith_client +from ubersmith_client.exceptions import UbersmithConnectionError, UbersmithTimeout class ApiTest(unittest.TestCase): @@ -26,110 +26,14 @@ def setUp(self): self.username = 'admin' self.password = 'test' - self.auth = (self.username, self.password) - self.timeout = 60 - - @patch('ubersmith_client.ubersmith_request_get.requests') - def test_api_get_method_returns_without_arguments(self, requests_mock): - json_data = { - 'company': 'council of ricks' - } - expected_call = self.expect_a_ubersmith_call(requests_mock=requests_mock, - method='client.list', - returning=a_response_data(data=json_data)) - - ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=True) - response = ubersmith_api.client.list() - - assert_that(response, equal_to(json_data)) - - expected_call() - - @patch('ubersmith_client.ubersmith_request_get.requests') - def test_api_get_method_returns_with_arguments(self, request_mock): - json_data = { - 'group_id': '1', - 'client_id': '30001', - 'assignment_count': '1' - } - expected_call = self.expect_a_ubersmith_call(requests_mock=request_mock, - method='device.ip_group_list', - fac_id=1, - client_id=30001, - returning=a_response_data(data=json_data)) - - ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=True) - response = ubersmith_api.device.ip_group_list(fac_id=1, client_id=30001) - - assert_that(response, equal_to(json_data)) - - expected_call() - - @patch('ubersmith_client.ubersmith_request_post.requests') - def test_api_post_method_returns_with_arguments(self, request_mock): - json_data = { - 'group_id': '1', - 'client_id': '30001', - 'assignment_count': '1' - } - expected_call = self.expect_a_ubersmith_call_post(requests_mock=request_mock, - method='device.ip_group_list', - fac_id=1, - client_id=30001, - returning=a_response_data(data=json_data)) - - ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=False) - response = ubersmith_api.device.ip_group_list(fac_id=1, client_id=30001) - - assert_that(response, equal_to(json_data)) - - expected_call() - - @patch('ubersmith_client.ubersmith_request_post.requests') - def test_api_post_method_returns_without_arguments(self, requests_mock): - json_data = { - 'company': 'schwifty' - } - expected_call = self.expect_a_ubersmith_call_post(requests_mock=requests_mock, - method='client.list', - returning=a_response_data(data=json_data)) - - ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=False) - response = ubersmith_api.client.list() - - assert_that(response, equal_to(json_data)) - - expected_call() - - @patch('ubersmith_client.ubersmith_request_post.requests') - def test_api_raises_exception_with_if_data_status_is_false(self, requests_mock): - data = a_response_data(status=False, - error_code=1, - error_message='invalid method specified: client.miss', - data="schwifty") - ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=False) - - self.expect_a_ubersmith_call_post(requests_mock, method='client.miss', returning=data) - assert_that(calling(ubersmith_api.client.miss), raises(ubersmith_client.exceptions.UbersmithException)) - - def expect_a_ubersmith_call(self, requests_mock, returning=None, **kwargs): - response = MagicMock(status_code=200) - requests_mock.get = MagicMock(return_value=response) - response.json = MagicMock(return_value=returning) - - def assert_called_with(): - requests_mock.get.assert_called_with(auth=self.auth, params=kwargs, timeout=self.timeout, url=self.url) - response.json.assert_called_with() - - return assert_called_with + def test_api_method_returns_handle_connection_error_exception(self): + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password) + ubersmith_api.ubersmith_request = Mock(side_effect=ConnectionError()) - def expect_a_ubersmith_call_post(self, requests_mock, returning=None, status_code=200, **kwargs): - response = MagicMock(status_code=status_code) - requests_mock.post = MagicMock(return_value=response) - response.json = MagicMock(return_value=returning) + assert_that(calling(ubersmith_api.__getattr__).with_args("client"), raises(UbersmithConnectionError)) - def assert_called_with(): - requests_mock.post.assert_called_with(auth=self.auth, timeout=self.timeout, url=self.url, data=kwargs) - response.json.assert_called_with() + def test_api_method_returns_handle_timeout_exception(self): + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password) + ubersmith_api.ubersmith_request = Mock(side_effect=Timeout()) - return assert_called_with + assert_that(calling(ubersmith_api.__getattr__).with_args("client"), raises(UbersmithTimeout)) diff --git a/tests/ubersmith_request_get_test.py b/tests/ubersmith_request_get_test.py new file mode 100644 index 0000000..155a976 --- /dev/null +++ b/tests/ubersmith_request_get_test.py @@ -0,0 +1,76 @@ +# Copyright 2016 Internap. +# +# 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 unittest +from hamcrest import assert_that, equal_to +from mock import patch, MagicMock + +import ubersmith_client +from tests.ubersmith_json.response_data_structure import a_response_data + + +class UbersmithRequestGetTest(unittest.TestCase): + def setUp(self): + self.url = 'http://ubersmith.example.com/' + self.username = 'admin' + self.password = 'test' + + self.auth = (self.username, self.password) + self.timeout = 60 + + @patch('ubersmith_client.ubersmith_request_get.requests') + def test_api_get_method_returns_without_arguments(self, requests_mock): + json_data = { + 'company': 'council of ricks' + } + expected_call = self.expect_a_ubersmith_call(requests_mock=requests_mock, + method='client.list', + returning=a_response_data(data=json_data)) + + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=True) + response = ubersmith_api.client.list() + + assert_that(response, equal_to(json_data)) + + expected_call() + + @patch('ubersmith_client.ubersmith_request_get.requests') + def test_api_get_method_returns_with_arguments(self, request_mock): + json_data = { + 'group_id': '1', + 'client_id': '30001', + 'assignment_count': '1' + } + expected_call = self.expect_a_ubersmith_call(requests_mock=request_mock, + method='device.ip_group_list', + fac_id=1, + client_id=30001, + returning=a_response_data(data=json_data)) + + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password, use_http_get=True) + response = ubersmith_api.device.ip_group_list(fac_id=1, client_id=30001) + + assert_that(response, equal_to(json_data)) + + expected_call() + + def expect_a_ubersmith_call(self, requests_mock, returning=None, **kwargs): + response = MagicMock(status_code=200) + requests_mock.get = MagicMock(return_value=response) + response.json = MagicMock(return_value=returning) + + def assert_called_with(): + requests_mock.get.assert_called_with(auth=self.auth, params=kwargs, timeout=self.timeout, url=self.url) + response.json.assert_called_with() + + return assert_called_with diff --git a/tests/ubersmith_request_post_test.py b/tests/ubersmith_request_post_test.py new file mode 100644 index 0000000..81417db --- /dev/null +++ b/tests/ubersmith_request_post_test.py @@ -0,0 +1,87 @@ +# Copyright 2016 Internap. +# +# 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 unittest +from hamcrest import assert_that, equal_to, calling, raises +from mock import patch, MagicMock + +import ubersmith_client +from tests.ubersmith_json.response_data_structure import a_response_data + + +class UbersmithRequestPostTest(unittest.TestCase): + def setUp(self): + self.url = 'http://ubersmith.example.com/' + self.username = 'admin' + self.password = 'test' + + self.auth = (self.username, self.password) + self.timeout = 60 + + @patch('ubersmith_client.ubersmith_request_post.requests') + def test_api_post_method_returns_with_arguments(self, request_mock): + json_data = { + 'group_id': '1', + 'client_id': '30001', + 'assignment_count': '1' + } + expected_call = self.expect_a_ubersmith_call_post(requests_mock=request_mock, + method='device.ip_group_list', + fac_id=1, + client_id=30001, + returning=a_response_data(data=json_data)) + + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password) + response = ubersmith_api.device.ip_group_list(fac_id=1, client_id=30001) + + assert_that(response, equal_to(json_data)) + + expected_call() + + @patch('ubersmith_client.ubersmith_request_post.requests') + def test_api_post_method_returns_without_arguments(self, requests_mock): + json_data = { + 'company': 'schwifty' + } + expected_call = self.expect_a_ubersmith_call_post(requests_mock=requests_mock, + method='client.list', + returning=a_response_data(data=json_data)) + + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password) + response = ubersmith_api.client.list() + + assert_that(response, equal_to(json_data)) + + expected_call() + + @patch('ubersmith_client.ubersmith_request_post.requests') + def test_api_raises_exception_with_if_data_status_is_false(self, requests_mock): + data = a_response_data(status=False, + error_code=1, + error_message='invalid method specified: client.miss', + data="schwifty") + ubersmith_api = ubersmith_client.api.init(self.url, self.username, self.password) + + self.expect_a_ubersmith_call_post(requests_mock, method='client.miss', returning=data) + assert_that(calling(ubersmith_api.client.miss), raises(ubersmith_client.exceptions.UbersmithException)) + + def expect_a_ubersmith_call_post(self, requests_mock, returning=None, status_code=200, **kwargs): + response = MagicMock(status_code=status_code) + requests_mock.post = MagicMock(return_value=response) + response.json = MagicMock(return_value=returning) + + def assert_called_with(): + requests_mock.post.assert_called_with(auth=self.auth, timeout=self.timeout, url=self.url, data=kwargs) + response.json.assert_called_with() + + return assert_called_with diff --git a/ubersmith_client/exceptions.py b/ubersmith_client/exceptions.py index bfb0fd5..08b075d 100644 --- a/ubersmith_client/exceptions.py +++ b/ubersmith_client/exceptions.py @@ -60,3 +60,14 @@ def __init__(self): class UnknownError(UbersmithException): def __init__(self, code): super(UnknownError, self).__init__(code=code, message='An unknown error occurred') + + +class UbersmithConnectionError(UbersmithException): + def __init__(self, url): + super(UbersmithConnectionError, self).__init__(message="Could not connect to {0}".format(url)) + + +class UbersmithTimeout(UbersmithException): + def __init__(self, url, timeout): + super(UbersmithTimeout, self)\ + .__init__(message='Trying to connect to {url} times out after {timeout}'.format(url=url, timeout=timeout)) diff --git a/ubersmith_client/ubersmith_api.py b/ubersmith_client/ubersmith_api.py index 4731bc5..aaacf46 100644 --- a/ubersmith_client/ubersmith_api.py +++ b/ubersmith_client/ubersmith_api.py @@ -10,6 +10,9 @@ # 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. +from requests.exceptions import ConnectionError, Timeout + +from ubersmith_client.exceptions import UbersmithConnectionError, UbersmithTimeout from ubersmith_client.ubersmith_request_get import UbersmithRequestGet from ubersmith_client.ubersmith_request_post import UbersmithRequestPost @@ -23,4 +26,9 @@ def __init__(self, url, user, password, timeout, use_http_get): self.ubersmith_request = UbersmithRequestGet if use_http_get else UbersmithRequestPost def __getattr__(self, module): - return self.ubersmith_request(self.url, self.user, self.password, module, self.timeout) + try: + return self.ubersmith_request(self.url, self.user, self.password, module, self.timeout) + except ConnectionError: + raise UbersmithConnectionError(self.url) + except Timeout: + raise UbersmithTimeout(self.url, self.timeout)