diff --git a/heat/api/aws/exception.py b/heat/api/aws/exception.py index 22bf9a0278..b5f592d35d 100644 --- a/heat/api/aws/exception.py +++ b/heat/api/aws/exception.py @@ -319,20 +319,22 @@ def map_remote_error(ex): request_limit_exceeded = ('RequestLimitExceeded') ex_type = reflection.get_class_name(ex, fully_qualified=False) - if ex_type.endswith('_Remote'): ex_type = ex_type[:-len('_Remote')] + safe = getattr(ex, 'safe', False) + detail = six.text_type(ex) if safe else None + if ex_type in inval_param_errors: - return HeatInvalidParameterValueError(detail=six.text_type(ex)) + return HeatInvalidParameterValueError(detail=detail) elif ex_type in denied_errors: - return HeatAccessDeniedError(detail=six.text_type(ex)) + return HeatAccessDeniedError(detail=detail) elif ex_type in already_exists_errors: - return AlreadyExistsError(detail=six.text_type(ex)) + return AlreadyExistsError(detail=detail) elif ex_type in invalid_action_errors: - return HeatActionInProgressError(detail=six.text_type(ex)) + return HeatActionInProgressError(detail=detail) elif ex_type in request_limit_exceeded: - return HeatRequestLimitExceeded(detail=six.text_type(ex)) + return HeatRequestLimitExceeded(detail=detail) else: # Map everything else to internal server error for now - return HeatInternalFailureError(detail=six.text_type(ex)) + return HeatInternalFailureError(detail=detail) diff --git a/heat/api/middleware/fault.py b/heat/api/middleware/fault.py index dd4b386bc8..2e977393a7 100644 --- a/heat/api/middleware/fault.py +++ b/heat/api/middleware/fault.py @@ -110,6 +110,8 @@ class FaultWrapper(wsgi.Middleware): trace = None traceback_marker = 'Traceback (most recent call last)' webob_exc = None + safe = getattr(ex, 'safe', False) + if isinstance(ex, exception.HTTPExceptionDisguise): # An HTTP exception was disguised so it could make it here # let's remove the disguise and set the original HTTP exception @@ -151,11 +153,12 @@ class FaultWrapper(wsgi.Middleware): 'title': webob_exc.title, 'explanation': webob_exc.explanation, 'error': { - 'message': message, 'type': ex_type, 'traceback': trace, } } + if safe: + error['error']['message'] = message return error diff --git a/heat/common/exception.py b/heat/common/exception.py index e498971644..f42c9e07f6 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -55,6 +55,8 @@ class HeatException(Exception): # YYY - Specific error code for a given exception. error_code = None + safe = True + def __init__(self, **kwargs): self.kwargs = kwargs @@ -448,6 +450,8 @@ class HTTPExceptionDisguise(Exception): They can be handled by the webob fault application in the wsgi pipeline. """ + safe = True + def __init__(self, exception): self.exc = exception self.tb = sys.exc_info()[2] diff --git a/heat/tests/test_fault_middleware.py b/heat/tests/test_fault_middleware.py index 01efb17e9e..3292bb6686 100644 --- a/heat/tests/test_fault_middleware.py +++ b/heat/tests/test_fault_middleware.py @@ -144,8 +144,7 @@ class FaultMiddlewareTest(common.HeatTestCase): wrapper = fault.FaultWrapper(None) msg = wrapper._error(remote_error) expected = {'code': 500, - 'error': {'message': msg['error']['message'], - 'traceback': None, + 'error': {'traceback': None, 'type': 'RemoteError'}, 'explanation': msg['explanation'], 'title': 'Internal Server Error'} @@ -211,8 +210,7 @@ class FaultMiddlewareTest(common.HeatTestCase): msg = wrapper._error(NotMappedException('A message')) expected = {'code': 500, - 'error': {'message': u'A message', - 'traceback': None, + 'error': {'traceback': None, 'type': 'NotMappedException'}, 'explanation': ('The server has either erred or is ' 'incapable of performing the requested '