Avoid error on double-delete of nested stack
When deleting a stack that has a nested stack previously deleted, the process fails because the nested stack cannot be retrieved from the database. To solve the bug, the nested stack is now retrieved from the database ignoring the deleted stacks before the deletion process begins. Then a NotFound exception is raised, and then when it's catched the nested stack will be ignored. Change-Id: Ib863527dbfb0200b833a4e90b5a4fd50f469c1ce Closes-Bug: #1261436
This commit is contained in:
parent
e3688f5f1a
commit
7233ba1b14
|
@ -65,7 +65,8 @@ class StackResource(resource.Resource):
|
|||
if self._nested is None and self.resource_id is not None:
|
||||
self._nested = parser.Stack.load(self.context,
|
||||
self.resource_id,
|
||||
parent_resource=self)
|
||||
parent_resource=self,
|
||||
show_deleted=False)
|
||||
|
||||
if self._nested is None:
|
||||
raise exception.NotFound(_('Nested stack not found in DB'))
|
||||
|
|
|
@ -480,6 +480,41 @@ Resources:
|
|||
self.assertIn('Recursion depth exceeds', stack.status_reason)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_nested_stack_delete(self):
|
||||
urlfetch.get('https://server.test/the.template').MultipleTimes().\
|
||||
AndReturn(self.nested_template)
|
||||
self.m.ReplayAll()
|
||||
|
||||
stack = self.create_stack(self.test_template)
|
||||
rsrc = stack['the_nested']
|
||||
scheduler.TaskRunner(rsrc.delete)()
|
||||
self.assertEqual((stack.DELETE, stack.COMPLETE), rsrc.state)
|
||||
|
||||
nested_stack = parser.Stack.load(utils.dummy_context(
|
||||
'test_username', 'aaaa', 'password'), rsrc.resource_id)
|
||||
self.assertEqual((stack.DELETE, stack.COMPLETE), nested_stack.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_nested_stack_delete_then_delete_parent_stack(self):
|
||||
urlfetch.get('https://server.test/the.template').MultipleTimes().\
|
||||
AndReturn(self.nested_template)
|
||||
self.m.ReplayAll()
|
||||
|
||||
stack = self.create_stack(self.test_template)
|
||||
rsrc = stack['the_nested']
|
||||
|
||||
nested_stack = parser.Stack.load(utils.dummy_context(
|
||||
'test_username', 'aaaa', 'password'), rsrc.resource_id)
|
||||
nested_stack.delete()
|
||||
|
||||
stack = parser.Stack.load(utils.dummy_context(
|
||||
'test_username', 'aaaa', 'password'), stack.id)
|
||||
stack.delete()
|
||||
self.assertEqual((stack.DELETE, stack.COMPLETE), stack.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
class ResDataResource(generic_rsrc.GenericResource):
|
||||
def handle_create(self):
|
||||
|
|
|
@ -241,7 +241,8 @@ class StackResourceTest(HeatTestCase):
|
|||
self.m.StubOutWithMock(parser.Stack, 'load')
|
||||
parser.Stack.load(self.parent_resource.context,
|
||||
self.parent_resource.resource_id,
|
||||
parent_resource=self.parent_resource).AndReturn('s')
|
||||
parent_resource=self.parent_resource,
|
||||
show_deleted=False).AndReturn('s')
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.parent_resource.nested()
|
||||
|
@ -257,7 +258,8 @@ class StackResourceTest(HeatTestCase):
|
|||
self.m.StubOutWithMock(parser.Stack, 'load')
|
||||
parser.Stack.load(self.parent_resource.context,
|
||||
self.parent_resource.resource_id,
|
||||
parent_resource=self.parent_resource)
|
||||
parent_resource=self.parent_resource,
|
||||
show_deleted=False)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(exception.NotFound, self.parent_resource.nested)
|
||||
|
@ -273,6 +275,21 @@ class StackResourceTest(HeatTestCase):
|
|||
self.parent_resource.delete_nested()
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_delete_nested_not_found_nested_stack(self):
|
||||
self.parent_resource.create_with_template(self.templ,
|
||||
{"KeyName": "key"})
|
||||
self.stack = self.parent_resource.nested()
|
||||
|
||||
self.parent_resource._nested = None
|
||||
self.m.StubOutWithMock(parser.Stack, 'load')
|
||||
parser.Stack.load(self.parent_resource.context,
|
||||
self.parent_resource.resource_id,
|
||||
parent_resource=self.parent_resource,
|
||||
show_deleted=False).AndRaise(exception.NotFound)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(self.parent_resource.delete_nested())
|
||||
|
||||
def test_get_output_ok(self):
|
||||
nested = self.m.CreateMockAnything()
|
||||
self.m.StubOutWithMock(stack_resource.StackResource, 'nested')
|
||||
|
|
Loading…
Reference in New Issue