Don't re-bind parameters during stack update

While we're in the process of updating a stack, we set the stack's parameters
to the new, updated values. However, we don't want to change existing
resources' idea of their own values until we have explicitly done an update of
them to bring them into line with the new template/parameters. So when parsing
a template snippet, store the parameters object to which it will refer.
References will resolve to the new parameters only when the template has been
re-resolved.

Closes-bug: #1291411

Change-Id: Iebbb518c5d15cfba858db001648f3412a7d8b1c0
This commit is contained in:
Zane Bitter 2014-03-19 20:56:43 -04:00
parent 96f427b592
commit a674ac35d1
4 changed files with 106 additions and 2 deletions

View File

@ -75,11 +75,16 @@ class ParamRef(function.Function):
{ "Ref" : "<param_name>" }
'''
def __init__(self, stack, fn_name, args):
super(ParamRef, self).__init__(stack, fn_name, args)
self.parameters = self.stack.parameters
def result(self):
param_name = function.resolve(self.args)
try:
return self.stack.parameters[param_name]
return self.parameters[param_name]
except (KeyError, ValueError):
raise exception.UserParameterMissing(key=param_name)

View File

@ -35,6 +35,11 @@ class GetParam(function.Function):
- ...
'''
def __init__(self, stack, fn_name, args):
super(GetParam, self).__init__(stack, fn_name, args)
self.parameters = self.stack.parameters
def result(self):
args = function.resolve(self.args)
@ -57,7 +62,7 @@ class GetParam(function.Function):
self.fn_name)
try:
parameter = self.stack.parameters[param_name]
parameter = self.parameters[param_name]
except KeyError:
raise exception.UserParameterMissing(key=param_name)

View File

@ -642,6 +642,53 @@ class StackTest(test_parser.StackTest):
self.assertEqual(newstack.parameters['OS::stack_id'],
stack_identifier.stack_id)
@utils.stack_delete_after
def test_update_modify_param_ok_replace(self):
tmpl = {
'heat_template_version': '2013-05-23',
'parameters': {
'foo': {'type': 'string'}
},
'resources': {
'AResource': {
'type': 'ResourceWithPropsType',
'properties': {'Foo': {'get_param': 'foo'}}
}
}
}
self.m.StubOutWithMock(generic_rsrc.ResourceWithProps,
'update_template_diff')
self.stack = parser.Stack(self.ctx, 'update_test_stack',
template.Template(tmpl),
environment.Environment({'foo': 'abc'}))
self.stack.store()
self.stack.create()
self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
self.stack.state)
updated_stack = parser.Stack(self.ctx, 'updated_stack',
template.Template(tmpl),
environment.Environment({'foo': 'xyz'}))
def check_props(*args):
self.assertEqual('abc', self.stack['AResource'].properties['Foo'])
generic_rsrc.ResourceWithProps.update_template_diff(
{'Type': 'ResourceWithPropsType',
'Properties': {'Foo': 'xyz'}},
{'Type': 'ResourceWithPropsType',
'Properties': {'Foo': 'abc'}}).WithSideEffects(check_props) \
.AndRaise(resource.UpdateReplace)
self.m.ReplayAll()
self.stack.update(updated_stack)
self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE),
self.stack.state)
self.assertEqual('xyz', self.stack['AResource'].properties['Foo'])
self.m.VerifyAll()
class StackAttributesTest(HeatTestCase):
"""

View File

@ -1638,6 +1638,53 @@ class StackTest(HeatTestCase):
self.assertEqual('xyz', self.stack['AResource'].properties['Foo'])
self.m.VerifyAll()
@utils.stack_delete_after
def test_update_modify_param_ok_replace(self):
tmpl = {
'HeatTemplateFormatVersion': '2012-12-12',
'Parameters': {
'foo': {'Type': 'String'}
},
'Resources': {
'AResource': {
'Type': 'ResourceWithPropsType',
'Properties': {'Foo': {'Ref': 'foo'}}
}
}
}
self.m.StubOutWithMock(generic_rsrc.ResourceWithProps,
'update_template_diff')
self.stack = parser.Stack(self.ctx, 'update_test_stack',
template.Template(tmpl),
environment.Environment({'foo': 'abc'}))
self.stack.store()
self.stack.create()
self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
self.stack.state)
updated_stack = parser.Stack(self.ctx, 'updated_stack',
template.Template(tmpl),
environment.Environment({'foo': 'xyz'}))
def check_props(*args):
self.assertEqual('abc', self.stack['AResource'].properties['Foo'])
generic_rsrc.ResourceWithProps.update_template_diff(
{'Type': 'ResourceWithPropsType',
'Properties': {'Foo': 'xyz'}},
{'Type': 'ResourceWithPropsType',
'Properties': {'Foo': 'abc'}}).WithSideEffects(check_props) \
.AndRaise(resource.UpdateReplace)
self.m.ReplayAll()
self.stack.update(updated_stack)
self.assertEqual((parser.Stack.UPDATE, parser.Stack.COMPLETE),
self.stack.state)
self.assertEqual('xyz', self.stack['AResource'].properties['Foo'])
self.m.VerifyAll()
@utils.stack_delete_after
def test_update_modify_update_failed(self):
tmpl = {'Resources': {'AResource': {'Type': 'ResourceWithPropsType',