]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
For Fn::Join join strings in resolve_static_data
authorSteve Baker <sbaker@redhat.com>
Tue, 27 Nov 2012 00:50:20 +0000 (13:50 +1300)
committerSteve Baker <sbaker@redhat.com>
Tue, 27 Nov 2012 00:56:37 +0000 (13:56 +1300)
Fn::Join now has some preprocessing in resolve_static_data
where contiguous strings are joined into a single string.

This will allow equivalence tests to pass when comparing
JSON templates to hand-tidied YAML

Change-Id: I49fb2456388b3fd554ccec00920d7e84f6998183

heat/engine/parser.py
heat/engine/template.py
heat/tests/test_parser.py

index d339524071d9c6d6b5ce086d67d8df92c165a381..bd01015df165d4c4d80348aac03758ee6586ac5c 100644 (file)
@@ -439,7 +439,8 @@ def resolve_static_data(template, parameters, snippet):
                      [functools.partial(template.resolve_param_refs,
                                         parameters=parameters),
                       template.resolve_availability_zones,
-                      template.resolve_find_in_map])
+                      template.resolve_find_in_map,
+                      template.reduce_joins])
 
 
 def resolve_runtime_data(template, resources, snippet):
index 63924f70cb644ba4577f09dab878296add6c253d..301add30ed3162fa535d5ea5221232d6e5a8e447 100644 (file)
@@ -149,6 +149,37 @@ class Template(collections.Mapping):
 
         return _resolve(lambda k, v: k == 'Fn::GetAtt', handle_getatt, s)
 
+    @staticmethod
+    def reduce_joins(s):
+        '''
+        Reduces contiguous strings in Fn::Join to a single joined string
+        eg the following
+        { "Fn::Join" : [ " ", [ "str1", "str2", {"f": "b"}, "str3", "str4"]}
+        is reduced to
+        { "Fn::Join" : [ " ", [ "str1 str2", {"f": "b"}, "str3 str4"]}
+        '''
+        def handle_join(args):
+            if not isinstance(args, (list, tuple)):
+                raise TypeError('Arguments to "Fn::Join" must be a list')
+            delim, items = args
+            if not isinstance(items, (list, tuple)):
+                raise TypeError('Arguments to "Fn::Join" not fully resolved')
+            reduced = []
+            contiguous = []
+            for item in items:
+                if isinstance(item, (str, unicode)):
+                    contiguous.append(item)
+                else:
+                    if contiguous:
+                        reduced.append(delim.join(contiguous))
+                        contiguous = []
+                    reduced.append(item)
+            if contiguous:
+                reduced.append(delim.join(contiguous))
+            return {'Fn::Join': [delim, reduced]}
+
+        return _resolve(lambda k, v: k == 'Fn::Join', handle_join, s)
+
     @staticmethod
     def resolve_joins(s):
         '''
index e6d9b8f04054208587889de4e65c35da271f0b34..e3c31a24178ec293640ad91bd1235346ad3977e9 100644 (file)
@@ -18,6 +18,7 @@ import unittest
 from nose.plugins.attrib import attr
 import mox
 import json
+import sys
 
 from heat.common import context
 from heat.common import exception
@@ -29,11 +30,7 @@ from heat.engine.resources import Resource
 
 
 def join(raw):
-    def handle_join(args):
-        delim, strs = args
-        return delim.join(strs)
-
-    return template._resolve(lambda k, v: k == 'Fn::Join', handle_join, raw)
+    return parser.Template.resolve_joins(raw)
 
 
 @attr(tag=['unit', 'parser'])
@@ -210,6 +207,23 @@ class TemplateTest(unittest.TestCase):
                                                                resources),
                          p_snippet)
 
+    def test_join_reduce(self):
+        join = {"Fn::Join": [" ", ["foo", "bar", "baz", {'Ref': 'baz'},
+            "bink", "bonk"]]}
+        self.assertEqual(parser.Template.reduce_joins(join),
+            {"Fn::Join": [" ", ["foo bar baz", {'Ref': 'baz'},
+            "bink bonk"]]})
+
+        join = {"Fn::Join": [" ", ["foo", {'Ref': 'baz'},
+            "bink"]]}
+        self.assertEqual(parser.Template.reduce_joins(join),
+            {"Fn::Join": [" ", ["foo", {'Ref': 'baz'},
+            "bink"]]})
+
+        join = {"Fn::Join": [" ", [{'Ref': 'baz'}]]}
+        self.assertEqual(parser.Template.reduce_joins(join),
+            {"Fn::Join": [" ", [{'Ref': 'baz'}]]})
+
     def test_join(self):
         join = {"Fn::Join": [" ", ["foo", "bar"]]}
         self.assertEqual(parser.Template.resolve_joins(join), "foo bar")