Merge "Stop using notCompute in favor of controller"
[apex-tripleo-heat-templates.git] / tripleo_heat_merge / merge.py
index dd254ab..4571d28 100644 (file)
@@ -4,6 +4,27 @@ import yaml
 import argparse
 
 
+def apply_maps(template):
+    """Apply Merge::Map within template.
+
+    Any dict {'Merge::Map': {'Foo': 'Bar', 'Baz': 'Quux'}}
+    will resolve to ['Bar', 'Quux'] - that is a dict with key
+    'Merge::Map' is replaced entirely by that dict['Merge::Map'].values().
+    """
+    if isinstance(template, dict):
+        if 'Merge::Map' in template:
+            return sorted(
+                apply_maps(value) for value in template['Merge::Map'].values()
+                )
+        else:
+            return dict((key, apply_maps(value))
+                for key, value in template.items())
+    elif isinstance(template, list):
+        return [apply_maps(item) for item in template]
+    else:
+        return template
+
+
 def apply_scaling(template, scaling, in_copies=None):
     """Apply a set of scaling operations to template.
 
@@ -12,9 +33,12 @@ def apply_scaling(template, scaling, in_copies=None):
 
     Values are handled via scale_value.
 
-    Keys in dicts are always copied per the scaling rule.
+    Keys in dicts are copied per the scaling rule.
     Values are either replaced or copied depending on whether the given
     scaling rule is in in_copies.
+
+    in_copies is reset to None when a dict {'Merge::Map': someobject} is
+    encountered.
     """
     in_copies = dict(in_copies or {})
     # Shouldn't be needed but to avoid unexpected side effects/bugs we short
@@ -22,6 +46,8 @@ def apply_scaling(template, scaling, in_copies=None):
     if not scaling:
         return template
     if isinstance(template, dict):
+        if 'Merge::Map' in template:
+            in_copies = None
         new_template = {}
         for key, value in template.items():
             for prefix, copy_num, new_key in scale_value(
@@ -301,6 +327,7 @@ def merge(templates, master_role=None, slave_roles=None,
                 end_template['Resources'][r] = rbody
 
     end_template = apply_scaling(end_template, scaling)
+    end_template = apply_maps(end_template)
 
     def fix_ref(item, old, new):
         if isinstance(item, dict):