Save updated-in-place resources to backup stack
The patch changes the approach of resource backup during stack
update. It stores the definition of resource that needs to be
updated in-place to backup stack(if it was not created before).
Without this functionality, InvalidTemplateReference will be thrown
every time when update-replaced resource has a reference to updated
in-place resource and stack update was failed. In this case, backup
stack has a resource that refers to not-presented another resource
and backup stack deletion generates an exception.
Change-Id: I436c44a579bb4df3031d1a17b9ca5b62da37afeb
Closes-bug: #1446575
(cherry-picked from commit f2edd0d68e
)
This commit is contained in:
parent
be9af2811c
commit
da3777342a
|
@ -135,6 +135,15 @@ class StackUpdate(object):
|
|||
except resource.UpdateReplace:
|
||||
pass
|
||||
else:
|
||||
# Save resource definition to backup stack if it is not
|
||||
# present in backup stack template already
|
||||
if res_name not in self.previous_stack.t[
|
||||
self.previous_stack.t.RESOURCES]:
|
||||
definition = existing_res.t.reparse(self.previous_stack,
|
||||
existing_res.stack.t)
|
||||
self.previous_stack.t.add_resource(definition)
|
||||
self.previous_stack.t.store(self.previous_stack.context)
|
||||
|
||||
LOG.info(_LI("Resource %(res_name)s for stack %(stack_name)s "
|
||||
"updated"),
|
||||
{'res_name': res_name,
|
||||
|
|
|
@ -1492,3 +1492,71 @@ class StackUpdateTest(common.HeatTestCase):
|
|||
self.assertEqual((stack.Stack.UPDATE, stack.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
self.assertEqual('foo', self.stack['AResource'].properties['Foo'])
|
||||
|
||||
def test_delete_stack_when_update_failed_twice(self):
|
||||
"""Test when stack update failed twice and delete the stack.
|
||||
|
||||
Test checks the following scenario:
|
||||
1. Create stack
|
||||
2. Update stack (failed)
|
||||
3. Update stack (failed)
|
||||
4. Delete stack
|
||||
The test checks the behavior of backup stack when update is failed.
|
||||
If some resources were not backed up correctly then test will fail.
|
||||
"""
|
||||
tmpl_create = {
|
||||
'heat_template_version': '2013-05-23',
|
||||
'resources': {
|
||||
'Ares': {'type': 'GenericResourceType'}
|
||||
}
|
||||
}
|
||||
# create a stack
|
||||
self.stack = stack.Stack(self.ctx, 'update_fail_test_stack',
|
||||
template.Template(tmpl_create),
|
||||
disable_rollback=True)
|
||||
self.stack.store()
|
||||
self.stack.create()
|
||||
self.assertEqual((stack.Stack.CREATE, stack.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
|
||||
tmpl_update = {
|
||||
'heat_template_version': '2013-05-23',
|
||||
'resources': {
|
||||
'Ares': {'type': 'GenericResourceType'},
|
||||
'Bres': {'type': 'GenericResourceType'},
|
||||
'Cres': {
|
||||
'type': 'ResourceWithPropsType',
|
||||
'properties': {
|
||||
'Foo': {'get_resource': 'Bres'},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mock_create = self.patchobject(
|
||||
generic_rsrc.ResourceWithProps,
|
||||
'handle_create',
|
||||
side_effect=[Exception, Exception])
|
||||
|
||||
updated_stack_first = stack.Stack(self.ctx,
|
||||
'update_fail_test_stack',
|
||||
template.Template(tmpl_update))
|
||||
self.stack.update(updated_stack_first)
|
||||
self.stack.resources['Cres'].resource_id_set('c_res')
|
||||
self.assertEqual((stack.Stack.UPDATE, stack.Stack.FAILED),
|
||||
self.stack.state)
|
||||
|
||||
# try to update the stack again
|
||||
updated_stack_second = stack.Stack(self.ctx,
|
||||
'update_fail_test_stack',
|
||||
template.Template(tmpl_update))
|
||||
self.stack.update(updated_stack_second)
|
||||
self.assertEqual((stack.Stack.UPDATE, stack.Stack.FAILED),
|
||||
self.stack.state)
|
||||
|
||||
self.assertEqual(mock_create.call_count, 2)
|
||||
|
||||
# delete the failed stack
|
||||
self.stack.delete()
|
||||
self.assertEqual((stack.Stack.DELETE, stack.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
|
|
Loading…
Reference in New Issue