Use a sentinel to indicate when all attributes are required

To generate its NodeData, a Resource must know which of its attributes
other parts of the template have dependencies on, which it determines by
asking the intrinsic functions in the template. Currently, the get_attr
function when used with no arguments depends on all of the attributes of
the resource (except 'show'), and it obtains this list from the Resource
itself (via the attributes_schema). This presents a chicken-and-egg problem
if we want to give Functions access only to a ResourceProxy based on the
NodeData.

Resolve this by returning a constant sentinel value (indicating that all
attributes are required) to the Resource, which can determine for itself
what attributes it has.

Change-Id: If209b589278fe1facb06e157fe76209fdd42a8a2
Partially-Implements: blueprint stack-definition
This commit is contained in:
Zane Bitter 2017-02-17 13:33:06 -05:00
parent 2cf7af7deb
commit 06afc2f3b0
4 changed files with 20 additions and 4 deletions

View File

@ -135,6 +135,10 @@ def _stack_id_output(resource_name, template_type='cfn'):
BASE_ATTRIBUTES = (SHOW_ATTR, ) = ('show', )
# Returned by function.dep_attrs() to indicate that all attributes are
# referenced
ALL_ATTRIBUTES = '*'
@repr_wrapper
class Attributes(collections.Mapping):
@ -146,6 +150,9 @@ class Attributes(collections.Mapping):
self._attributes = Attributes._make_attributes(schema)
self.reset_resolved_values()
assert ALL_ATTRIBUTES not in schema, \
"Invalid attribute name '%s'" % ALL_ATTRIBUTES
def reset_resolved_values(self):
self._resolved_values = {}

View File

@ -73,6 +73,9 @@ class Function(object):
Return an iterator over any attributes of the specified resource that
this function references.
The special value heat.engine.attributes.ALL_ATTRIBUTES may be used to
indicate that all attributes of the resource are required.
"""
return dep_attrs(self.args, resource_name)
@ -179,6 +182,9 @@ class Macro(Function):
Return an iterator over any attributes of the specified resource that
this function references.
The special value heat.engine.attributes.ALL_ATTRIBUTES may be used to
indicate that all attributes of the resource are required.
"""
return dep_attrs(self.parsed, resource_name)

View File

@ -315,8 +315,7 @@ class GetAttAllAttributes(GetAtt):
if self._attribute is not None:
return super(GetAttAllAttributes, self).dep_attrs(resource_name)
elif self._res_name() == resource_name:
res = self._resource()
attrs = six.iterkeys(res.attributes_schema)
attrs = [attributes.ALL_ATTRIBUTES]
else:
attrs = []
return itertools.chain(function.dep_attrs(self.args,

View File

@ -872,9 +872,13 @@ class Resource(status.ResourceStatus):
except exception.InvalidTemplateAttribute as ita:
LOG.info('%s', ita)
dep_attrs = self.stack.get_dep_attrs(
dep_attrs = set(self.stack.get_dep_attrs(
six.itervalues(self.stack.resources),
self.name)
self.name))
if attributes.ALL_ATTRIBUTES in dep_attrs:
dep_attrs.remove(attributes.ALL_ATTRIBUTES)
dep_attrs |= (set(self.attributes) - {self.SHOW})
return node_data.NodeData(self.id, self.name, self.uuid,
self.get_reference_id(),
dict(get_attrs(dep_attrs)),