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:
Terry Howe
2014-09-14 09:28:44 -06:00
parent b43ba62e71
commit 26c082f466
3 changed files with 51 additions and 1 deletions

View File

@@ -16,6 +16,8 @@
Exception definitions.
"""
import six
class SDKException(Exception):
"""The base exception class for all exceptions this library raises."""
@@ -62,6 +64,15 @@ class HttpException(SDKException):
super(HttpException, self).__init__(message)
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):
"""The resource does not support this operation type."""

View File

@@ -15,6 +15,7 @@ import logging
import fixtures
import httpretty
import mock
import requests
import six
@@ -634,3 +635,18 @@ class TestTransportRedirects(base.TestTransportBase):
for r, s in zip(req_resp.history, resp.history):
self.assertEqual(s.url, r.url)
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))

View File

@@ -151,7 +151,8 @@ class Transport(requests.Session):
try:
resp.raise_for_status()
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:
try:
resp.body = resp.json()
@@ -202,6 +203,28 @@ class Transport(requests.Session):
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):
if not _logger.isEnabledFor(logging.DEBUG):
return