Copy template version when update fails

When an update fails, we may have copy some chunk of resources or
parameters to the new template. If the version was updated and the new
resources require the version, this can lead to a state where the stack
is in an usable state. This synchronizes the version when a failure
happens.

Change-Id: I2faf8f3541fc800ea61c417e5575f4a56a83665b
Closes-Bug: #1620696
This commit is contained in:
Thomas Herve 2017-04-20 15:11:08 +02:00
parent 8b1d912a56
commit 45fde10197
2 changed files with 53 additions and 0 deletions

View File

@ -1579,9 +1579,14 @@ class Stack(collections.Mapping):
# and new stack resources, we should have user params of both. # and new stack resources, we should have user params of both.
existing_params.load(newstack.t.env.user_env_as_dict()) existing_params.load(newstack.t.env.user_env_as_dict())
self.t.env = existing_params self.t.env = existing_params
# Update the template version, in case new things were used
self.t.t[newstack.t.version[0]] = max(
newstack.t.version[1], self.t.version[1])
self.t.merge_snippets(newstack.t) self.t.merge_snippets(newstack.t)
self.t.store(self.context) self.t.store(self.context)
backup_stack.t.env = existing_params backup_stack.t.env = existing_params
backup_stack.t.t[newstack.t.version[0]] = max(
newstack.t.version[1], self.t.version[1])
backup_stack.t.merge_snippets(newstack.t) backup_stack.t.merge_snippets(newstack.t)
backup_stack.t.store(self.context) backup_stack.t.store(self.context)
self.store() self.store()

View File

@ -625,3 +625,51 @@ resources:
self.assertEqual({'test1': 'OS::Heat::TestResource', self.assertEqual({'test1': 'OS::Heat::TestResource',
'test2': 'My::TestResource'}, 'test2': 'My::TestResource'},
self.list_resources(stack_identifier)) self.list_resources(stack_identifier))
def test_stack_update_with_new_version(self):
"""Update handles new template version in failure.
If a stack update fails while changing the template version, update is
able to handle the new version fine.
"""
stack_identifier = self.stack_create(
template=test_template_one_resource)
# Update with a new function and make the update fails
template = _change_rsrc_properties(test_template_two_resource,
['test1'], {'fail': True})
template['heat_template_version'] = '2015-10-15'
template['resources']['test2']['properties']['value'] = {
'list_join': [',', ['a'], ['b']]}
self.update_stack(stack_identifier,
template=template,
expected_status='UPDATE_FAILED')
template = _change_rsrc_properties(template,
['test2'], {'value': 'Test2'})
self.update_stack(stack_identifier,
template=template,
expected_status='UPDATE_FAILED')
self._stack_delete(stack_identifier)
def test_stack_update_with_old_version(self):
"""Update handles old template version in failure.
If a stack update fails while changing the template version, update is
able to handle the old version fine.
"""
template = _change_rsrc_properties(
test_template_one_resource,
['test1'], {'value': {'list_join': [',', ['a'], ['b']]}})
template['heat_template_version'] = '2015-10-15'
stack_identifier = self.stack_create(
template=template)
# Update with a new function and make the update fails
template = _change_rsrc_properties(test_template_one_resource,
['test1'], {'fail': True})
self.update_stack(stack_identifier,
template=template,
expected_status='UPDATE_FAILED')
self._stack_delete(stack_identifier)