From b10898a7a277cf4ca107c5641f6fde88f5ae5636 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 27 Nov 2012 13:50:20 +1300 Subject: [PATCH] For Fn::Join join strings in resolve_static_data 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 | 3 ++- heat/engine/template.py | 31 +++++++++++++++++++++++++++++++ heat/tests/test_parser.py | 24 +++++++++++++++++++----- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/heat/engine/parser.py b/heat/engine/parser.py index d3395240..bd01015d 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -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): diff --git a/heat/engine/template.py b/heat/engine/template.py index 63924f70..301add30 100644 --- a/heat/engine/template.py +++ b/heat/engine/template.py @@ -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): ''' diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index e6d9b8f0..e3c31a24 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -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") -- 2.45.2