Allow multiple lists for list_join intrinsic functions

Allow the HOT list_join function to optionally accept multiple
lists.  This is useful when you want to combine two or more lists,
for example to join a hard-coded list with a user provided one.

Although this is 100% backwards compatible, it's been added as a new
function which is available only via the Liberty HOT version.  This
should allow easier determination of whether a particular heat service
supports this revised syntax.

Change-Id: I375450960c6d486998308ec0b915c25628f745a5
This commit is contained in:
Steven Hardy 2015-06-23 15:40:16 +01:00
parent 90d74a1e55
commit 25a27d4fe7
3 changed files with 78 additions and 1 deletions

View File

@ -236,9 +236,51 @@ class Join(cfn_funcs.Join):
And resolves to::
"<string_1><delim><string_2><delim>..."
'''
class JoinMultiple(cfn_funcs.Join):
'''
A function for joining strings.
Takes the form::
{ "list_join" : [ "<delim>", [ "<string_1>", "<string_2>", ... ] ] }
And resolves to::
"<string_1><delim><string_2><delim>..."
Optionally multiple lists may be specified, which will also be joined.
'''
def __init__(self, stack, fn_name, args):
example = '"%s" : [ " ", [ "str1", "str2"] ...]' % fn_name
fmt_data = {'fn_name': fn_name,
'example': example}
if isinstance(args, (six.string_types, collections.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
try:
delim = args.pop(0)
joinlist = args.pop(0)
except IndexError:
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
# Optionally allow additional lists, which are appended
for l in args:
try:
joinlist += l
except (AttributeError, TypeError):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
super(JoinMultiple, self).__init__(stack, fn_name,
args=[delim, joinlist])
class ResourceFacade(cfn_funcs.ResourceFacade):
'''
A function for obtaining data from the facade resource from within the

View File

@ -334,7 +334,7 @@ class HOTemplate20151015(HOTemplate20150430):
'get_file': hot_funcs.GetFile,
'get_param': hot_funcs.GetParam,
'get_resource': cfn_funcs.ResourceRef,
'list_join': hot_funcs.Join,
'list_join': hot_funcs.JoinMultiple,
'repeat': hot_funcs.Repeat,
'resource_facade': hot_funcs.ResourceFacade,
'str_replace': hot_funcs.Replace,

View File

@ -49,6 +49,10 @@ hot_kilo_tpl_empty = template_format.parse('''
heat_template_version: 2015-04-30
''')
hot_liberty_tpl_empty = template_format.parse('''
heat_template_version: 2015-10-15
''')
hot_tpl_empty_sections = template_format.parse('''
heat_template_version: 2013-05-23
parameters:
@ -591,6 +595,37 @@ class HOTemplateTest(common.HeatTestCase):
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl, stack))
def test_list_join(self):
snippet = {'list_join': [',', ['bar', 'baz']]}
snippet_resolved = 'bar,baz'
tmpl = template.Template(hot_kilo_tpl_empty)
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
def test_join_multiple(self):
snippet = {'list_join': [',', ['bar', 'baz'], ['bar2', 'baz2']]}
snippet_resolved = 'bar,baz,bar2,baz2'
tmpl = template.Template(hot_liberty_tpl_empty)
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
def test_join_invalid(self):
snippet = {'list_join': 'bad'}
tmpl = template.Template(hot_liberty_tpl_empty)
exc = self.assertRaises(TypeError, self.resolve, snippet, tmpl)
self.assertIn('Incorrect arguments', six.text_type(exc))
def test_join_invalid_value(self):
snippet = {'list_join': [',']}
tmpl = template.Template(hot_liberty_tpl_empty)
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
self.assertIn('Incorrect arguments', six.text_type(exc))
def test_join_invalid_multiple(self):
snippet = {'list_join': [',', 'bad', ['foo']]}
tmpl = template.Template(hot_liberty_tpl_empty)
exc = self.assertRaises(TypeError, self.resolve, snippet, tmpl)
self.assertIn('Incorrect arguments', six.text_type(exc))
def test_repeat(self):
"""Test repeat function."""
snippet = {'repeat': {'template': 'this is %var%',