Do not attempt deletion of a DELETE_COMPLETE stack in service api
A stack may be in transient state where it is DELETE_COMPLETE, but has
has not actually been soft-deleted yet. For the purposes of
delete_stack in service.py, consider a DELETE_COMPLETE stack as
equivalent to a soft-deleted one (it soon will be), thereby avoiding a
race where we would have attempted to update the stack, running into a
foreign-key constraint issue for a non-existing user_cred.
Change-Id: Iec021e6a0df262d447fdf9ee1789603c7a1c55f8
Closes-Bug: #1626173
Closes-Bug: #1626107
(cherry picked from commit e1f161a19a
)
This commit is contained in:
parent
55a4aad7f9
commit
fb26ec9da5
@ -1358,6 +1358,10 @@ class EngineService(service.Service):
|
||||
"""
|
||||
|
||||
st = self._get_stack(cnxt, stack_identity)
|
||||
if (st.status == parser.Stack.COMPLETE and
|
||||
st.action == parser.Stack.DELETE):
|
||||
raise exception.EntityNotFound(entity='Stack', name=st.name)
|
||||
|
||||
LOG.info(_LI('Deleting stack %s'), st.name)
|
||||
stack = parser.Stack.load(cnxt, stack=st)
|
||||
self.resource_enforcer.enforce_stack(stack)
|
||||
|
@ -975,6 +975,17 @@ class StackServiceTest(common.HeatTestCase):
|
||||
outputs = self.eng.list_outputs(self.ctx, mock.ANY)
|
||||
self.assertEqual([], outputs)
|
||||
|
||||
def test_stack_delete_complete_is_not_found(self):
|
||||
mock_get_stack = self.patchobject(self.eng, '_get_stack')
|
||||
mock_get_stack.return_value = mock.MagicMock()
|
||||
mock_get_stack.return_value.status = parser.Stack.COMPLETE
|
||||
mock_get_stack.return_value.action = parser.Stack.DELETE
|
||||
ex = self.assertRaises(dispatcher.ExpectedException,
|
||||
self.eng.delete_stack,
|
||||
'irrelevant',
|
||||
'irrelevant')
|
||||
self.assertEqual(exception.EntityNotFound, ex.exc_info[0])
|
||||
|
||||
def test_get_environment(self):
|
||||
# Setup
|
||||
t = template_format.parse(tools.wp_template)
|
||||
|
Loading…
Reference in New Issue
Block a user