summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngus Salkeld <asalkeld@mirantis.com>2015-03-27 12:00:42 +1000
committerMiguel Grinberg <miguelgrinberg50@gmail.com>2015-03-27 15:12:54 -0700
commit29365bda1cab48aad7b98907af521130321e526a (patch)
tree8585335bef64f31ef03bdecd63c69d7b0c547882
parent1e6b0ba66cc244fcc7ee7860ca3f96a7bea5fb8f (diff)
downloadheat-29365bda1cab48aad7b98907af521130321e526a.tar.gz
Set state to failed if we get a base exception
The scheduler only raises ExceptionGroup if aggregate_exceptions is True. This change adds a catch-all exception handler that sets the stack to failed on any exceptions. Co-Authored-By: Miguel Grinberg <miguel.grinberg@gmail.com> Change-Id: I76a6e87924416335921115ec3147a991659cfb2e Closes-Bug: #1436128
-rwxr-xr-xheat/engine/stack.py11
-rw-r--r--heat/tests/test_stack.py29
2 files changed, 37 insertions, 3 deletions
diff --git a/heat/engine/stack.py b/heat/engine/stack.py
index 373f2fefc..00bfbf451 100755
--- a/heat/engine/stack.py
+++ b/heat/engine/stack.py
@@ -719,12 +719,17 @@ class Stack(collections.Mapping):
try:
yield action_task()
- except (exception.ResourceFailure, scheduler.ExceptionGroup) as ex:
- stack_status = self.FAILED
- reason = 'Resource %s failed: %s' % (action, six.text_type(ex))
except scheduler.Timeout:
stack_status = self.FAILED
reason = '%s timed out' % action.title()
+ except Exception as ex:
+ # We use a catch-all here to ensure any raised exceptions
+ # make the stack fail. This is necessary for when
+ # aggregate_exceptions is false, as in that case we don't get
+ # ExceptionGroup, but the raw exception.
+ # see scheduler.py line 395-399
+ stack_status = self.FAILED
+ reason = 'Resource %s failed: %s' % (action, six.text_type(ex))
self.state_set(action, stack_status, reason)
diff --git a/heat/tests/test_stack.py b/heat/tests/test_stack.py
index acf055b08..e337af828 100644
--- a/heat/tests/test_stack.py
+++ b/heat/tests/test_stack.py
@@ -936,6 +936,35 @@ class StackTest(common.HeatTestCase):
self.m.VerifyAll()
+ def test_create_bad_attribute(self):
+ tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
+ 'Resources': {
+ 'AResource': {'Type': 'GenericResourceType'},
+ 'BResource': {'Type': 'ResourceWithPropsType',
+ 'Properties': {
+ 'Foo': {'Fn::GetAtt': ['AResource',
+ 'Foo']}}}}}
+ self.stack = stack.Stack(self.ctx, 'bad_attr_test_stack',
+ template.Template(tmpl),
+ disable_rollback=True)
+
+ self.m.StubOutWithMock(generic_rsrc.ResourceWithProps,
+ '_update_stored_properties')
+
+ generic_rsrc.ResourceWithProps._update_stored_properties().AndRaise(
+ exception.InvalidTemplateAttribute(resource='a', key='foo'))
+
+ self.m.ReplayAll()
+
+ self.stack.store()
+ self.stack.create()
+
+ self.assertEqual((stack.Stack.CREATE, stack.Stack.FAILED),
+ self.stack.state)
+ self.assertEqual('Resource CREATE failed: The Referenced Attribute '
+ '(a foo) is incorrect.', self.stack.status_reason)
+ self.m.VerifyAll()
+
def test_stack_create_timeout(self):
self.m.StubOutWithMock(scheduler.DependencyTaskGroup, '__call__')
self.m.StubOutWithMock(scheduler, 'wallclock')