From 652af4bde3a2cf4251a2546b9960a118f637858c Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Wed, 19 Jul 2017 17:35:39 -0400 Subject: [PATCH] Use placeholder data for resources prior to creation When requesting the NodeData for a Resource, generate placeholder values if the resource has not been created yet. Currently, all attributes are given a value of None (consistent with how the get_attr intrinsic functions substitute them when the resource state indicates that the attributes are not valid now). Reference IDs are generated as usual (since the logic for what to return when the state indicates the data are not valid is contained in the resource plugins). In future, this will allow us to add placeholder NodeData for all resources to the StackDefinition prior to validation. In the long term, that should help us to remove the state-checking logic from the intrinsic functions. In the short term, it will allow us to validate template data that is parsed against the StackDefinition (rather than the Stack), since it gives us a list of valid attribute names. In the medium term, this should give us a place to substitute in more sophisticated placeholder values to do better validation. Change-Id: Ife69f563a3748c6cb611ca02f826229e76bee4d0 Partially-Implements: blueprint stack-definition --- heat/engine/resource.py | 15 +++++++++++---- heat/tests/engine/test_check_resource.py | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index cf6ede1672..6abc6b0fab 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -993,10 +993,17 @@ class Resource(status.ResourceStatus): (self.attributes.get_cache_mode(path[0]) == attributes.Schema.CACHE_NONE)): continue - try: - yield attr, self._get_attribute_caching(*path) - except exception.InvalidTemplateAttribute as ita: - LOG.info('%s', ita) + if self.action == self.INIT: + if (path[0] in self.attributes or + (type(self).get_attribute != Resource.get_attribute or + type(self).FnGetAtt != Resource.FnGetAtt)): + # TODO(ricolin) make better placeholder values here + yield attr, None + else: + try: + yield attr, self._get_attribute_caching(*path) + except exception.InvalidTemplateAttribute as ita: + LOG.info('%s', ita) dep_attrs = self.referenced_attrs(in_outputs=False) diff --git a/heat/tests/engine/test_check_resource.py b/heat/tests/engine/test_check_resource.py index efdd44cf0f..c2597ff453 100644 --- a/heat/tests/engine/test_check_resource.py +++ b/heat/tests/engine/test_check_resource.py @@ -606,6 +606,7 @@ class MiscMethodsTest(common.HeatTestCase): self.resource = self.stack['A'] def test_node_data_ok(self): + self.resource.action = self.resource.CREATE expected_input_data = {'attrs': {(u'flat_dict', u'key2'): 'val2', (u'flat_dict', u'key3'): 'val3', (u'nested_dict', u'dict', u'a'): 1, @@ -620,6 +621,7 @@ class MiscMethodsTest(common.HeatTestCase): self.assertEqual(expected_input_data, actual_input_data.as_dict()) def test_node_data_exception(self): + self.resource.action = self.resource.CREATE expected_input_data = {'attrs': {}, 'id': mock.ANY, 'reference_id': 'A',