make heat-api return a parsable error
add a wsgi middleware (faultwrap) that catches exceptions and transform those exceptions into a parsable format according to 'Content-Type' of the request. Fixes bug 1158598 Implements blueprint exception-formatting Change-Id: Iacdb8cc119b250ff1e39c99b7a7f66fd4c35e7d9
This commit is contained in:
parent
fe1557d60d
commit
c5ab33614b
|
@ -1,7 +1,7 @@
|
|||
|
||||
# heat-api pipeline
|
||||
[pipeline:heat-api]
|
||||
pipeline = versionnegotiation authtoken context apiv1app
|
||||
pipeline = faultwrap versionnegotiation authtoken context apiv1app
|
||||
|
||||
# heat-api pipeline for standalone heat
|
||||
# ie. uses alternative auth backend that authenticates users against keystone
|
||||
|
@ -12,7 +12,7 @@ pipeline = versionnegotiation authtoken context apiv1app
|
|||
# flavor = standalone
|
||||
#
|
||||
[pipeline:heat-api-standalone]
|
||||
pipeline = versionnegotiation authpassword context apiv1app
|
||||
pipeline = faultwrap versionnegotiation authpassword context apiv1app
|
||||
|
||||
# heat-api pipeline for custom cloud backends
|
||||
# i.e. in heat-api.conf:
|
||||
|
@ -20,7 +20,7 @@ pipeline = versionnegotiation authpassword context apiv1app
|
|||
# flavor = custombackend
|
||||
#
|
||||
[pipeline:heat-api-custombackend]
|
||||
pipeline = versionnegotiation context custombackendauth apiv1app
|
||||
pipeline = faultwrap versionnegotiation context custombackendauth apiv1app
|
||||
|
||||
# heat-api-cfn pipeline
|
||||
[pipeline:heat-api-cfn]
|
||||
|
@ -56,6 +56,10 @@ heat.app_factory = heat.api.cloudwatch:API
|
|||
paste.filter_factory = heat.common.wsgi:filter_factory
|
||||
heat.filter_factory = heat.api.openstack:version_negotiation_filter
|
||||
|
||||
[filter:faultwrap]
|
||||
paste.filter_factory = heat.common.wsgi:filter_factory
|
||||
heat.filter_factory = heat.api.openstack:faultwrap_filter
|
||||
|
||||
[filter:cfnversionnegotiation]
|
||||
paste.filter_factory = heat.common.wsgi:filter_factory
|
||||
heat.filter_factory = heat.api.cfn:version_negotiation_filter
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2013 Unitedstack Inc.
|
||||
#
|
||||
# Author: Jianing YANG (jianingy@unitedstack.com)
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""A middleware that turns exceptions into parsable string. Inspired by
|
||||
Cinder's faultwrapper
|
||||
"""
|
||||
|
||||
import traceback
|
||||
import webob
|
||||
|
||||
from heat.openstack.common import log as logging
|
||||
import heat.openstack.common.rpc.common as rpc_common
|
||||
|
||||
from heat.common import wsgi
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Fault(object):
|
||||
|
||||
def __init__(self, error):
|
||||
self.error = error
|
||||
|
||||
@webob.dec.wsgify(RequestClass=wsgi.Request)
|
||||
def __call__(self, req):
|
||||
if req.content_type == 'application/xml':
|
||||
serializer = wsgi.XMLResponseSerializer()
|
||||
else:
|
||||
serializer = wsgi.JSONResponseSerializer()
|
||||
resp = webob.Response(request=req)
|
||||
default_webob_exc = webob.exc.HTTPInternalServerError()
|
||||
resp.status_code = self.error.get('code', default_webob_exc.code)
|
||||
serializer.default(resp, self.error)
|
||||
return resp
|
||||
|
||||
|
||||
class FaultWrapper(wsgi.Middleware):
|
||||
"""Replace error body with something the client can parse."""
|
||||
|
||||
error_map = {
|
||||
'AttributeError': webob.exc.HTTPBadRequest,
|
||||
'ValueError': webob.exc.HTTPBadRequest,
|
||||
'StackNotFound': webob.exc.HTTPNotFound,
|
||||
'ResourceNotFound': webob.exc.HTTPNotFound,
|
||||
'ResourceNotAvailable': webob.exc.HTTPNotFound,
|
||||
'PhysicalResourceNotFound': webob.exc.HTTPNotFound,
|
||||
'InvalidTenant': webob.exc.HTTPForbidden,
|
||||
'StackExists': webob.exc.HTTPConflict,
|
||||
'StackValidationFailed': webob.exc.HTTPBadRequest,
|
||||
'InvalidTemplateReference': webob.exc.HTTPBadRequest,
|
||||
'UnknownUserParameter': webob.exc.HTTPBadRequest,
|
||||
'RevertFailed': webob.exc.HTTPInternalServerError,
|
||||
'ServerBuildFailed': webob.exc.HTTPInternalServerError,
|
||||
'NotSupported': webob.exc.HTTPBadRequest,
|
||||
'MissingCredentialError': webob.exc.HTTPBadRequest,
|
||||
'UserParameterMissing': webob.exc.HTTPBadRequest,
|
||||
}
|
||||
|
||||
def _error(self, ex):
|
||||
|
||||
ex_type = ex.__class__.__name__
|
||||
|
||||
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)
|
||||
else:
|
||||
message = str(ex)
|
||||
trace = traceback.format_exc()
|
||||
|
||||
webob_exc = self.error_map.get(ex_type,
|
||||
webob.exc.HTTPInternalServerError)
|
||||
|
||||
error = {
|
||||
'code': webob_exc.code,
|
||||
'title': webob_exc.title,
|
||||
'explanation': webob_exc.explanation,
|
||||
'error': {
|
||||
'message': message,
|
||||
'type': ex_type,
|
||||
'traceback': trace,
|
||||
}
|
||||
}
|
||||
|
||||
return error
|
||||
|
||||
def process_request(self, req):
|
||||
try:
|
||||
return req.get_response(self.application)
|
||||
except Exception as exc:
|
||||
return req.get_response(Fault(self._error(exc)))
|
|
@ -14,9 +14,14 @@
|
|||
# under the License.
|
||||
|
||||
from heat.api.middleware.version_negotiation import VersionNegotiationFilter
|
||||
from heat.api.middleware.fault import FaultWrapper
|
||||
from heat.api.openstack import versions
|
||||
|
||||
|
||||
def version_negotiation_filter(app, conf, **local_conf):
|
||||
return VersionNegotiationFilter(versions.Controller, app,
|
||||
conf, **local_conf)
|
||||
|
||||
|
||||
def faultwrap_filter(app, conf, **local_conf):
|
||||
return FaultWrapper(app)
|
||||
|
|
|
@ -67,31 +67,10 @@ def make_link(req, identity, relationship='self'):
|
|||
|
||||
|
||||
def remote_error(ex):
|
||||
"""
|
||||
Map rpc_common.RemoteError exceptions returned by the engine
|
||||
to webob exceptions which can be used to return
|
||||
properly formatted error responses.
|
||||
"""The RemoteError mapping work has been moved to heat.api.middleware.fault
|
||||
which handles error formating now. This function will be deprecated
|
||||
in the future, so please raise exceptions directly.
|
||||
"""
|
||||
|
||||
error_map = {
|
||||
'AttributeError': exc.HTTPBadRequest,
|
||||
'ValueError': exc.HTTPBadRequest,
|
||||
'StackNotFound': exc.HTTPNotFound,
|
||||
'ResourceNotFound': exc.HTTPNotFound,
|
||||
'ResourceNotAvailable': exc.HTTPNotFound,
|
||||
'PhysicalResourceNotFound': exc.HTTPNotFound,
|
||||
'InvalidTenant': exc.HTTPForbidden,
|
||||
'StackExists': exc.HTTPConflict,
|
||||
'StackValidationFailed': exc.HTTPBadRequest,
|
||||
'InvalidTemplateReference': exc.HTTPBadRequest,
|
||||
'UnknownUserParameter': exc.HTTPBadRequest,
|
||||
'RevertFailed': exc.HTTPInternalServerError,
|
||||
'ServerBuildFailed': exc.HTTPInternalServerError,
|
||||
'NotSupported': exc.HTTPBadRequest,
|
||||
'MissingCredentialError': exc.HTTPBadRequest,
|
||||
'UserParameterMissing': exc.HTTPBadRequest,
|
||||
}
|
||||
|
||||
Exc = error_map.get(ex.exc_type, exc.HTTPInternalServerError)
|
||||
|
||||
raise Exc(str(ex))
|
||||
# TODO(jianingy): add a deprecated warning here to inform others.
|
||||
raise ex
|
||||
|
|
|
@ -116,6 +116,14 @@ cfg.CONF.register_opts(rpc_opts)
|
|||
cfg.CONF.register_group(paste_deploy_group)
|
||||
cfg.CONF.register_opts(paste_deploy_opts, group=paste_deploy_group)
|
||||
|
||||
# TODO(jianingy): I'll set allowed_rpc_exception_modules here for now.
|
||||
# after figure out why rpc_set_default was not called,
|
||||
# I'll move these settings into rpc_set_default()
|
||||
allowed_rpc_exception_modules = cfg.CONF.allowed_rpc_exception_modules
|
||||
allowed_rpc_exception_modules.append('heat.common.exception')
|
||||
cfg.CONF.set_default(name='allowed_rpc_exception_modules',
|
||||
default=allowed_rpc_exception_modules)
|
||||
|
||||
|
||||
def rpc_set_default():
|
||||
rpc.set_defaults(control_exchange='heat')
|
||||
|
|
|
@ -19,9 +19,11 @@ import webob.exc
|
|||
|
||||
from heat.common import identifier
|
||||
from heat.openstack.common import rpc
|
||||
import heat.openstack.common.rpc.common as rpc_common
|
||||
|
||||
from heat.common import exception as heat_exc
|
||||
from heat.common.wsgi import Request
|
||||
from heat.common import urlfetch
|
||||
from heat.openstack.common.rpc import common as rpc_common
|
||||
from heat.rpc import api as rpc_api
|
||||
from heat.tests.common import HeatTestCase
|
||||
|
||||
|
@ -32,6 +34,33 @@ import heat.api.openstack.v1.events as events
|
|||
import heat.api.openstack.v1.actions as actions
|
||||
from heat.tests.utils import dummy_context
|
||||
|
||||
import heat.api.middleware.fault as fault
|
||||
|
||||
|
||||
def request_with_middleware(middleware, func, req, *args, **kwargs):
|
||||
|
||||
@webob.dec.wsgify
|
||||
def _app(req):
|
||||
return func(req, *args, **kwargs)
|
||||
|
||||
resp = middleware(_app).process_request(req)
|
||||
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
|
||||
|
||||
module = ex_type().__class__.__module__
|
||||
str_override = lambda self: "%s\n<Traceback>" % message
|
||||
new_ex_type = type(ex_type.__name__ + rpc_common._REMOTE_POSTFIX,
|
||||
(ex_type,),
|
||||
{'__str__': str_override, '__unicode__': str_override})
|
||||
|
||||
new_ex_type.__module__ = '%s%s' % (module, rpc_common._REMOTE_POSTFIX)
|
||||
return new_ex_type()
|
||||
|
||||
|
||||
class InstantiationDataTest(HeatTestCase):
|
||||
|
||||
|
@ -369,12 +398,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_stacks',
|
||||
'args': {},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("AttributeError"))
|
||||
None).AndRaise(remote_error(AttributeError))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant)
|
||||
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'AttributeError')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_index_rmt_interr(self):
|
||||
|
@ -386,12 +418,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_stacks',
|
||||
'args': {},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("Exception"))
|
||||
None).AndRaise(remote_error(Exception))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPInternalServerError,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant)
|
||||
|
||||
self.assertEqual(resp.json['code'], 500)
|
||||
self.assertEqual(resp.json['error']['type'], 'Exception')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_create(self):
|
||||
|
@ -488,7 +523,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("AttributeError"))
|
||||
None).AndRaise(remote_error(AttributeError))
|
||||
rpc.call(req.context, self.topic,
|
||||
{'namespace': None,
|
||||
'method': 'create_stack',
|
||||
|
@ -498,7 +533,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("UnknownUserParameter"))
|
||||
None).AndRaise(remote_error(heat_exc.UnknownUserParameter))
|
||||
rpc.call(req.context, self.topic,
|
||||
{'namespace': None,
|
||||
'method': 'create_stack',
|
||||
|
@ -508,20 +543,28 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("UserParameterMissing"))
|
||||
|
||||
None).AndRaise(remote_error(heat_exc.UserParameterMissing))
|
||||
self.m.ReplayAll()
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'AttributeError')
|
||||
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'UnknownUserParameter')
|
||||
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'UserParameterMissing')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_create_err_existing(self):
|
||||
|
@ -546,12 +589,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackExists"))
|
||||
None).AndRaise(remote_error(heat_exc.StackExists))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPConflict,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 409)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackExists')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_create_err_engine(self):
|
||||
|
@ -576,14 +622,15 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError(
|
||||
'StackValidationFailed',
|
||||
'Something went wrong'))
|
||||
None).AndRaise(remote_error(heat_exc.StackValidationFailed))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.create,
|
||||
req, tenant_id=self.tenant, body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackValidationFailed')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_lookup(self):
|
||||
|
@ -637,11 +684,16 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'identify_stack',
|
||||
'args': {'stack_name': stack_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound, self.controller.lookup,
|
||||
req, tenant_id=self.tenant, stack_name=stack_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.lookup,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_lookup_resource(self):
|
||||
|
@ -681,12 +733,17 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'identify_stack',
|
||||
'args': {'stack_name': stack_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound, self.controller.lookup,
|
||||
req, tenant_id=self.tenant, stack_name=stack_name,
|
||||
path='resources')
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.lookup,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_name,
|
||||
path='resources')
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show(self):
|
||||
|
@ -769,14 +826,17 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'show_stack',
|
||||
'args': {'stack_identity': dict(identity)},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show_invalidtenant(self):
|
||||
|
@ -790,14 +850,17 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'show_stack',
|
||||
'args': {'stack_identity': dict(identity)},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("InvalidTenant"))
|
||||
None).AndRaise(remote_error(heat_exc.InvalidTenant))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPForbidden,
|
||||
self.controller.show,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 403)
|
||||
self.assertEqual(resp.json['error']['type'], 'InvalidTenant')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_get_template(self):
|
||||
|
@ -832,15 +895,18 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'get_template',
|
||||
'args': {'stack_identity': dict(identity)},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.template,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.template,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_update(self):
|
||||
|
@ -902,15 +968,18 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'files': {},
|
||||
'args': {'timeout_mins': 30}},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.update,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id,
|
||||
body=body)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.update,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id,
|
||||
body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_delete(self):
|
||||
|
@ -959,14 +1028,17 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'delete_stack',
|
||||
'args': {'stack_identity': dict(identity)},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.delete,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.delete,
|
||||
req, tenant_id=identity.tenant,
|
||||
stack_name=identity.stack_name,
|
||||
stack_id=identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_validate_template(self):
|
||||
|
@ -1056,12 +1128,14 @@ class StackControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_resource_types',
|
||||
'args': {},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("ValueError"))
|
||||
None).AndRaise(remote_error(heat_exc.ServerError))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPInternalServerError,
|
||||
self.controller.list_resource_types,
|
||||
req, tenant_id=self.tenant)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.list_resource_types,
|
||||
req, tenant_id=self.tenant)
|
||||
self.assertEqual(resp.json['code'], 500)
|
||||
self.assertEqual(resp.json['error']['type'], 'ServerError')
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
|
@ -1163,14 +1237,17 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_stack_resources',
|
||||
'args': {'stack_identity': stack_identity},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show(self):
|
||||
|
@ -1248,15 +1325,18 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'args': {'stack_identity': stack_identity,
|
||||
'resource_name': res_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show_nonexist_resource(self):
|
||||
|
@ -1275,15 +1355,18 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'args': {'stack_identity': stack_identity,
|
||||
'resource_name': res_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("ResourceNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.ResourceNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'ResourceNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show_uncreated_resource(self):
|
||||
|
@ -1302,15 +1385,18 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'args': {'stack_identity': stack_identity,
|
||||
'resource_name': res_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("ResourceNotAvailable"))
|
||||
None).AndRaise(remote_error(heat_exc.ResourceNotAvailable))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'ResourceNotAvailable')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_metadata_show(self):
|
||||
|
@ -1373,15 +1459,18 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'args': {'stack_identity': stack_identity,
|
||||
'resource_name': res_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.metadata,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.metadata,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_metadata_show_nonexist_resource(self):
|
||||
|
@ -1400,15 +1489,18 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
|
|||
'args': {'stack_identity': stack_identity,
|
||||
'resource_name': res_name},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("ResourceNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.ResourceNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.metadata,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.metadata,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'ResourceNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
|
@ -1577,14 +1669,17 @@ class EventControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_events',
|
||||
'args': {'stack_identity': stack_identity},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_index_resource_nonexist(self):
|
||||
|
@ -1818,15 +1913,19 @@ class EventControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'list_events',
|
||||
'args': {'stack_identity': stack_identity},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("StackNotFound"))
|
||||
None).AndRaise(remote_error(heat_exc.StackNotFound))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name, event_id=event_id)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.show,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
resource_name=res_name,
|
||||
event_id=event_id)
|
||||
|
||||
self.assertEqual(resp.json['code'], 404)
|
||||
self.assertEqual(resp.json['error']['type'], 'StackNotFound')
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
|
@ -2233,15 +2332,18 @@ class ActionControllerTest(ControllerTest, HeatTestCase):
|
|||
'method': 'stack_suspend',
|
||||
'args': {'stack_identity': stack_identity},
|
||||
'version': self.api_version},
|
||||
None).AndRaise(rpc_common.RemoteError("AttributeError"))
|
||||
None).AndRaise(remote_error(AttributeError))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.action,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
body=body)
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.action,
|
||||
req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id,
|
||||
body=body)
|
||||
|
||||
self.assertEqual(resp.json['code'], 400)
|
||||
self.assertEqual(resp.json['error']['type'], 'AttributeError')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_action_badaction_ise(self):
|
||||
|
|
Loading…
Reference in New Issue