Implement list_concat function
This function uses python's extend function for lists in order to concatenate lists. So, given the input: [['v1', 'v2'], ['v3', 'v4']] the result would be ['v1', 'v2', 'v3', 'v4']. This comes as an alternative to using yaql's concat. Change-Id: I082833e73388540b29f71b78293fd36fe04b7b92
This commit is contained in:
parent
7dacf57a9a
commit
98faf03be4
@ -304,6 +304,7 @@ for the ``heat_template_version`` key:
|
|||||||
get_resource
|
get_resource
|
||||||
list_join
|
list_join
|
||||||
make_url
|
make_url
|
||||||
|
list_concat
|
||||||
map_merge
|
map_merge
|
||||||
map_replace
|
map_replace
|
||||||
repeat
|
repeat
|
||||||
@ -1893,3 +1894,28 @@ For example
|
|||||||
``server_url`` will be evaluated to a URL in the form::
|
``server_url`` will be evaluated to a URL in the form::
|
||||||
|
|
||||||
http://[<server IP>]:8080/hello?recipient=world#greeting
|
http://[<server IP>]:8080/hello?recipient=world#greeting
|
||||||
|
|
||||||
|
list_concat
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The ``list_concat`` function concatenates lists together.
|
||||||
|
|
||||||
|
The syntax of the ``list_concat`` function is
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
list_concat:
|
||||||
|
- <list #1>
|
||||||
|
- <list #2>
|
||||||
|
- ...
|
||||||
|
|
||||||
|
|
||||||
|
For example
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
list_concat: [['v1', 'v2'], ['v3', 'v4']]
|
||||||
|
|
||||||
|
Will resolve to the list ``['v1', 'v2', 'v3', 'v4']``.
|
||||||
|
|
||||||
|
Null values will be ignored.
|
||||||
|
@ -1436,3 +1436,47 @@ class MakeURL(function.Function):
|
|||||||
|
|
||||||
return urlparse.urlunsplit((scheme, ''.join(netloc()),
|
return urlparse.urlunsplit((scheme, ''.join(netloc()),
|
||||||
path, query, fragment))
|
path, query, fragment))
|
||||||
|
|
||||||
|
|
||||||
|
class ListConcat(function.Function):
|
||||||
|
"""A function for extending lists.
|
||||||
|
|
||||||
|
Takes the form::
|
||||||
|
|
||||||
|
list_concat:
|
||||||
|
- [<value 1>, <value 2>]
|
||||||
|
- [<value 3>, <value 4>]
|
||||||
|
|
||||||
|
And resolves to::
|
||||||
|
|
||||||
|
[<value 1>, <value 2>, <value 3>, <value 4>]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, stack, fn_name, args):
|
||||||
|
super(ListConcat, self).__init__(stack, fn_name, args)
|
||||||
|
example = (_('"%s" : [ [ <value 1>, <value 2> ], '
|
||||||
|
'[ <value 3>, <value 4> ] ]')
|
||||||
|
% fn_name)
|
||||||
|
self.fmt_data = {'fn_name': fn_name, 'example': example}
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
args = function.resolve(self.args)
|
||||||
|
|
||||||
|
if not isinstance(args, collections.Sequence):
|
||||||
|
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
|
||||||
|
'should be: %(example)s') % self.fmt_data)
|
||||||
|
|
||||||
|
def ensure_list(m):
|
||||||
|
if m is None:
|
||||||
|
return []
|
||||||
|
elif isinstance(m, collections.Sequence):
|
||||||
|
return m
|
||||||
|
else:
|
||||||
|
msg = _('Incorrect arguments: Items to concat must be lists.')
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
|
ret_list = []
|
||||||
|
for m in args:
|
||||||
|
ret_list.extend(ensure_list(m))
|
||||||
|
return ret_list
|
||||||
|
@ -590,6 +590,7 @@ class HOTemplate20170901(HOTemplate20170224):
|
|||||||
|
|
||||||
# functions added in 2017-09-01
|
# functions added in 2017-09-01
|
||||||
'make_url': hot_funcs.MakeURL,
|
'make_url': hot_funcs.MakeURL,
|
||||||
|
'list_concat': hot_funcs.ListConcat,
|
||||||
|
|
||||||
# functions removed from 2015-10-15
|
# functions removed from 2015-10-15
|
||||||
'Fn::Select': hot_funcs.Removed,
|
'Fn::Select': hot_funcs.Removed,
|
||||||
|
@ -2060,6 +2060,26 @@ conditions:
|
|||||||
stack.validate()
|
stack.validate()
|
||||||
self.assertEqual({'one', 'three'}, set(stack.resources))
|
self.assertEqual({'one', 'three'}, set(stack.resources))
|
||||||
|
|
||||||
|
def test_list_concat(self):
|
||||||
|
snippet = {'list_concat': [['v1', 'v2'], ['v3', 'v4']]}
|
||||||
|
snippet_resolved = ['v1', 'v2', 'v3', 'v4']
|
||||||
|
tmpl = template.Template(hot_pike_tpl_empty)
|
||||||
|
resolved = self.resolve(snippet, tmpl)
|
||||||
|
self.assertEqual(snippet_resolved, resolved)
|
||||||
|
|
||||||
|
def test_list_concat_none(self):
|
||||||
|
snippet = {'list_concat': [['v1', 'v2'], ['v3', 'v4'], None]}
|
||||||
|
snippet_resolved = ['v1', 'v2', 'v3', 'v4']
|
||||||
|
tmpl = template.Template(hot_pike_tpl_empty)
|
||||||
|
resolved = self.resolve(snippet, tmpl)
|
||||||
|
self.assertEqual(snippet_resolved, resolved)
|
||||||
|
|
||||||
|
def test_list_concat_invalid(self):
|
||||||
|
snippet = {'list_concat': [{'k1': 'v2'}, ['v3', 'v4']]}
|
||||||
|
tmpl = template.Template(hot_pike_tpl_empty)
|
||||||
|
exc = self.assertRaises(TypeError, self.resolve, snippet, tmpl)
|
||||||
|
self.assertIn('Incorrect arguments', six.text_type(exc))
|
||||||
|
|
||||||
|
|
||||||
class HotStackTest(common.HeatTestCase):
|
class HotStackTest(common.HeatTestCase):
|
||||||
"""Test stack function when stack was created from HOT template."""
|
"""Test stack function when stack was created from HOT template."""
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- The list_concat function was added, which concats several lists using
|
||||||
|
python's extend function.
|
Loading…
Reference in New Issue
Block a user