Convergence: Handle InvalidTemplateAttribute in worker

All attributes are retrieved (including ones referenced in the output).
In our functional test there is a bug where a nested stack did not
have an output that was referenced from the output. This didn't effect
the stack creation as:
- outputs are not normally required in the stack creation
- if the output is used by a TemplateResource it *may* be used

The way outputs are used currently is that they do not fail on
the first output that doesn't work as it is useful to get the ones
that do work. To help with this errors are placed alongside the
value (in a key "error_msg").

This is somewhat problematic in convergence as we now *require* all
attributes (including those based off of outputs).

Note: if you have an outer resource referencing a non-existent template
resource output it *will* fail, but when the outer stack's output references
the inner stack's output then it is not validated.

Change-Id: Id07c617a19eae56543f92ee21aea58cd38fa3606
This commit is contained in:
Angus Salkeld 2015-07-27 20:00:41 +10:00
parent 4b3b4ce14b
commit 375226ecff
2 changed files with 19 additions and 2 deletions

View File

@ -269,7 +269,13 @@ def construct_input_data(rsrc):
six.itervalues(rsrc.stack.resources),
rsrc.stack.outputs,
rsrc.name)
resolved_attributes = {attr: rsrc.FnGetAtt(attr) for attr in attributes}
resolved_attributes = {}
for attr in attributes:
try:
resolved_attributes[attr] = rsrc.FnGetAtt(attr)
except exception.InvalidTemplateAttribute as ita:
LOG.info(six.text_type(ita))
input_data = {'id': rsrc.id,
'name': rsrc.name,
'physical_resource_id': rsrc.resource_id,

View File

@ -442,7 +442,7 @@ class MiscMethodsTest(common.HeatTestCase):
self.stack.converge_stack(self.stack.t)
self.resource = self.stack['A']
def test_construct_input_data(self):
def test_construct_input_data_ok(self):
expected_input_data = {'attrs': {'value': None},
'id': mock.ANY,
'physical_resource_id': None,
@ -450,6 +450,17 @@ class MiscMethodsTest(common.HeatTestCase):
actual_input_data = worker.construct_input_data(self.resource)
self.assertEqual(expected_input_data, actual_input_data)
def test_construct_input_data_exception(self):
expected_input_data = {'attrs': {},
'id': mock.ANY,
'physical_resource_id': None,
'name': 'A'}
self.resource.FnGetAtt = mock.Mock(
side_effect=exception.InvalidTemplateAttribute(resource='A',
key='value'))
actual_input_data = worker.construct_input_data(self.resource)
self.assertEqual(expected_input_data, actual_input_data)
@mock.patch.object(sync_point, 'sync')
def test_check_stack_complete_root(self, mock_sync):
worker.check_stack_complete(