Merge "Send HTTP exceptions in the format expected by neutronclient"
This commit is contained in:
commit
35b2d27883
@ -99,17 +99,16 @@ def Resource(controller, faults=None, deserializers=None, serializers=None):
|
||||
else:
|
||||
LOG.exception(_('%s failed'), action)
|
||||
e = translate(e, language)
|
||||
# following structure is expected by python-neutronclient
|
||||
err_data = {'type': e.__class__.__name__,
|
||||
'message': e, 'detail': ''}
|
||||
body = serializer.serialize({'NeutronError': err_data})
|
||||
body = serializer.serialize(
|
||||
{'NeutronError': get_exception_data(e)})
|
||||
kwargs = {'body': body, 'content_type': content_type}
|
||||
raise mapped_exc(**kwargs)
|
||||
except webob.exc.HTTPException as e:
|
||||
type_, value, tb = sys.exc_info()
|
||||
LOG.exception(_('%s failed'), action)
|
||||
translate(e, language)
|
||||
value.body = serializer.serialize({'NeutronError': e})
|
||||
value.body = serializer.serialize(
|
||||
{'NeutronError': get_exception_data(e)})
|
||||
value.content_type = content_type
|
||||
six.reraise(type_, value, tb)
|
||||
except NotImplementedError as e:
|
||||
@ -121,7 +120,7 @@ def Resource(controller, faults=None, deserializers=None, serializers=None):
|
||||
# because a plugin does not implement a feature,
|
||||
# returning 500 is definitely confusing.
|
||||
body = serializer.serialize(
|
||||
{'NotImplementedError': e.message})
|
||||
{'NotImplementedError': get_exception_data(e)})
|
||||
kwargs = {'body': body, 'content_type': content_type}
|
||||
raise webob.exc.HTTPNotImplemented(**kwargs)
|
||||
except Exception:
|
||||
@ -131,7 +130,9 @@ def Resource(controller, faults=None, deserializers=None, serializers=None):
|
||||
msg = _('Request Failed: internal server error while '
|
||||
'processing your request.')
|
||||
msg = translate(msg, language)
|
||||
body = serializer.serialize({'NeutronError': msg})
|
||||
body = serializer.serialize(
|
||||
{'NeutronError': get_exception_data(
|
||||
webob.exc.HTTPInternalServerError(msg))})
|
||||
kwargs = {'body': body, 'content_type': content_type}
|
||||
raise webob.exc.HTTPInternalServerError(**kwargs)
|
||||
|
||||
@ -148,6 +149,21 @@ def Resource(controller, faults=None, deserializers=None, serializers=None):
|
||||
return resource
|
||||
|
||||
|
||||
def get_exception_data(e):
|
||||
"""Extract the information about an exception.
|
||||
|
||||
Neutron client for the v2 API expects exceptions to have 'type', 'message'
|
||||
and 'detail' attributes.This information is extracted and converted into a
|
||||
dictionary.
|
||||
|
||||
:param e: the exception to be reraised
|
||||
:returns: a structured dict with the exception data
|
||||
"""
|
||||
err_data = {'type': e.__class__.__name__,
|
||||
'message': e, 'detail': ''}
|
||||
return err_data
|
||||
|
||||
|
||||
def translate(translatable, locale):
|
||||
"""Translates the object to the given locale.
|
||||
|
||||
|
@ -122,6 +122,13 @@ class RequestTestCase(base.BaseTestCase):
|
||||
|
||||
class ResourceTestCase(base.BaseTestCase):
|
||||
|
||||
@staticmethod
|
||||
def _get_deserializer(req_format):
|
||||
if req_format == 'json':
|
||||
return wsgi.JSONDeserializer()
|
||||
else:
|
||||
return wsgi.XMLDeserializer()
|
||||
|
||||
def test_unmapped_neutron_error_with_json(self):
|
||||
msg = u'\u7f51\u7edc'
|
||||
|
||||
@ -260,47 +267,74 @@ class ResourceTestCase(base.BaseTestCase):
|
||||
self.assertIn(msg_translation,
|
||||
str(wsgi.JSONDeserializer().deserialize(res.body)))
|
||||
|
||||
def test_http_error(self):
|
||||
@staticmethod
|
||||
def _make_request_with_side_effect(side_effect, req_format=None):
|
||||
controller = mock.MagicMock()
|
||||
controller.test.side_effect = exc.HTTPGatewayTimeout()
|
||||
controller.test.side_effect = side_effect
|
||||
|
||||
resource = webtest.TestApp(wsgi_resource.Resource(controller))
|
||||
|
||||
environ = {'wsgiorg.routing_args': (None, {'action': 'test'})}
|
||||
routing_args = {'action': 'test'}
|
||||
if req_format:
|
||||
routing_args.update({'format': req_format})
|
||||
environ = {'wsgiorg.routing_args': (None, routing_args)}
|
||||
res = resource.get('', extra_environ=environ, expect_errors=True)
|
||||
self.assertEqual(res.status_int, exc.HTTPGatewayTimeout.code)
|
||||
return res
|
||||
|
||||
def test_http_error(self):
|
||||
res = self._make_request_with_side_effect(exc.HTTPGatewayTimeout())
|
||||
|
||||
# verify that the exception structure is the one expected
|
||||
# by the python-neutronclient
|
||||
self.assertEqual(exc.HTTPGatewayTimeout().explanation,
|
||||
res.json['NeutronError']['message'])
|
||||
self.assertEqual('HTTPGatewayTimeout',
|
||||
res.json['NeutronError']['type'])
|
||||
self.assertEqual('', res.json['NeutronError']['detail'])
|
||||
self.assertEqual(exc.HTTPGatewayTimeout.code, res.status_int)
|
||||
|
||||
def _test_unhandled_error(self, req_format='json'):
|
||||
expected_res = {'body': {'NeutronError':
|
||||
{'detail': '',
|
||||
'message': _(
|
||||
'Request Failed: internal server '
|
||||
'error while processing your request.'),
|
||||
'type': 'HTTPInternalServerError'}}}
|
||||
res = self._make_request_with_side_effect(side_effect=Exception(),
|
||||
req_format=req_format)
|
||||
self.assertEqual(exc.HTTPInternalServerError.code,
|
||||
res.status_int)
|
||||
self.assertEqual(expected_res,
|
||||
self._get_deserializer(
|
||||
req_format).deserialize(res.body))
|
||||
|
||||
def test_unhandled_error_with_json(self):
|
||||
expected_res = {'body': {'NeutronError':
|
||||
_('Request Failed: internal server error '
|
||||
'while processing your request.')}}
|
||||
controller = mock.MagicMock()
|
||||
controller.test.side_effect = Exception()
|
||||
|
||||
resource = webtest.TestApp(wsgi_resource.Resource(controller))
|
||||
|
||||
environ = {'wsgiorg.routing_args': (None, {'action': 'test',
|
||||
'format': 'json'})}
|
||||
res = resource.get('', extra_environ=environ, expect_errors=True)
|
||||
self.assertEqual(res.status_int, exc.HTTPInternalServerError.code)
|
||||
self.assertEqual(wsgi.JSONDeserializer().deserialize(res.body),
|
||||
expected_res)
|
||||
self._test_unhandled_error()
|
||||
|
||||
def test_unhandled_error_with_xml(self):
|
||||
self._test_unhandled_error(req_format='xml')
|
||||
|
||||
def _test_not_implemented_error(self, req_format='json'):
|
||||
expected_res = {'body': {'NeutronError':
|
||||
_('Request Failed: internal server error '
|
||||
'while processing your request.')}}
|
||||
controller = mock.MagicMock()
|
||||
controller.test.side_effect = Exception()
|
||||
{'detail': '',
|
||||
'message': _(
|
||||
'The server has either erred or is '
|
||||
'incapable of performing the requested '
|
||||
'operation.'),
|
||||
'type': 'HTTPNotImplemented'}}}
|
||||
|
||||
resource = webtest.TestApp(wsgi_resource.Resource(controller))
|
||||
res = self._make_request_with_side_effect(exc.HTTPNotImplemented(),
|
||||
req_format=req_format)
|
||||
self.assertEqual(exc.HTTPNotImplemented.code, res.status_int)
|
||||
self.assertEqual(expected_res,
|
||||
self._get_deserializer(
|
||||
req_format).deserialize(res.body))
|
||||
|
||||
environ = {'wsgiorg.routing_args': (None, {'action': 'test',
|
||||
'format': 'xml'})}
|
||||
res = resource.get('', extra_environ=environ, expect_errors=True)
|
||||
self.assertEqual(res.status_int, exc.HTTPInternalServerError.code)
|
||||
self.assertEqual(wsgi.XMLDeserializer().deserialize(res.body),
|
||||
expected_res)
|
||||
def test_not_implemented_error_with_json(self):
|
||||
self._test_not_implemented_error()
|
||||
|
||||
def test_not_implemented_error_with_xml(self):
|
||||
self._test_not_implemented_error(req_format='xml')
|
||||
|
||||
def test_status_200(self):
|
||||
controller = mock.MagicMock()
|
||||
|
Loading…
x
Reference in New Issue
Block a user