Make TransportErrors more descriptive
Problems: 1. In some cases no information is provided for the CLI user when these exceptions are raised: https://github.com/openstack/python-zaqarclient/blob/master/zaqarclient/ transport/http.py#L30. For example, try "openstack pool show unexisting_pool". You will see just blank line. It is because the server returns no message in the 404 response body. And the user sees the blank line. 2. Most of the error responses from Zaqar have bodies in title-description format. TransportErrors can only show descriptions from these responses. It's better to include also titles in the client's exception messages. 3. Some of the error responses from Zaqar are not in title-description format, but still have some info in their bodies. It's better to include this info to the client's exception message. Solution: This patch makes all exceptions in zaqarclient/transport/errors.py show at least error response code. The patch TransportErrors properly gather the info from Zaqar's error response bodies and show it. Partial-Bug: 1542804 Change-Id: Ie2cc3081a5dd7c4f21c29bdf78a9bad76b515121
This commit is contained in:
@@ -24,12 +24,24 @@ from zaqarclient import errors
|
|||||||
|
|
||||||
__all__ = ['TransportError', 'ResourceNotFound', 'MalformedRequest',
|
__all__ = ['TransportError', 'ResourceNotFound', 'MalformedRequest',
|
||||||
'UnauthorizedError', 'ForbiddenError', 'ServiceUnavailableError',
|
'UnauthorizedError', 'ForbiddenError', 'ServiceUnavailableError',
|
||||||
'InternalServerError']
|
'InternalServerError', 'ConflictError']
|
||||||
|
|
||||||
|
|
||||||
class TransportError(errors.ZaqarError):
|
class TransportError(errors.ZaqarError):
|
||||||
"""Base class for all transport errors."""
|
"""Base class for all transport errors."""
|
||||||
|
|
||||||
|
code = None
|
||||||
|
|
||||||
|
def __init__(self, title=None, description=None, text=None):
|
||||||
|
msg = 'Error response from Zaqar. Code: {0}.'.format(self.code)
|
||||||
|
if title:
|
||||||
|
msg += ' Title: {0}.'.format(title)
|
||||||
|
if description:
|
||||||
|
msg += ' Description: {0}.'.format(description)
|
||||||
|
if text:
|
||||||
|
msg += ' Text: {0}.'.format(text)
|
||||||
|
super(TransportError, self).__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
class ResourceNotFound(TransportError):
|
class ResourceNotFound(TransportError):
|
||||||
"""Indicates that a resource is missing
|
"""Indicates that a resource is missing
|
||||||
@@ -37,6 +49,8 @@ class ResourceNotFound(TransportError):
|
|||||||
This error maps to HTTP's 404
|
This error maps to HTTP's 404
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 404
|
||||||
|
|
||||||
|
|
||||||
class MalformedRequest(TransportError):
|
class MalformedRequest(TransportError):
|
||||||
"""Indicates that a request is malformed
|
"""Indicates that a request is malformed
|
||||||
@@ -44,6 +58,8 @@ class MalformedRequest(TransportError):
|
|||||||
This error maps to HTTP's 400
|
This error maps to HTTP's 400
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
|
||||||
class UnauthorizedError(TransportError):
|
class UnauthorizedError(TransportError):
|
||||||
"""Indicates that a request was not authenticated
|
"""Indicates that a request was not authenticated
|
||||||
@@ -51,6 +67,8 @@ class UnauthorizedError(TransportError):
|
|||||||
This error maps to HTTP's 401
|
This error maps to HTTP's 401
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 401
|
||||||
|
|
||||||
|
|
||||||
class ForbiddenError(TransportError):
|
class ForbiddenError(TransportError):
|
||||||
"""Indicates that a request is forbidden to access the particular resource
|
"""Indicates that a request is forbidden to access the particular resource
|
||||||
@@ -58,6 +76,8 @@ class ForbiddenError(TransportError):
|
|||||||
This error maps to HTTP's 403
|
This error maps to HTTP's 403
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 403
|
||||||
|
|
||||||
|
|
||||||
class InternalServerError(TransportError):
|
class InternalServerError(TransportError):
|
||||||
"""Indicates that the server encountered an unexpected situation
|
"""Indicates that the server encountered an unexpected situation
|
||||||
@@ -65,6 +85,8 @@ class InternalServerError(TransportError):
|
|||||||
This error maps to HTTP's 500
|
This error maps to HTTP's 500
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 500
|
||||||
|
|
||||||
|
|
||||||
class ServiceUnavailableError(TransportError):
|
class ServiceUnavailableError(TransportError):
|
||||||
"""Indicates that the server was unable to service the request
|
"""Indicates that the server was unable to service the request
|
||||||
@@ -72,9 +94,13 @@ class ServiceUnavailableError(TransportError):
|
|||||||
This error maps to HTTP's 503
|
This error maps to HTTP's 503
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 503
|
||||||
|
|
||||||
|
|
||||||
class ConflictError(TransportError):
|
class ConflictError(TransportError):
|
||||||
"""Indicates that the server was unable to service the request
|
"""Indicates that the server was unable to service the request
|
||||||
|
|
||||||
This error maps to HTTP's 409
|
This error maps to HTTP's 409
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
code = 409
|
||||||
|
@@ -96,14 +96,20 @@ class HttpTransport(base.Transport):
|
|||||||
data=request.content)
|
data=request.content)
|
||||||
|
|
||||||
if resp.status_code in self.http_to_zaqar:
|
if resp.status_code in self.http_to_zaqar:
|
||||||
|
kwargs = {}
|
||||||
try:
|
try:
|
||||||
msg = json.loads(resp.text)['description']
|
error_body = json.loads(resp.text)
|
||||||
|
kwargs['title'] = error_body['title']
|
||||||
|
kwargs['description'] = error_body['description']
|
||||||
except Exception:
|
except Exception:
|
||||||
# TODO(flaper87): Log this exception
|
# TODO(flaper87): Log this exception
|
||||||
# but don't stop raising the corresponding
|
# but don't stop raising the corresponding
|
||||||
# exception
|
# exception
|
||||||
msg = ''
|
# Note(Eva-i): most of the error responses from Zaqar have
|
||||||
raise self.http_to_zaqar[resp.status_code](msg)
|
# dict with title and description in their bodies. If it's not
|
||||||
|
# the case, let's just show body text.
|
||||||
|
kwargs['text'] = resp.text
|
||||||
|
raise self.http_to_zaqar[resp.status_code](**kwargs)
|
||||||
|
|
||||||
# NOTE(flaper87): This reads the whole content
|
# NOTE(flaper87): This reads the whole content
|
||||||
# and will consume any attempt of streaming.
|
# and will consume any attempt of streaming.
|
||||||
|
Reference in New Issue
Block a user