From 6e8534bef01cc068f02adc061c1f8a478402d522 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 22 Jun 2017 12:18:03 -0400 Subject: [PATCH] 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 (cherry picked from commit ba0b570054f89c72d261e2e2d0aedd55c4fe2344) --- heat/engine/function.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/heat/engine/function.py b/heat/engine/function.py index aa3d7d4b51..46c3edfa11 100644 --- a/heat/engine/function.py +++ b/heat/engine/function.py @@ -182,6 +182,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)