Always update nested stacks

There's no reason to not issue an update to a nested stack, so don't bother
trying to decide if its inputs have changed (and especially don't replace
it because it's in a failed state). Overriding _needs_update() also allows
us to remove what was effectively an isinstance check from the previous
handling of failed states.

Change-Id: Ia48ebfcb6c1b3a904f01a83f8f34d8c7a13bb2be
Related-Bug: #1383618
This commit is contained in:
Zane Bitter 2014-12-12 15:20:24 -05:00
parent e1540f834c
commit 35ac781db3
6 changed files with 22 additions and 20 deletions

View File

@ -660,10 +660,7 @@ class Resource(object):
def _needs_update(self, after, before, after_props, before_props,
prev_resource):
if self.status == self.FAILED:
if hasattr(self, 'nested'):
return True
else:
raise UpdateReplace(self)
raise UpdateReplace(self)
if prev_resource is not None:
cur_class_def, cur_ver = self.implementation_signature()

View File

@ -188,6 +188,12 @@ class RemoteStack(resource.Resource):
% self.name)
self.heat().stacks.suspend(stack_id=self.resource_id)
def _needs_update(self, after, before, after_props, before_props,
prev_resource):
# Always issue an update to the remote stack and let the individual
# resources in it decide if they need updating.
return True
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if self.resource_id and prop_diff:
snippet = json_snippet.get('Properties', {})

View File

@ -69,6 +69,12 @@ class StackResource(resource.Resource):
self.attributes_schema,
self._resolve_attribute)
def _needs_update(self, after, before, after_props, before_props,
prev_resource):
# Always issue an update to the nested stack and let the individual
# resources in it decide if they need updating.
return True
def nested(self, force_reload=False, show_deleted=False):
'''
Return a Stack object representing the nested (child) stack.

View File

@ -670,7 +670,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
num_updates_expected_on_updt=9,
num_creates_expected_on_updt=1,
num_deletes_expected_on_updt=1,
num_reloads_expected_on_updt=12,
num_reloads_expected_on_updt=13,
update_replace=True,
update_image_id=update_image)

View File

@ -973,7 +973,7 @@ Outputs:
Value: {'Fn::GetAtt': [NestedResource, value]}
'''
EXPECTED = (REPLACE, UPDATE, NOCHANGE) = ('replace', 'update', 'nochange')
EXPECTED = (UPDATE, NOCHANGE) = ('update', 'nochange')
scenarios = [
('no_changes', dict(template=main_template,
provider=initial_tmpl,
@ -986,10 +986,10 @@ Outputs:
expect=UPDATE)),
('provider_props_change', dict(template=main_template,
provider=prop_change_tmpl,
expect=REPLACE)),
expect=NOCHANGE)),
('provider_attr_change', dict(template=main_template,
provider=attr_change_tmpl,
expect=REPLACE)),
expect=NOCHANGE)),
]
def setUp(self):
@ -1015,19 +1015,12 @@ Outputs:
updated_stack = parser.Stack(self.ctx, stack.name, tmpl)
stack.update(updated_stack)
self.assertEqual(('UPDATE', 'COMPLETE'), stack.state)
if self.expect == self.REPLACE:
self.assertNotEqual(initial_id,
stack.output('identifier'))
self.assertNotEqual(initial_val,
stack.output('value'))
elif self.expect == self.NOCHANGE:
self.assertEqual(initial_id,
stack.output('identifier'))
self.assertEqual(initial_id,
stack.output('identifier'))
if self.expect == self.NOCHANGE:
self.assertEqual(initial_val,
stack.output('value'))
else:
self.assertEqual(initial_id,
stack.output('identifier'))
self.assertNotEqual(initial_val,
stack.output('value'))
self.m.VerifyAll()

View File

@ -440,8 +440,8 @@ class ResourceGroupTest(common.HeatTestCase):
new_snip = copy.deepcopy(resg.t)
scheduler.TaskRunner(resg.update, new_snip)()
self.stack = resg.nested()
self.assertEqual((resg.CREATE, resg.COMPLETE), resg.state)
self.assertEqual((resg.CREATE, resg.COMPLETE), resg.nested().state)
self.assertEqual((resg.UPDATE, resg.COMPLETE), resg.state)
self.assertEqual((resg.UPDATE, resg.COMPLETE), resg.nested().state)
self.assertEqual(2, len(resg.nested()))
resource_names = [r.name for r in resg.nested().iter_resources()]
self.assertEqual(['0', '1'], sorted(resource_names))