diff --git a/valenceclient/common/apiclient/exceptions.py b/valenceclient/common/apiclient/exceptions.py index 84d4221..b8988dd 100644 --- a/valenceclient/common/apiclient/exceptions.py +++ b/valenceclient/common/apiclient/exceptions.py @@ -1,4 +1,4 @@ -# Copyright 2016 99cloud, Inc. +# Copyright 2017 99cloud, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -65,6 +65,16 @@ class HTTPClientError(HttpError): message = _("HTTP Client Error") +class BadRequest(HTTPClientError): + """HTTP 400 - Bad Request. + + The request cannot be fulfilled due to bad syntax. + """ + + http_status = http_client.BAD_REQUEST + message = _("Bad Request") + + class HttpServerError(HttpError): """Server-side HTTP error. @@ -95,7 +105,7 @@ def from_response(response, method, url): if not req_id: req_id = response.headers.get('X-compute-request-id') - kwages = { + kwargs = { 'http_status': response.status_code, 'response': response, 'method': method, @@ -104,7 +114,7 @@ def from_response(response, method, url): } if 'retry_after' in response.headers: - kwages['retry_after'] = response.headers['retry_after'] + kwargs['retry_after'] = response.headers['retry_after'] content_type = response.headers.get('Content-Type', "") if content_type.startswith('application/json'): @@ -116,12 +126,12 @@ def from_response(response, method, url): if isinstance(body, dict): error = body.get(list(body)[0]) if isinstance(error, dict): - kwages['message'] = (error.get('message') or + kwargs['message'] = (error.get('message') or error.get('faultstring')) - kwages['details'] = (error.get('details') or + kwargs['details'] = (error.get('details') or six.text_type(body)) elif content_type.startswith("text/"): - kwages['details'] = getattr(response, 'text', '') + kwargs['details'] = getattr(response, 'text', '') try: cls = _code_map[response.status_code] @@ -136,4 +146,4 @@ def from_response(response, method, url): else: cls = HttpError - return cls + return cls(**kwargs) diff --git a/valenceclient/tests/unit/common/apiclient/test_exception.py b/valenceclient/tests/unit/common/apiclient/test_exception.py new file mode 100644 index 0000000..42d0c5b --- /dev/null +++ b/valenceclient/tests/unit/common/apiclient/test_exception.py @@ -0,0 +1,72 @@ +# Copyright 2017 99cloud, Inc. +# All Rights Reserved. +# +# 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. + +from oslotest import base as test_base +from six.moves import http_client +from valenceclient.common.apiclient import exceptions + + +class FakeResponse(object): + json_data = {} + + def __init__(self, **kwargs): + for key, value in kwargs.items(): + setattr(self, key, value) + + def json(self): + return self.json_data + + +class ExceptionsArgsTest(test_base.BaseTestCase): + + def assert_exception(self, ex_cls, method, url, status_code, json_data, + error_msg=None, error_details=None, + check_description=True): + ex = exceptions.from_response( + FakeResponse(status_code=status_code, + headers={'Content-Type': 'application/json'}, + json_data=json_data), + method, + url) + self.assertIsInstance(ex, ex_cls) + if check_description: + expected_msg = error_msg or json_data['error']['message'] + expected_details = error_details or json_data['error']['details'] + self.assertEqual(expected_msg, ex.message) + self.assertEqual(expected_details, ex.details) + self.assertEqual(method, ex.method) + self.assertEqual(url, ex.url) + self.assertEqual(status_code, ex.http_status) + + def test_from_response_know(self): + method = "GET" + url = "/fake" + status_code = http_client.BAD_REQUEST + json_data = {"error": {"message": "fake message", + "details": "fake details"}} + self.assert_exception(exceptions.BadRequest, + method, url, status_code, json_data) + + def test_from_response_unknown(self): + method = "POST" + url = "/fake-unknown" + status_code = 499 + json_data = {"error": {"message": "fake message", + "details": "fake details"}} + self.assert_exception( + exceptions.HTTPClientError, method, url, status_code, json_data) + status_code = 600 + self.assert_exception( + exceptions.HttpError, method, url, status_code, json_data)