summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/heat-api2
-rwxr-xr-xbin/heat-api-cfn2
-rwxr-xr-xbin/heat-api-cloudwatch2
-rwxr-xr-xbin/heat-cfn2
-rwxr-xr-xbin/heat-engine2
-rwxr-xr-xbin/heat-manage4
-rw-r--r--heat/api/middleware/fault.py16
-rw-r--r--heat/api/openstack/v1/__init__.py4
-rw-r--r--heat/api/openstack/v1/events.py1
-rw-r--r--heat/api/openstack/v1/stacks.py1
-rw-r--r--heat/api/openstack/v1/util.py2
-rw-r--r--heat/common/exception.py1
-rw-r--r--heat/common/wsgi.py41
-rw-r--r--heat/openstack/common/exception.py3
-rw-r--r--heat/openstack/common/rpc/common.py1
-rw-r--r--heat/tests/test_api_openstack_v1.py87
-rw-r--r--heat/tests/test_wsgi.py52
17 files changed, 169 insertions, 54 deletions
diff --git a/bin/heat-api b/bin/heat-api
index 4ac438596..8f58c0944 100755
--- a/bin/heat-api
+++ b/bin/heat-api
@@ -33,7 +33,7 @@ if os.path.exists(os.path.join(possible_topdir, 'heat', '__init__.py')):
from heat.openstack.common import gettextutils
-gettextutils.install('heat')
+gettextutils.install('heat', lazy=True)
from oslo.config import cfg
diff --git a/bin/heat-api-cfn b/bin/heat-api-cfn
index 8eceb6aef..95a946ca8 100755
--- a/bin/heat-api-cfn
+++ b/bin/heat-api-cfn
@@ -35,7 +35,7 @@ if os.path.exists(os.path.join(possible_topdir, 'heat', '__init__.py')):
from heat.openstack.common import gettextutils
-gettextutils.install('heat')
+gettextutils.install('heat', lazy=True)
from oslo.config import cfg
diff --git a/bin/heat-api-cloudwatch b/bin/heat-api-cloudwatch
index 7453b7744..155a4d48f 100755
--- a/bin/heat-api-cloudwatch
+++ b/bin/heat-api-cloudwatch
@@ -35,7 +35,7 @@ if os.path.exists(os.path.join(possible_topdir, 'heat', '__init__.py')):
from heat.openstack.common import gettextutils
-gettextutils.install('heat')
+gettextutils.install('heat', lazy=True)
from oslo.config import cfg
diff --git a/bin/heat-cfn b/bin/heat-cfn
index fc31938df..34a5bd0d8 100755
--- a/bin/heat-cfn
+++ b/bin/heat-cfn
@@ -41,7 +41,7 @@ scriptname = os.path.basename(sys.argv[0])
from heat.openstack.common import gettextutils
-gettextutils.install('heat')
+gettextutils.install('heat', lazy=True)
if scriptname == 'heat-boto':
from heat.cfn_client import boto_client as heat_client
diff --git a/bin/heat-engine b/bin/heat-engine
index 14e6f1851..36412cbae 100755
--- a/bin/heat-engine
+++ b/bin/heat-engine
@@ -36,7 +36,7 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')):
from heat.openstack.common import gettextutils
-gettextutils.install('heat')
+gettextutils.install('heat', lazy=True)
from oslo.config import cfg
diff --git a/bin/heat-manage b/bin/heat-manage
index 95e4a5d14..32bdc8f78 100755
--- a/bin/heat-manage
+++ b/bin/heat-manage
@@ -25,6 +25,10 @@ POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'heat', '__init__.py')):
sys.path.insert(0, POSSIBLE_TOPDIR)
+from heat.openstack.common import gettextutils
+
+gettextutils.install('heat')
+
from heat.cmd import manage
manage.main()
diff --git a/heat/api/middleware/fault.py b/heat/api/middleware/fault.py
index 9df7ae60e..c8e77093f 100644
--- a/heat/api/middleware/fault.py
+++ b/heat/api/middleware/fault.py
@@ -23,6 +23,7 @@ Cinder's faultwrapper
import traceback
import webob
+from heat.common import exception
from heat.openstack.common import log as logging
import heat.openstack.common.rpc.common as rpc_common
@@ -79,11 +80,18 @@ class FaultWrapper(wsgi.Middleware):
if ex_type.endswith(rpc_common._REMOTE_POSTFIX):
ex_type = ex_type[:-len(rpc_common._REMOTE_POSTFIX)]
- message = str(ex)
- if message.find('\n') > -1:
- message, trace = message.split('\n', 1)
+ if isinstance(ex, exception.OpenstackException):
+ # If the exception is an OpenstackException it is going to have a
+ # translated Message object as the message, let's recreate it here
+ message = (ex.message % ex.kwargs
+ if hasattr(ex, 'kwargs') else ex.message)
+ else:
+ message = ex.message
+
+ trace = str(ex)
+ if trace.find('\n') > -1:
+ unused, trace = trace.split('\n', 1)
else:
- message = str(ex)
trace = traceback.format_exc()
webob_exc = self.error_map.get(ex_type,
diff --git a/heat/api/openstack/v1/__init__.py b/heat/api/openstack/v1/__init__.py
index a1ab038f1..f21f89b83 100644
--- a/heat/api/openstack/v1/__init__.py
+++ b/heat/api/openstack/v1/__init__.py
@@ -15,10 +15,6 @@
import routes
-from heat.openstack.common import gettextutils
-
-gettextutils.install('heat')
-
from heat.api.openstack.v1 import stacks
from heat.api.openstack.v1 import resources
from heat.api.openstack.v1 import events
diff --git a/heat/api/openstack/v1/events.py b/heat/api/openstack/v1/events.py
index 81264a50e..b0c0bbb69 100644
--- a/heat/api/openstack/v1/events.py
+++ b/heat/api/openstack/v1/events.py
@@ -21,7 +21,6 @@ from heat.common import wsgi
from heat.rpc import api as engine_api
from heat.common import identifier
from heat.rpc import client as rpc_client
-from heat.openstack.common.gettextutils import _
summary_keys = [
diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py
index 617f25a3f..a79db25a9 100644
--- a/heat/api/openstack/v1/stacks.py
+++ b/heat/api/openstack/v1/stacks.py
@@ -29,7 +29,6 @@ from heat.rpc import client as rpc_client
from heat.common import urlfetch
from heat.openstack.common import log as logging
-from heat.openstack.common.gettextutils import _
logger = logging.getLogger(__name__)
diff --git a/heat/api/openstack/v1/util.py b/heat/api/openstack/v1/util.py
index 43381bfce..b6dcdc5ed 100644
--- a/heat/api/openstack/v1/util.py
+++ b/heat/api/openstack/v1/util.py
@@ -18,8 +18,6 @@ from functools import wraps
from heat.common import identifier
-from heat.openstack.common.gettextutils import _
-
def tenant_local(handler):
'''
diff --git a/heat/common/exception.py b/heat/common/exception.py
index eb236a5a3..ed4fbc5c2 100644
--- a/heat/common/exception.py
+++ b/heat/common/exception.py
@@ -20,7 +20,6 @@
import functools
import urlparse
import sys
-from heat.openstack.common.gettextutils import _
from heat.openstack.common import exception
diff --git a/heat/common/wsgi.py b/heat/common/wsgi.py
index f108fe68e..a4da6b0eb 100644
--- a/heat/common/wsgi.py
+++ b/heat/common/wsgi.py
@@ -2,6 +2,7 @@
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2013 IBM Corp.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -43,8 +44,8 @@ import webob.dec
import webob.exc
from heat.common import exception
+from heat.openstack.common import gettextutils
from heat.openstack.common import importutils
-from heat.openstack.common.gettextutils import _
URL_LENGTH_LIMIT = 50000
@@ -431,6 +432,12 @@ class Request(webob.Request):
else:
return content_type
+ def best_match_language(self):
+ """Determine language for returned response."""
+ all_languages = gettextutils.get_available_languages('heat')
+ return self.accept_language.best_match(all_languages,
+ default_match='en_US')
+
def is_json_content_type(request):
if request.method == 'GET':
@@ -589,7 +596,17 @@ class Resource(object):
request, **action_args)
except TypeError as err:
logging.error(_('Exception handling resource: %s') % str(err))
- raise webob.exc.HTTPBadRequest()
+ msg = _('The server could not comply with the request since\r\n'
+ 'it is either malformed or otherwise incorrect.\r\n')
+ err = webob.exc.HTTPBadRequest(msg)
+ raise translate_exception(err, request.best_match_language())
+ except webob.exc.HTTPException as err:
+ logging.error(_("Returning %(code)s to user: %(explanation)s"),
+ {'code': err.code, 'explanation': err.explanation})
+ raise translate_exception(err, request.best_match_language())
+ except Exception as err:
+ logging.error(_("Unexpected error occurred serving API: %s") % err)
+ raise translate_exception(err, request.best_match_language())
# Here we support either passing in a serializer or detecting it
# based on the content type.
@@ -653,6 +670,26 @@ class Resource(object):
return args
+def translate_exception(exc, locale):
+ """Translates all translatable elements of the given exception."""
+ exc.message = gettextutils.get_localized_message(exc.message, locale)
+ if isinstance(exc, webob.exc.HTTPError):
+ # If the explanation is not a Message, that means that the
+ # explanation is the default, generic and not translatable explanation
+ # from webop.exc. Since the explanation is the error shown when the
+ # exception is converted to a response, let's actually swap it with
+ # message, since message is what gets passed in at construction time
+ # in the API
+ if not isinstance(exc.explanation, gettextutils.Message):
+ exc.explanation = exc.message
+ exc.detail = ''
+ else:
+ exc.explanation = \
+ gettextutils.get_localized_message(exc.explanation, locale)
+ exc.detail = gettextutils.get_localized_message(exc.detail, locale)
+ return exc
+
+
class BasePasteFactory(object):
"""A base class for paste app and filter factories.
diff --git a/heat/openstack/common/exception.py b/heat/openstack/common/exception.py
index ca1195a3e..9ba9fc144 100644
--- a/heat/openstack/common/exception.py
+++ b/heat/openstack/common/exception.py
@@ -21,8 +21,6 @@ Exceptions common to OpenStack projects
import logging
-from heat.openstack.common.gettextutils import _
-
_FATAL_EXCEPTION_FORMAT_ERRORS = False
@@ -120,6 +118,7 @@ class OpenstackException(Exception):
def __init__(self, **kwargs):
try:
+ self.kwargs = kwargs
self._error_string = self.message % kwargs
except Exception as e:
diff --git a/heat/openstack/common/rpc/common.py b/heat/openstack/common/rpc/common.py
index 31ecbdf3d..365161124 100644
--- a/heat/openstack/common/rpc/common.py
+++ b/heat/openstack/common/rpc/common.py
@@ -24,7 +24,6 @@ import traceback
from oslo.config import cfg
import six
-from heat.openstack.common.gettextutils import _
from heat.openstack.common import importutils
from heat.openstack.common import jsonutils
from heat.openstack.common import local
diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py
index db0275a28..12be4f89c 100644
--- a/heat/tests/test_api_openstack_v1.py
+++ b/heat/tests/test_api_openstack_v1.py
@@ -47,11 +47,15 @@ def request_with_middleware(middleware, func, req, *args, **kwargs):
return resp
-def remote_error(ex_type, message=''):
- """convert rpc original exception to the one with _Remote suffix."""
-
- # NOTE(jianingy): this function helps simulate the real world exceptions
+def to_remote_error(error):
+ """Converts the given exception to the one with the _Remote suffix.
+ This is how RPC exceptions are recreated on the caller's side, so
+ this helps better simulate how the exception mechanism actually works.
+ """
+ ex_type = type(error)
+ kwargs = error.kwargs if hasattr(error, 'kwargs') else {}
+ message = error.message
module = ex_type().__class__.__module__
str_override = lambda self: "%s\n<Traceback>" % message
new_ex_type = type(ex_type.__name__ + rpc_common._REMOTE_POSTFIX,
@@ -59,7 +63,7 @@ def remote_error(ex_type, message=''):
{'__str__': str_override, '__unicode__': str_override})
new_ex_type.__module__ = '%s%s' % (module, rpc_common._REMOTE_POSTFIX)
- return new_ex_type()
+ return new_ex_type(**kwargs)
class InstantiationDataTest(HeatTestCase):
@@ -398,7 +402,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'list_stacks',
'args': {},
'version': self.api_version},
- None).AndRaise(remote_error(AttributeError))
+ None).AndRaise(to_remote_error(AttributeError()))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -418,7 +422,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'list_stacks',
'args': {},
'version': self.api_version},
- None).AndRaise(remote_error(Exception))
+ None).AndRaise(to_remote_error(Exception()))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -513,6 +517,8 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._post('/stacks', json.dumps(body))
+ unknown_parameter = heat_exc.UnknownUserParameter(key='a')
+ missing_parameter = heat_exc.UserParameterMissing(key='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -523,7 +529,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(AttributeError))
+ None).AndRaise(to_remote_error(AttributeError()))
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'create_stack',
@@ -533,7 +539,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.UnknownUserParameter))
+ None).AndRaise(to_remote_error(unknown_parameter))
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'create_stack',
@@ -543,7 +549,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.UserParameterMissing))
+ None).AndRaise(to_remote_error(missing_parameter))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
self.controller.create,
@@ -579,6 +585,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._post('/stacks', json.dumps(body))
+ error = heat_exc.StackExists(stack_name='s')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -589,7 +596,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackExists))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -612,6 +619,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._post('/stacks', json.dumps(body))
+ error = heat_exc.StackValidationFailed(message='')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -622,7 +630,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackValidationFailed))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -678,13 +686,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._get('/stacks/%(stack_name)s' % locals())
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'identify_stack',
'args': {'stack_name': stack_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -727,13 +736,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._get('/stacks/%(stack_name)s/resources' % locals())
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'identify_stack',
'args': {'stack_name': stack_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -820,13 +830,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._get('/stacks/%(stack_name)s/%(stack_id)s' % identity)
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'show_stack',
'args': {'stack_identity': dict(identity)},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -844,13 +855,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._get('/stacks/%(stack_name)s/%(stack_id)s' % identity)
+ error = heat_exc.InvalidTenant(target='a', actual='b')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'show_stack',
'args': {'stack_identity': dict(identity)},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.InvalidTenant))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -887,15 +899,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
def test_get_template_err_notfound(self):
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
req = self._get('/stacks/%(stack_name)s/%(stack_id)s' % identity)
- template = {u'Foo': u'bar'}
+ error = error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'get_template',
'args': {'stack_identity': dict(identity)},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
@@ -958,6 +970,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._put('/stacks/%(stack_name)s/%(stack_id)s' % identity,
json.dumps(body))
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -968,7 +981,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'files': {},
'args': {'timeout_mins': 30}},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1021,6 +1034,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
req = self._delete('/stacks/%(stack_name)s/%(stack_id)s' % identity)
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
# Engine returns None when delete successful
rpc.call(req.context, self.topic,
@@ -1028,7 +1042,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'delete_stack',
'args': {'stack_identity': dict(identity)},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1122,13 +1136,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'AWS::EC2::EIP',
'AWS::EC2::EIPAssociation']
+ error = heat_exc.ServerError(body='')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'list_resource_types',
'args': {},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.ServerError))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1158,13 +1173,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
def test_generate_template_not_found(self):
req = self._get('/resource_types/NOT_FOUND/template')
+
+ error = heat_exc.ResourceTypeNotFound(type_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'generate_template',
'args': {'type_name': 'NOT_FOUND'},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.ResourceTypeNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
self.controller.generate_template,
@@ -1267,13 +1284,14 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(stack_identity._tenant_path() + '/resources')
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'list_stack_resources',
'args': {'stack_identity': stack_identity},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1354,6 +1372,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(res_identity._tenant_path())
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -1361,7 +1380,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
'args': {'stack_identity': stack_identity,
'resource_name': res_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1384,6 +1403,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(res_identity._tenant_path())
+ error = heat_exc.ResourceNotFound(stack_name='a', resource_name='b')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -1391,7 +1411,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
'args': {'stack_identity': stack_identity,
'resource_name': res_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.ResourceNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1414,6 +1434,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(res_identity._tenant_path())
+ error = heat_exc.ResourceNotAvailable(resource_name='')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -1421,7 +1442,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
'args': {'stack_identity': stack_identity,
'resource_name': res_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.ResourceNotAvailable))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1488,6 +1509,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(res_identity._tenant_path() + '/metadata')
+ error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -1495,7 +1517,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
'args': {'stack_identity': stack_identity,
'resource_name': res_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1518,6 +1540,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
req = self._get(res_identity._tenant_path() + '/metadata')
+ error = heat_exc.ResourceNotFound(stack_name='a', resource_name='b')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
@@ -1525,7 +1548,7 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
'args': {'stack_identity': stack_identity,
'resource_name': res_name},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.ResourceNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1699,13 +1722,14 @@ class EventControllerTest(ControllerTest, HeatTestCase):
req = self._get(stack_identity._tenant_path() + '/events')
+ error = error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'list_events',
'args': {'stack_identity': stack_identity},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -1943,13 +1967,14 @@ class EventControllerTest(ControllerTest, HeatTestCase):
req = self._get(stack_identity._tenant_path() +
'/resources/' + res_name + '/events/' + event_id)
+ error = error = heat_exc.StackNotFound(stack_name='a')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'list_events',
'args': {'stack_identity': stack_identity},
'version': self.api_version},
- None).AndRaise(remote_error(heat_exc.StackNotFound))
+ None).AndRaise(to_remote_error(error))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
@@ -2380,7 +2405,7 @@ class ActionControllerTest(ControllerTest, HeatTestCase):
'method': 'stack_suspend',
'args': {'stack_identity': stack_identity},
'version': self.api_version},
- None).AndRaise(remote_error(AttributeError))
+ None).AndRaise(to_remote_error(AttributeError()))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
diff --git a/heat/tests/test_wsgi.py b/heat/tests/test_wsgi.py
index e6e113027..ab26f2547 100644
--- a/heat/tests/test_wsgi.py
+++ b/heat/tests/test_wsgi.py
@@ -17,6 +17,7 @@
import datetime
+import stubout
import webob
from heat.common import exception
@@ -26,6 +27,10 @@ from heat.tests.common import HeatTestCase
class RequestTest(HeatTestCase):
+ def setUp(self):
+ self.stubs = stubout.StubOutForTesting()
+ super(RequestTest, self).setUp()
+
def test_content_type_missing(self):
request = wsgi.Request.blank('/tests/123')
self.assertRaises(exception.InvalidContentType,
@@ -74,9 +79,28 @@ class RequestTest(HeatTestCase):
result = request.best_match_content_type()
self.assertEqual(result, "application/json")
+ def test_best_match_language(self):
+ # Here we test that we are actually invoking language negotiation
+ # by webop and also that the default locale always available is en-US
+ request = wsgi.Request.blank('/')
+ accepted = 'unknown-lang'
+ request.headers = {'Accept-Language': accepted}
+
+ def fake_best_match(self, offers, default_match=None):
+ return default_match
+
+ self.stubs.SmartSet(request.accept_language,
+ 'best_match', fake_best_match)
+
+ self.assertEqual(request.best_match_language(), 'en_US')
+
class ResourceTest(HeatTestCase):
+ def setUp(self):
+ self.stubs = stubout.StubOutForTesting()
+ super(ResourceTest, self).setUp()
+
def test_get_action_args(self):
env = {
'wsgiorg.routing_args': [
@@ -160,6 +184,34 @@ class ResourceTest(HeatTestCase):
None)
self.assertRaises(webob.exc.HTTPBadRequest, resource, request)
+ def test_resource_call_error_handle_localized(self):
+ class Controller(object):
+ def delete(self, req, identity):
+ return (req, identity)
+
+ actions = {'action': 'delete', 'id': 12, 'body': 'data'}
+ env = {'wsgiorg.routing_args': [None, actions]}
+ request = wsgi.Request.blank('/tests/123', environ=env)
+ request.body = '{"foo" : "value"}'
+ message_es = "No Encontrado"
+ translated_ex = webob.exc.HTTPBadRequest(message_es)
+
+ resource = wsgi.Resource(Controller(),
+ wsgi.JSONRequestDeserializer(),
+ None)
+
+ def fake_translate_exception(ex, locale):
+ return translated_ex
+
+ self.stubs.SmartSet(wsgi,
+ 'translate_exception', fake_translate_exception)
+
+ try:
+ resource(request)
+ except webob.exc.HTTPBadRequest as e:
+ self.assertEquals(message_es, e.message)
+ self.m.VerifyAll()
+
class JSONResponseSerializerTest(HeatTestCase):