diff --git a/doc/source/template_guide/hot_spec.rst b/doc/source/template_guide/hot_spec.rst index c5548282b3..118c624647 100644 --- a/doc/source/template_guide/hot_spec.rst +++ b/doc/source/template_guide/hot_spec.rst @@ -295,8 +295,10 @@ for the ``heat_template_version`` key: document is a HOT template and it may contain features added and/or removed up until the Pike release. This version adds the ``make_url`` function for assembling URLs, the ``list_concat`` function for combining multiple - lists, and ``string_replace_vstrict`` which raises errors for - missing and empty params. The complete list of supported functions is:: + lists, the ``list_concat_unique`` function for combining multiple + lists without repeating items, and the``string_replace_vstrict`` which + raises errors for missing and empty params. The complete list of + supported functions is:: digest filter @@ -307,6 +309,7 @@ for the ``heat_template_version`` key: list_join make_url list_concat + list_concat_unique map_merge map_replace repeat @@ -1931,3 +1934,17 @@ For example Will resolve to the list ``['v1', 'v2', 'v3', 'v4']``. Null values will be ignored. + +list_concat_unique +------------------ + +The ``list_concat_unique`` function behaves identically to the function +``list_concat``, only removes the repeating items of lists. + +For example + +.. code-block:: yaml + + list_concat_unique: [['v1', 'v2'], ['v2', 'v43']] + +Will resolve to the list ``['v1', 'v2', 'v3']``. diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py index bc9d1c431e..e4d35d8672 100644 --- a/heat/engine/hot/functions.py +++ b/heat/engine/hot/functions.py @@ -1480,6 +1480,8 @@ class ListConcat(function.Function): """ + _unique = False + def __init__(self, stack, fn_name, args): super(ListConcat, self).__init__(stack, fn_name, args) example = (_('"%s" : [ [ , ], ' @@ -1508,4 +1510,20 @@ class ListConcat(function.Function): ret_list = [] for m in args: ret_list.extend(ensure_list(m)) + + if self._unique: + for i in ret_list: + while ret_list.count(i) > 1: + del ret_list[ret_list.index(i)] + return ret_list + + +class ListConcatUnique(ListConcat): + """A function for extending lists with unique items. + + list_concat_unique is identical to the list_concat function, only + contains unique items in retuning list. + """ + + _unique = True diff --git a/heat/engine/hot/template.py b/heat/engine/hot/template.py index 2d939c3f77..04032913c7 100644 --- a/heat/engine/hot/template.py +++ b/heat/engine/hot/template.py @@ -592,6 +592,7 @@ class HOTemplate20170901(HOTemplate20170224): 'make_url': hot_funcs.MakeURL, 'list_concat': hot_funcs.ListConcat, 'str_replace_vstrict': hot_funcs.ReplaceJsonVeryStrict, + 'list_concat_unique': hot_funcs.ListConcatUnique, # functions removed from 2015-10-15 'Fn::Select': hot_funcs.Removed, diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index 547cd7cb9a..4ed7906580 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -2125,6 +2125,34 @@ conditions: resolved = self.resolve(snippet, tmpl) self.assertEqual(snippet_resolved, resolved) + def test_list_concat_repeat_dict_item(self): + snippet = {'list_concat': [[{'v1': 'v2'}], [{'v1': 'v2'}]]} + snippet_resolved = [{'v1': 'v2'}, {'v1': 'v2'}] + tmpl = template.Template(hot_pike_tpl_empty) + resolved = self.resolve(snippet, tmpl) + self.assertEqual(snippet_resolved, resolved) + + def test_list_concat_repeat_item(self): + snippet = {'list_concat': [['v1', 'v2'], ['v2', 'v3']]} + snippet_resolved = ['v1', 'v2', 'v2', 'v3'] + tmpl = template.Template(hot_pike_tpl_empty) + resolved = self.resolve(snippet, tmpl) + self.assertEqual(snippet_resolved, resolved) + + def test_list_concat_unique_dict_item(self): + snippet = {'list_concat_unique': [[{'v1': 'v2'}], [{'v1': 'v2'}]]} + snippet_resolved = [{'v1': 'v2'}] + tmpl = template.Template(hot_pike_tpl_empty) + resolved = self.resolve(snippet, tmpl) + self.assertEqual(snippet_resolved, resolved) + + def test_list_concat_unique(self): + snippet = {'list_concat_unique': [['v1', 'v2'], ['v2', 'v3']]} + snippet_resolved = ['v1', 'v2', 'v3'] + tmpl = template.Template(hot_pike_tpl_empty) + resolved = self.resolve(snippet, tmpl) + self.assertEqual(snippet_resolved, resolved) + def _test_list_concat_invalid(self, snippet): tmpl = template.Template(hot_pike_tpl_empty) msg = 'Incorrect arguments' diff --git a/releasenotes/notes/add-list-concat-unique-function-5a87130d9c93cb08.yaml b/releasenotes/notes/add-list-concat-unique-function-5a87130d9c93cb08.yaml new file mode 100644 index 0000000000..3430d83066 --- /dev/null +++ b/releasenotes/notes/add-list-concat-unique-function-5a87130d9c93cb08.yaml @@ -0,0 +1,5 @@ +--- +features: + - The list_concat_unique function was added, which behaves identically + to the function ``list_concat`` to concat several lists using + python's extend function and make sure without repeating items.