Update resource definitions after legacy in-place update

Since we remove a resource's definition after it is deleted, we must also
update a resource's definition after it is updated. Otherwise, a resource
that depended on the now-deleted resource prior to its last in-place update
could remain in the template, leaving the stack inoperable since it is
unable to calculate its own dependencies.

We already update the template in the backup stack when updating resources
in-place, and in the main stack when creating replacement resources. Also
update the main template when resources are updated in-place, not just when
they are replaced.

Change-Id: I97ddc6a970ffd27bfd40bb8f6bec8d1cbf28a815
Story: #2003612
Task: 24946
Task: 25740
(cherry picked from commit 75c912181d
 and 8bb1cef48f)
This commit is contained in:
Zane Bitter 2018-08-31 17:08:58 -04:00 committed by Rabi Mishra
parent 1599ee9b8f
commit 233bab7337
3 changed files with 41 additions and 3 deletions

View File

@ -184,6 +184,8 @@ class StackUpdate(object):
res_name)
self.previous_stack.t.add_resource(new_res.t)
self.previous_stack.t.store(self.previous_stack.context)
self.existing_stack.t.add_resource(new_res.t)
self.existing_stack.t.store(self.existing_stack.context)
LOG.info("Resource %(res_name)s for stack "
"%(stack_name)s updated",

View File

@ -226,7 +226,7 @@ class TestValueUpdate(TestValue):
param2=True, param_type2="boolean")),
]
def test_value(self):
def test_value_update(self):
ts1, tl1 = self.get_strict_and_loose_templates(self.param_type1)
ts2, tl2 = self.get_strict_and_loose_templates(self.param_type2)
@ -244,7 +244,7 @@ class TestValueUpdate(TestValue):
else:
# starting with param2, updating to param1
p2, p1, e2, e1 = self.param1, self.param2, env1, env2
stack = self.create_stack(t_initial, env=e1)
stack = self.create_stack(copy.deepcopy(t_initial), env=e1)
self.assertEqual(p1, stack['my_value2'].FnGetAtt('value'))
res1_id = stack['my_value'].id
res2_id = stack['my_value2'].id
@ -252,7 +252,7 @@ class TestValueUpdate(TestValue):
updated_stack = parser.Stack(
stack.context, 'updated_stack',
template.Template(t_updated, env=e2))
template.Template(copy.deepcopy(t_updated), env=e2))
updated_stack.validate()
stack.update(updated_stack)
self.assertEqual(p2, stack['my_value2'].FnGetAtt('value'))

View File

@ -726,3 +726,39 @@ resources:
}
}
self._test_conditional(test3)
def test_inplace_update_old_ref_deleted_failed_stack(self):
template = '''
heat_template_version: pike
resources:
test1:
type: OS::Heat::TestResource
properties:
value: test
test2:
type: OS::Heat::TestResource
properties:
value: {get_attr: [test1, output]}
test3:
type: OS::Heat::TestResource
properties:
value: test3
fail: false
action_wait_secs:
update: 5
'''
stack_identifier = self.stack_create(
template=template)
_template = template.replace('test1:',
'test-1:').replace('fail: false',
'fail: true')
updated_template = _template.replace(
'{get_attr: [test1',
'{get_attr: [test-1').replace('value: test3',
'value: test-3')
self.update_stack(stack_identifier,
template=updated_template,
expected_status='UPDATE_FAILED')
self.update_stack(stack_identifier, template=template,
expected_status='UPDATE_COMPLETE')