Resolve Macros when copying templates

During stack updates in the legacy path, we copy resource definitions
back and forth between templates. In the case where the definitions
contain macros (which in practice means the If macro for conditionals),
they may rely on external state (in practice, the conditional
definitions) that is not available in the template they're being copied
into (e.g. in the case of an If macro referencing a new condition).

This change means that when we copy a template, the macros get resolved
so that only the chosen path of the If macro is represented.

This resolves the issue where trying to signal a resource during an
update fails when one of the already-updated resources in the template
contains an If macro that refers to a condition definition that is
newly-added in the new template.

Change-Id: I6d08507f43b0fcc4c0b5e848e97fa26033d839b2
Closes-Bug: #1699463
This commit is contained in:
Zane Bitter 2017-06-22 12:18:03 -04:00
parent a5ac2c3b1d
commit ba0b570054
1 changed files with 14 additions and 0 deletions

View File

@ -188,6 +188,20 @@ class Macro(Function):
"""
return dep_attrs(self.parsed, resource_name)
def __reduce__(self):
"""Return a representation of the macro result suitable for pickling.
This allows the copy module (which works by pickling and then
unpickling objects) to copy a template. Functions in the copy will
return to their original (JSON) form (i.e. a single-element map).
Unlike other functions, macros are *not* preserved during a copy. The
the processed (but unparsed) output is returned in their place.
"""
if isinstance(self.parsed, Function):
return self.parsed.__reduce__()
return type(self.parsed), (self.parsed,)
def _repr_result(self):
return repr(self.parsed)