diff --git a/tacker/tests/unit/vnflcm/test_controller.py b/tacker/tests/unit/vnflcm/test_controller.py index 8c22f3d01..20a7e1612 100644 --- a/tacker/tests/unit/vnflcm/test_controller.py +++ b/tacker/tests/unit/vnflcm/test_controller.py @@ -645,8 +645,9 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("No flavour with id 'invalid'.", - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -742,9 +743,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("No instantiation level with id " "'instantiation_level_1'.", - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -785,8 +787,9 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("No instantiation level with id 'non-existing'.", - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -887,9 +890,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("VimConnection id is not found: %s" % uuidsentinel.vim_id, - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -936,9 +940,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Region not found for the VimConnection: %s" % uuidsentinel.vim_id, - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -979,8 +984,9 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Default VIM is not defined.", - resp.json['badRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -1032,10 +1038,11 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in task_state INSTANTIATING. Cannot " "instantiate while the vnf instance is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1093,8 +1100,9 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("'flavourId' is a required property", - resp.json['badRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1134,9 +1142,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual( "Can not find requested vnf: %s" % constants.INVALID_UUID, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1159,9 +1168,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % uuidsentinel.vnf_instance_id, - resp.json['itemNotFound']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -1261,9 +1271,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % uuidsentinel.vnf_instance_id, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1275,9 +1286,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % constants.INVALID_UUID, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1385,8 +1397,9 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("'terminationType' is a required property", - resp.json['badRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1426,9 +1439,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % uuidsentinel.vnf_instance_id, - resp.json['itemNotFound']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -1457,10 +1471,11 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in task_state TERMINATING. Cannot " "terminate while the vnf instance is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) mock_get_vnf.assert_called_once() @mock.patch.object(TackerManager, 'get_service_plugins', @@ -1542,11 +1557,12 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in instantiation_state " "NOT_INSTANTIATED. Cannot heal while the vnf instance " "is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1573,11 +1589,12 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in task_state " "HEALING. Cannot heal while the vnf instance " "is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1609,10 +1626,11 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertFalse('Location' in resp.headers.keys()) self.assertEqual(http_client.BAD_REQUEST, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = "Vnfc id %s not present in vnf instance %s" self.assertEqual(expected_msg % (uuidsentinel.vnfc_instance_id, uuidsentinel.vnf_instance_id), - resp.json['badRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1735,9 +1753,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % uuidsentinel.vnf_instance_id, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1751,9 +1770,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual("Can not find requested vnf instance: %s" % constants.INVALID_UUID, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1773,11 +1793,12 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in instantiation_state " "INSTANTIATED. Cannot delete while the vnf instance " "is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': @@ -1798,11 +1819,12 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.CONFLICT, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_msg = ("Vnf instance %s in task_state ERROR. " "Cannot delete while the vnf instance " "is in this state.") self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, - resp.json['conflictingRequest']['message']) + resp.json['detail']) @mock.patch.object(objects.VnfInstanceList, "get_by_filters") @ddt.data( @@ -3806,9 +3828,10 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(http_client.NOT_FOUND, resp.status_code) + self.assertIn('application/problem+json', resp.headers['Content-Type']) self.assertEqual( "Can not find requested vnf: %s" % constants.INVALID_UUID, - resp.json['itemNotFound']['message']) + resp.json['detail']) @mock.patch.object(TackerManager, 'get_service_plugins', return_value={'VNFM': FakeVNFMPlugin()}) @@ -4190,10 +4213,11 @@ class TestController(base.TestCase): resp = req.get_response(self.app) self.assertEqual(500, resp.status_code) - + self.assertIn('application/problem+json', resp.headers['Content-Type']) expected_vnf = {'tackerFault': {'code': 500, 'message': 'Unexpected API Error. Please report this at ' 'http://bugs.launchpad.net/tacker/ and attach the ' 'Tacker API log if possible.\n' ""}} - self.assertEqual(expected_vnf, resp.json) + expected_msg = expected_vnf['tackerFault']['message'] + self.assertEqual(expected_msg, resp.json['detail']) diff --git a/tacker/wsgi.py b/tacker/wsgi.py index 4dd6a9f66..34f52829f 100644 --- a/tacker/wsgi.py +++ b/tacker/wsgi.py @@ -19,6 +19,7 @@ Utility methods for working with WSGI servers import functools import errno +import http.client import os import socket import ssl @@ -1038,19 +1039,6 @@ def _default_body_function(wrapped_exc): class Fault(webob.exc.HTTPException): """Wrap webob.exc.HTTPException to provide API friendly response.""" - _fault_names = { - 400: "badRequest", - 401: "unauthorized", - 403: "forbidden", - 404: "itemNotFound", - 405: "badMethod", - 409: "conflictingRequest", - 413: "overLimit", - 415: "badMediaType", - 429: "overLimit", - 501: "notImplemented", - 503: "serviceUnavailable"} - def __init__(self, exception): """Create a Fault for the given webob.exc.exception.""" self.wrapped_exc = exception @@ -1064,22 +1052,24 @@ class Fault(webob.exc.HTTPException): user_locale = req.best_match_language() # Replace the body with fault details. code = self.wrapped_exc.status_int - fault_name = self._fault_names.get(code, "tackerFault") + fault_name = http.client.responses[code] explanation = self.wrapped_exc.explanation LOG.debug("Returning %(code)s to user: %(explanation)s", {'code': code, 'explanation': explanation}) explanation = i18n.translate(explanation, user_locale) - fault_data = { - fault_name: { - 'code': code, - 'message': explanation}} + fault_data = {} + if fault_name is not None: + fault_data['title'] = fault_name + fault_data['status'] = code + fault_data['detail'] = explanation + if code == 413 or code == 429: retry = self.wrapped_exc.headers.get('Retry-After', None) if retry: - fault_data[fault_name]['retryAfter'] = retry + fault_data['retryAfter'] = retry - self.wrapped_exc.content_type = 'application/json' + self.wrapped_exc.content_type = 'application/problem+json' self.wrapped_exc.charset = 'UTF-8' body = JSONDictSerializer().serialize(fault_data)