Add details to HttpException string
Without this change:
400 Client Error: Bad Request
With this change, the much more useful:
HttpException: 400 Client Error: Bad Request, Validation error: instance 'flavorRef' is a required property
Change-Id: Iaa63969e327532c02d72999efcbee42aa0d381d3
This commit is contained in:
@@ -16,6 +16,8 @@
|
|||||||
Exception definitions.
|
Exception definitions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class SDKException(Exception):
|
class SDKException(Exception):
|
||||||
"""The base exception class for all exceptions this library raises."""
|
"""The base exception class for all exceptions this library raises."""
|
||||||
@@ -62,6 +64,15 @@ class HttpException(SDKException):
|
|||||||
super(HttpException, self).__init__(message)
|
super(HttpException, self).__init__(message)
|
||||||
self.details = details
|
self.details = details
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
msg = self.__class__.__name__ + ": " + self.message
|
||||||
|
if self.details:
|
||||||
|
msg += ", " + six.text_type(self.details)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__unicode__()
|
||||||
|
|
||||||
|
|
||||||
class MethodNotSupported(SDKException):
|
class MethodNotSupported(SDKException):
|
||||||
"""The resource does not support this operation type."""
|
"""The resource does not support this operation type."""
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import logging
|
|||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
import httpretty
|
import httpretty
|
||||||
|
import mock
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -634,3 +635,18 @@ class TestTransportRedirects(base.TestTransportBase):
|
|||||||
for r, s in zip(req_resp.history, resp.history):
|
for r, s in zip(req_resp.history, resp.history):
|
||||||
self.assertEqual(s.url, r.url)
|
self.assertEqual(s.url, r.url)
|
||||||
self.assertEqual(s.status_code, r.status_code)
|
self.assertEqual(s.status_code, r.status_code)
|
||||||
|
|
||||||
|
def test_parse_error_response(self):
|
||||||
|
xport = transport.Transport(redirect=True)
|
||||||
|
resp = mock.Mock()
|
||||||
|
resp.json = mock.Mock()
|
||||||
|
resp.json.return_value = {"badRequest": {"message": "Not defined"}}
|
||||||
|
self.assertEqual("Not defined", xport._parse_error_response(resp))
|
||||||
|
resp.json.return_value = {"message": {"response": "Not Allowed"}}
|
||||||
|
self.assertEqual("Not Allowed", xport._parse_error_response(resp))
|
||||||
|
resp.json.return_value = {"itemNotFound": {"message": "Not found"}}
|
||||||
|
self.assertEqual("Not found", xport._parse_error_response(resp))
|
||||||
|
resp.json.return_value = {"instanceFault": {"message": "Wot?"}}
|
||||||
|
self.assertEqual("Wot?", xport._parse_error_response(resp))
|
||||||
|
resp.json.return_value = {"QuantumError": "Network error"}
|
||||||
|
self.assertEqual("Network error", xport._parse_error_response(resp))
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ class Transport(requests.Session):
|
|||||||
try:
|
try:
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
raise exceptions.HttpException(six.text_type(e), details=resp.text)
|
raise exceptions.HttpException(six.text_type(e),
|
||||||
|
self._parse_error_response(resp))
|
||||||
if accept == JSON:
|
if accept == JSON:
|
||||||
try:
|
try:
|
||||||
resp.body = resp.json()
|
resp.body = resp.json()
|
||||||
@@ -202,6 +203,28 @@ class Transport(requests.Session):
|
|||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
def _parse_error_response(self, resp):
|
||||||
|
try:
|
||||||
|
jresp = resp.json()
|
||||||
|
# compute
|
||||||
|
if "badRequest" in jresp and "message" in jresp["badRequest"]:
|
||||||
|
return jresp["badRequest"]["message"]
|
||||||
|
# identity
|
||||||
|
if "message" in jresp and "response" in jresp["message"]:
|
||||||
|
return jresp["message"]["response"]
|
||||||
|
# network
|
||||||
|
if "QuantumError" in jresp:
|
||||||
|
return jresp["QuantumError"]
|
||||||
|
# database
|
||||||
|
if "itemNotFound" in jresp and "message" in jresp["itemNotFound"]:
|
||||||
|
return jresp["itemNotFound"]["message"]
|
||||||
|
if "instanceFault" in jresp:
|
||||||
|
if "message" in jresp["instanceFault"]:
|
||||||
|
return jresp["instanceFault"]["message"]
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return resp.text
|
||||||
|
|
||||||
def _log_request(self, method, url, **kwargs):
|
def _log_request(self, method, url, **kwargs):
|
||||||
if not _logger.isEnabledFor(logging.DEBUG):
|
if not _logger.isEnabledFor(logging.DEBUG):
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user