diff --git a/heat/engine/stack.py b/heat/engine/stack.py index d4c6cf3698..cbffbab34c 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -882,7 +882,7 @@ class Stack(collections.Mapping): exp_trvsl=self.current_traversal) return updated else: - stack.update_and_save(values) + stack.update_and_save(values) def _send_notification_and_add_event(self): notification.send(self) @@ -1956,6 +1956,15 @@ class Stack(collections.Mapping): sync_point.delete_all(self.context, self.id, self.current_traversal) if (self.action, self.status) == (self.DELETE, self.COMPLETE): + if not self.owner_id: + status, reason = self._delete_credentials( + self.status, + self.status_reason, + False) + if status == self.FAILED: + # something wrong when delete credentials, set FAILED + self.state_set(self.action, status, reason) + return try: stack_object.Stack.delete(self.context, self.id) except exception.NotFound: diff --git a/heat/tests/test_convg_stack.py b/heat/tests/test_convg_stack.py index 84f9a76aa3..0a29113484 100644 --- a/heat/tests/test_convg_stack.py +++ b/heat/tests/test_convg_stack.py @@ -379,6 +379,37 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase): stack.purge_db() self.assertTrue(mock_tmpl_delete.called) + @mock.patch.object(parser.Stack, '_delete_credentials') + @mock.patch.object(stack_object.Stack, 'delete') + def test_purge_db_deletes_creds(self, mock_delete_stack, + mock_creds_delete, mock_cr): + stack = tools.get_stack('test_stack', utils.dummy_context(), + template=tools.string_template_five, + convergence=True) + reason = 'stack delete complete' + mock_creds_delete.return_value = (stack.COMPLETE, reason) + stack.state_set(stack.DELETE, stack.COMPLETE, reason) + stack.purge_db() + self.assertTrue(mock_creds_delete.called) + self.assertTrue(mock_delete_stack.called) + + @mock.patch.object(parser.Stack, '_delete_credentials') + @mock.patch.object(stack_object.Stack, 'delete') + def test_purge_db_deletes_creds_failed(self, mock_delete_stack, + mock_creds_delete, mock_cr): + stack = tools.get_stack('test_stack', utils.dummy_context(), + template=tools.string_template_five, + convergence=True) + + reason = 'stack delete complete' + failed_reason = 'Error deleting trust' + mock_creds_delete.return_value = (stack.FAILED, failed_reason) + stack.state_set(stack.DELETE, stack.COMPLETE, reason) + stack.purge_db() + self.assertTrue(mock_creds_delete.called) + self.assertFalse(mock_delete_stack.called) + self.assertEqual((stack.DELETE, stack.FAILED), stack.state) + @mock.patch.object(raw_template_object.RawTemplate, 'delete') def test_purge_db_does_not_delete_previous_template_when_stack_fails( self, mock_tmpl_delete, mock_cr):