diff options
author | Angus Salkeld <asalkeld@mirantis.com> | 2015-03-27 12:00:42 +1000 |
---|---|---|
committer | Miguel Grinberg <miguelgrinberg50@gmail.com> | 2015-03-27 15:12:54 -0700 |
commit | 29365bda1cab48aad7b98907af521130321e526a (patch) | |
tree | 8585335bef64f31ef03bdecd63c69d7b0c547882 | |
parent | 1e6b0ba66cc244fcc7ee7860ca3f96a7bea5fb8f (diff) | |
download | heat-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-x | heat/engine/stack.py | 11 | ||||
-rw-r--r-- | heat/tests/test_stack.py | 29 |
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') |