From 05a8919194fcaacdc872d032ec2855fa6f26e81b Mon Sep 17 00:00:00 2001 From: Pierre Padrixe Date: Fri, 30 May 2014 17:22:21 +0200 Subject: [PATCH] Add Pecan support for wrap_controller_exception decorator wrap_controller_exception decorator only works for WSME controllers It is now also avaiable for Pecan controllers. Change-Id: I307a4feb613ab27bc40ae63b3a11b62838a42cd0 --- solum/api/controllers/v1/assembly.py | 10 +++--- solum/api/controllers/v1/component.py | 10 +++--- solum/api/controllers/v1/extension.py | 10 +++--- solum/api/controllers/v1/language_pack.py | 10 +++--- solum/api/controllers/v1/operation.py | 10 +++--- solum/api/controllers/v1/plan.py | 10 +++--- solum/api/controllers/v1/root.py | 2 +- solum/api/controllers/v1/sensor.py | 10 +++--- solum/api/controllers/v1/service.py | 10 +++--- solum/builder/controllers/v1/image.py | 2 +- solum/common/exception.py | 41 +++++++++++++++++++---- solum/tests/common/test_exception_base.py | 6 ++-- 12 files changed, 79 insertions(+), 52 deletions(-) diff --git a/solum/api/controllers/v1/assembly.py b/solum/api/controllers/v1/assembly.py index 8f8b08815..a2601407f 100644 --- a/solum/api/controllers/v1/assembly.py +++ b/solum/api/controllers/v1/assembly.py @@ -31,7 +31,7 @@ class AssemblyController(rest.RestController): super(AssemblyController, self).__init__() self._id = assembly_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(assembly.Assembly) def get(self): """Return this assembly.""" @@ -40,7 +40,7 @@ class AssemblyController(rest.RestController): return assembly.Assembly.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(assembly.Assembly, body=assembly.Assembly) def put(self, data): """Modify this assembly.""" @@ -50,7 +50,7 @@ class AssemblyController(rest.RestController): data.as_dict(objects.registry.Assembly)) return assembly.Assembly.from_db_model(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(status_code=204) def delete(self): """Delete this assembly.""" @@ -68,7 +68,7 @@ class AssembliesController(rest.RestController): remainder = remainder[:-1] return AssemblyController(assembly_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(assembly.Assembly, body=assembly.Assembly, status_code=201) def post(self, data): @@ -96,7 +96,7 @@ class AssembliesController(rest.RestController): return assembly.Assembly.from_db_model( handler.create(js_data), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([assembly.Assembly]) def get_all(self): """Return all assemblies, based on the query provided.""" diff --git a/solum/api/controllers/v1/component.py b/solum/api/controllers/v1/component.py index 2c6f775c8..85cd70055 100644 --- a/solum/api/controllers/v1/component.py +++ b/solum/api/controllers/v1/component.py @@ -27,7 +27,7 @@ class ComponentController(rest.RestController): super(ComponentController, self).__init__() self._id = component_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(component.Component) def get(self): """Return this component.""" @@ -36,7 +36,7 @@ class ComponentController(rest.RestController): return component.Component.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(component.Component, body=component.Component) def put(self, data): """Modify this component.""" @@ -46,7 +46,7 @@ class ComponentController(rest.RestController): data.as_dict(objects.registry.Component)) return component.Component.from_db_model(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(None, status_code=204) def delete(self): """Delete this component.""" @@ -64,7 +64,7 @@ class ComponentsController(rest.RestController): remainder = remainder[:-1] return ComponentController(component_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(component.Component, body=component.Component, status_code=201) def post(self, data): @@ -75,7 +75,7 @@ class ComponentsController(rest.RestController): handler.create(data.as_dict(objects.registry.Component)), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([component.Component]) def get_all(self): """Return all components, based on the query provided.""" diff --git a/solum/api/controllers/v1/extension.py b/solum/api/controllers/v1/extension.py index 249ba5a2a..17302856e 100644 --- a/solum/api/controllers/v1/extension.py +++ b/solum/api/controllers/v1/extension.py @@ -27,7 +27,7 @@ class ExtensionController(rest.RestController): def __init__(self, extension_id): self._id = extension_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(extension.Extension, wtypes.text) def get(self): """Return this extension.""" @@ -36,7 +36,7 @@ class ExtensionController(rest.RestController): return extension.Extension.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(extension.Extension, wtypes.text, body=extension.Extension) def put(self, data): @@ -47,7 +47,7 @@ class ExtensionController(rest.RestController): data.as_dict(objects.registry.Extension)) return extension.Extension.from_db_model(obj, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(None, wtypes.text, status_code=204) def delete(self): """Delete this extension.""" @@ -65,7 +65,7 @@ class ExtensionsController(rest.RestController): remainder = remainder[:-1] return ExtensionController(extension_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(extension.Extension, wtypes.text, body=extension.Extension, status_code=201) @@ -76,7 +76,7 @@ class ExtensionsController(rest.RestController): obj = handler.create(data.as_dict(objects.registry.Extension)) return extension.Extension.from_db_model(obj, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([extension.Extension]) def get_all(self): """Return all extensions, based on the query provided.""" diff --git a/solum/api/controllers/v1/language_pack.py b/solum/api/controllers/v1/language_pack.py index 6c460b0cf..84873bcb6 100644 --- a/solum/api/controllers/v1/language_pack.py +++ b/solum/api/controllers/v1/language_pack.py @@ -28,7 +28,7 @@ class LanguagePackController(rest.RestController): super(LanguagePackController, self).__init__() self._id = language_pack_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(lp.LanguagePack) def get(self): """Return a language_pack.""" @@ -37,7 +37,7 @@ class LanguagePackController(rest.RestController): return lp.LanguagePack.from_image( handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(lp.LanguagePack, body=lp.LanguagePack) def put(self, data): """Modify this language_pack.""" @@ -46,7 +46,7 @@ class LanguagePackController(rest.RestController): res = handler.update(self._id, data.as_image_dict()) return lp.LanguagePack.from_image(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(status_code=204) def delete(self): """Delete this language_pack.""" @@ -64,7 +64,7 @@ class LanguagePacksController(rest.RestController): remainder = remainder[:-1] return LanguagePackController(language_pack_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(lp.LanguagePack, body=lp.LanguagePack, status_code=201) def post(self, data): @@ -74,7 +74,7 @@ class LanguagePacksController(rest.RestController): return lp.LanguagePack.from_image(handler.create(data.as_image_dict()), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([lp.LanguagePack]) def get_all(self): """Return all language_packs, based on the query provided.""" diff --git a/solum/api/controllers/v1/operation.py b/solum/api/controllers/v1/operation.py index 4046e39e2..7313272f4 100644 --- a/solum/api/controllers/v1/operation.py +++ b/solum/api/controllers/v1/operation.py @@ -28,7 +28,7 @@ class OperationController(rest.RestController): super(OperationController, self).__init__() self._id = operation_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(operation.Operation, wtypes.text) def get(self): """Return this operation.""" @@ -37,7 +37,7 @@ class OperationController(rest.RestController): return operation.Operation.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(operation.Operation, wtypes.text, body=operation.Operation) def put(self, data): @@ -48,7 +48,7 @@ class OperationController(rest.RestController): data.as_dict(objects.registry.Operation)) return operation.Operation.from_db_model(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(status_code=204) def delete(self): """Delete this operation.""" @@ -66,7 +66,7 @@ class OperationsController(rest.RestController): remainder = remainder[:-1] return OperationController(operation_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(operation.Operation, body=operation.Operation, status_code=201) def post(self, data): @@ -76,7 +76,7 @@ class OperationsController(rest.RestController): return operation.Operation.from_db_model(handler.create( data.as_dict(objects.registry.Operation)), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([operation.Operation]) def get_all(self): """Return all operations, based on the query provided.""" diff --git a/solum/api/controllers/v1/plan.py b/solum/api/controllers/v1/plan.py index 80f773009..e2c5ca3a7 100644 --- a/solum/api/controllers/v1/plan.py +++ b/solum/api/controllers/v1/plan.py @@ -29,7 +29,7 @@ class PlanController(rest.RestController): super(PlanController, self).__init__() self._id = plan_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(plan.Plan) def get(self): """Return this plan.""" @@ -37,7 +37,7 @@ class PlanController(rest.RestController): return plan.Plan.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(plan.Plan, body=plan.Plan) def put(self, data): """Modify this plan.""" @@ -46,7 +46,7 @@ class PlanController(rest.RestController): data.as_dict(objects.registry.Plan)) return plan.Plan.from_db_model(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(status_code=204) def delete(self): """Delete this plan.""" @@ -63,7 +63,7 @@ class PlansController(rest.RestController): remainder = remainder[:-1] return PlanController(plan_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(plan.Plan, body=plan.Plan, status_code=201) def post(self, data): """Create a new plan.""" @@ -72,7 +72,7 @@ class PlansController(rest.RestController): handler.create(data.as_dict(objects.registry.Plan)), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([plan.Plan]) def get_all(self): """Return all plans, based on the query provided.""" diff --git a/solum/api/controllers/v1/root.py b/solum/api/controllers/v1/root.py index c4640f306..49f719bd2 100644 --- a/solum/api/controllers/v1/root.py +++ b/solum/api/controllers/v1/root.py @@ -91,7 +91,7 @@ class Controller(object): language_packs = language_pack.LanguagePacksController() public = public.PublicController() - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(Platform) def index(self): host_url = '%s/%s' % (pecan.request.host_url, 'v1') diff --git a/solum/api/controllers/v1/sensor.py b/solum/api/controllers/v1/sensor.py index eb56ff58a..f4d365d36 100644 --- a/solum/api/controllers/v1/sensor.py +++ b/solum/api/controllers/v1/sensor.py @@ -28,7 +28,7 @@ class SensorController(rest.RestController): super(SensorController, self).__init__() self._id = sensor_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(sensor.Sensor, wtypes.text) def get(self): """Return this sensor.""" @@ -36,7 +36,7 @@ class SensorController(rest.RestController): return sensor.Sensor.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(sensor.Sensor, wtypes.text, body=sensor.Sensor) def put(self, data): """Modify this sensor.""" @@ -45,7 +45,7 @@ class SensorController(rest.RestController): data.as_dict(objects.registry.Sensor)) return sensor.Sensor.from_db_model(obj, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(None, wtypes.text, status_code=204) def delete(self): """Delete this sensor.""" @@ -62,7 +62,7 @@ class SensorsController(rest.RestController): remainder = remainder[:-1] return SensorController(sensor_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(sensor.Sensor, wtypes.text, body=sensor.Sensor, status_code=201) def post(self, data): @@ -71,7 +71,7 @@ class SensorsController(rest.RestController): obj = handler.create(data.as_dict(objects.registry.Sensor)) return sensor.Sensor.from_db_model(obj, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([sensor.Sensor]) def get_all(self): """Return all sensors, based on the query provided.""" diff --git a/solum/api/controllers/v1/service.py b/solum/api/controllers/v1/service.py index ce1056d4c..18b3d5270 100644 --- a/solum/api/controllers/v1/service.py +++ b/solum/api/controllers/v1/service.py @@ -27,7 +27,7 @@ class ServiceController(rest.RestController): super(ServiceController, self).__init__() self._id = service_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(service.Service) def get(self): """Return this service.""" @@ -36,7 +36,7 @@ class ServiceController(rest.RestController): return service.Service.from_db_model(handler.get(self._id), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(service.Service, body=service.Service) def put(self, data): """Modify this service.""" @@ -46,7 +46,7 @@ class ServiceController(rest.RestController): data.as_dict(objects.registry.Service)) return service.Service.from_db_model(res, pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(status_code=204) def delete(self): """Delete this service.""" @@ -64,7 +64,7 @@ class ServicesController(rest.RestController): remainder = remainder[:-1] return ServiceController(service_id), remainder - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(service.Service, body=service.Service, status_code=201) def post(self, data): @@ -75,7 +75,7 @@ class ServicesController(rest.RestController): handler.create(data.as_dict(objects.registry.Service)), pecan.request.host_url) - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose([service.Service]) def get_all(self): """Return all services, based on the query provided.""" diff --git a/solum/builder/controllers/v1/image.py b/solum/builder/controllers/v1/image.py index b770cf782..29eaf69b7 100644 --- a/solum/builder/controllers/v1/image.py +++ b/solum/builder/controllers/v1/image.py @@ -71,7 +71,7 @@ class ImageController(rest.RestController): super(ImageController, self).__init__() self._id = image_id - @exception.wrap_controller_exception + @exception.wrap_wsme_controller_exception @wsme_pecan.wsexpose(Image) def get(self): """Return this image.""" diff --git a/solum/common/exception.py b/solum/common/exception.py index 4c0d02d55..b93f912c1 100644 --- a/solum/common/exception.py +++ b/solum/common/exception.py @@ -19,6 +19,7 @@ Includes decorator for re-raising Solum-type exceptions. """ import functools +import pecan import sys import uuid @@ -90,7 +91,7 @@ OBFUSCATED_MSG = _('Your request could not be handled ' 'Error Correlation id is: %s') -def wrap_controller_exception(func): +def wrap_controller_exception(func, func_server_error, func_client_error): """This decorator wraps controllers methods to handle exceptions: - if an unhandled Exception or a SolumException with an error code >=500 @@ -117,18 +118,44 @@ def wrap_controller_exception(func): log_correlation_id = str(uuid.uuid4()) LOG.error("%s:%s", log_correlation_id, str(excp)) # raise a client error with an obfuscated message - raise wsme.exc.ClientSideError( - six.text_type(OBFUSCATED_MSG % log_correlation_id), - http_error_code) + func_server_error(log_correlation_id, http_error_code) else: # raise a client error the original message LOG.debug(excp) - raise wsme.exc.ClientSideError( - six.text_type(excp), http_error_code) - + func_client_error(excp, http_error_code) return wrapped +def wrap_wsme_controller_exception(func): + """This decorator wraps wsme controllers to handle exceptions.""" + def _func_server_error(log_correlation_id, status_code): + raise wsme.exc.ClientSideError( + six.text_type(OBFUSCATED_MSG % log_correlation_id), status_code) + + def _func_client_error(excp, status_code): + raise wsme.exc.ClientSideError(six.text_type(excp), status_code) + + return wrap_controller_exception(func, + _func_server_error, + _func_client_error) + + +def wrap_pecan_controller_exception(func): + """This decorator wraps pecan controllers to handle exceptions.""" + def _func_server_error(log_correlation_id, status_code): + pecan.response.status = status_code + pecan.response.body = six.text_type(OBFUSCATED_MSG % + log_correlation_id) + + def _func_client_error(excp, status_code): + pecan.response.status = status_code + pecan.response.body = six.text_type(excp) + + return wrap_controller_exception(func, + _func_server_error, + _func_client_error) + + def wrap_keystone_exception(func): """This decorator wraps keystone exception by throwing Solum specific exceptions. diff --git a/solum/tests/common/test_exception_base.py b/solum/tests/common/test_exception_base.py index 6e150be6e..3cf576379 100644 --- a/solum/tests/common/test_exception_base.py +++ b/solum/tests/common/test_exception_base.py @@ -78,7 +78,7 @@ class ExceptionTestCase(base.BaseTestCase): correlation_id = None try: - exception.wrap_controller_exception(error_func)() + exception.wrap_wsme_controller_exception(error_func)() except wsme.exc.ClientSideError as e: correlation_id = e.message.split(":")[1].strip() @@ -100,7 +100,7 @@ class ExceptionTestCase(base.BaseTestCase): raise exception.BadRequest(**error_args) try: - exception.wrap_controller_exception(error_func)() + exception.wrap_wsme_controller_exception(error_func)() self.assertTrue(False) except wsme.exc.ClientSideError as e: self.assertEqual(e.msg, expected_error_msg) @@ -113,7 +113,7 @@ class ExceptionTestCase(base.BaseTestCase): correlation_id = None try: - exception.wrap_controller_exception(error_func)() + exception.wrap_wsme_controller_exception(error_func)() except wsme.exc.ClientSideError as e: correlation_id = e.message.split(":")[1].strip()