Generate placeholders for resource proxies before validation
Before validating resources, generate placeholder NodeData for them in the StackDefinition. 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 the long term, this should help us to remove the state-checking logic from the intrinsic functions. In the short term, this allows 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: I154ff0cd019d279379886fccbd708cf0d39ce53f
This commit is contained in:
parent
666930d195
commit
f94d76cb32
|
@ -871,10 +871,17 @@ class Resource(status.ResourceStatus):
|
|||
def get_attrs(attrs):
|
||||
for attr in attrs:
|
||||
path = (attr,) if isinstance(attr, six.string_types) else attr
|
||||
try:
|
||||
yield attr, self.get_attribute(*path)
|
||||
except exception.InvalidTemplateAttribute as ita:
|
||||
LOG.info('%s', ita)
|
||||
if self.action == self.INIT:
|
||||
if (type(self).get_attribute != Resource.get_attribute or
|
||||
type(self).FnGetAtt != Resource.FnGetAtt or
|
||||
path[0] in self.attributes):
|
||||
# TODO(ricolin) make better placeholder values here
|
||||
yield path, None
|
||||
else:
|
||||
try:
|
||||
yield attr, self.get_attribute(*path)
|
||||
except exception.InvalidTemplateAttribute as ita:
|
||||
LOG.info('%s', ita)
|
||||
|
||||
dep_attrs = set(self.stack.get_dep_attrs(
|
||||
six.itervalues(self.stack.resources),
|
||||
|
|
|
@ -839,10 +839,11 @@ class Stack(collections.Mapping):
|
|||
raise exception.StackValidationFailed(
|
||||
message=_("Duplicate names %s") % dup_names)
|
||||
|
||||
if validate_by_deps:
|
||||
iter_rsc = self.dependencies
|
||||
else:
|
||||
iter_rsc = six.itervalues(resources)
|
||||
iter_rsc = (self.dependencies if validate_by_deps
|
||||
else six.itervalues(resources))
|
||||
|
||||
for name, res in six.iteritems(resources):
|
||||
stk_defn.update_resource_data(self.defn, name, res.node_data())
|
||||
|
||||
unique_defns = set(res.t for res in six.itervalues(resources))
|
||||
unique_defn_names = set(defn.name for defn in unique_defns)
|
||||
|
|
|
@ -604,6 +604,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,
|
||||
|
@ -618,6 +619,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',
|
||||
|
|
Loading…
Reference in New Issue