From 910b5d141d87766497b8efd91cbace02b2788824 Mon Sep 17 00:00:00 2001 From: Sebastian Schmitt <147703765+sschmittsva@users.noreply.github.com> Date: Fri, 1 Dec 2023 09:37:51 +0100 Subject: [PATCH 1/4] Update combine.yml --- lib/ansible/plugins/filter/combine.yml | 77 ++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/lib/ansible/plugins/filter/combine.yml b/lib/ansible/plugins/filter/combine.yml index fe32a1f4b43..1a5ed51e7a8 100644 --- a/lib/ansible/plugins/filter/combine.yml +++ b/lib/ansible/plugins/filter/combine.yml @@ -1,13 +1,14 @@ DOCUMENTATION: name: combine version_added: "2.0" - short_description: combine two dictionaries + short_description: combine two or more dictionaries description: - Create a dictionary (hash/associative array) as a result of merging existing dictionaries. + - Dictionaries to the right (new) have precende over dictionaries to the left (old). positional: _input, _dicts options: _input: - description: First dictionary to combine. + description: First dictionary to combine or a list of dictionaries to combine. type: dict required: true _dicts: # TODO: this is really an *args so not list, but list ref @@ -33,15 +34,71 @@ DOCUMENTATION: EXAMPLES: | - # ab => {'a':1, 'b':3, 'c': 4} - ab: {{ {'a':1, 'b':2} | ansible.builtin.combine({'b':3, 'c':4}) }} + ab: + a: 1 + b: 2 - many: "{{ dict1 | ansible.builtin.combine(dict2, dict3, dict4) }}" - - # defaults => {'a':{'b':3, 'c':4}, 'd': 5} - # customization => {'a':{'c':20}} - # final => {'a':{'b':3, 'c':20}, 'd': 5} - final: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" + bc: + b: 3 + c: 4 + + cd: + c: 5 + d: 6 + + defaults: + a: + b: 3 + c: 4 + d: 5 + + customization: + a: + c: 20 + d: 30 + + foo_with_list: + a: [1, 20] + + bar_with_list: + a: [20] + + # { 'a': 1, 'b': 3, 'c': 4 } + combine_ab_bc: "{{ ab | ansible.builtin.combine(bc) }}" + + # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } + combine_ab_bc_cd: "{{ ab | ansible.builtin.combine(bc, cd) }}" + + # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } + list_combine_ab_bc_cd: "{{ [ab, bc, cd] | ansible.builtin.combine }}" + + # { 'a': { 'c': 20 }, 'd': 30 } + # :recursive=false: (which is the default) defaults' 'a' is replaced with customization's 'a' + defaults_with_customization: "{{ defaults | ansible.builtin.combine(customization) }}" + + # { 'a': { 'b': 3, 'c': 20 }, 'd': 30 } + # recursive=true: defaults' 'a' is updated with customization's 'a', i.e., 'b' is untouched and 'c' is updated from 4 to 20 + defaults_with_customization_recursive_true: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" + + # { 'a': [ 20 ] } + list_merge_replace: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='replace') }}" + + # { 'a': [ 1, 20 ] } + list_merge_keep: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='keep') }}" + + #{ 'a': [ 1, 20, 20 ] + list_merge_append: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='append') }}" + + # { 'a': [ 20, 1, 20 ] } + list_merge_prepend: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='prepend') }}" + + # { 'a': [ 1, 20 ] } + # note that there is only a single entry with value 20 + list_merge_append_rp: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='append_rp') }}" + + # { 'a': [ 20, 1 ] } + # note that there is only a single entry with value 20 + list_merge_prepend_rp: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='prepend_rp') }}" RETURN: _value: From a9cf7c890b6b90637fd58dcabdccb321b0a3f187 Mon Sep 17 00:00:00 2001 From: Sebastian Schmitt <147703765+sschmittsva@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:09:36 +0100 Subject: [PATCH 2/4] Fix typo --- lib/ansible/plugins/filter/combine.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ansible/plugins/filter/combine.yml b/lib/ansible/plugins/filter/combine.yml index 1a5ed51e7a8..33028ae8154 100644 --- a/lib/ansible/plugins/filter/combine.yml +++ b/lib/ansible/plugins/filter/combine.yml @@ -4,7 +4,7 @@ DOCUMENTATION: short_description: combine two or more dictionaries description: - Create a dictionary (hash/associative array) as a result of merging existing dictionaries. - - Dictionaries to the right (new) have precende over dictionaries to the left (old). + - Dictionaries to the right (new) have precedence over dictionaries to the left (old). positional: _input, _dicts options: _input: From 7a99c903fb214186a77b76e0993c6f09356d28f0 Mon Sep 17 00:00:00 2001 From: Sebastian Schmitt Date: Fri, 8 Dec 2023 15:26:35 +0100 Subject: [PATCH 3/4] Address review comments --- lib/ansible/plugins/filter/combine.yml | 40 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/lib/ansible/plugins/filter/combine.yml b/lib/ansible/plugins/filter/combine.yml index 33028ae8154..d51fe98af7a 100644 --- a/lib/ansible/plugins/filter/combine.yml +++ b/lib/ansible/plugins/filter/combine.yml @@ -34,6 +34,16 @@ DOCUMENTATION: EXAMPLES: | + # ab => {'a':1, 'b':3, 'c': 4} + ab: {{ {'a':1, 'b':2} | ansible.builtin.combine({'b':3, 'c':4}) }} + + many: "{{ dict1 | ansible.builtin.combine(dict2, dict3, dict4) }}" + + # defaults => {'a':{'b':3, 'c':4}, 'd': 5} + # customization => {'a':{'c':20}} + # final => {'a':{'b':3, 'c':20}, 'd': 5} + final: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" + ab: a: 1 b: 2 @@ -42,10 +52,19 @@ EXAMPLES: | b: 3 c: 4 + # { 'a': 1, 'b': 3, 'c': 4 } + combine_ab_bc: "{{ ab | ansible.builtin.combine(bc) }}" + cd: c: 5 d: 6 + # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } + combine_ab_bc_cd: "{{ ab | ansible.builtin.combine(bc, cd) }}" + + # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } + list_combine_ab_bc_cd: "{{ [ab, bc, cd] | ansible.builtin.combine }}" + defaults: a: b: 3 @@ -57,21 +76,6 @@ EXAMPLES: | c: 20 d: 30 - foo_with_list: - a: [1, 20] - - bar_with_list: - a: [20] - - # { 'a': 1, 'b': 3, 'c': 4 } - combine_ab_bc: "{{ ab | ansible.builtin.combine(bc) }}" - - # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } - combine_ab_bc_cd: "{{ ab | ansible.builtin.combine(bc, cd) }}" - - # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } - list_combine_ab_bc_cd: "{{ [ab, bc, cd] | ansible.builtin.combine }}" - # { 'a': { 'c': 20 }, 'd': 30 } # :recursive=false: (which is the default) defaults' 'a' is replaced with customization's 'a' defaults_with_customization: "{{ defaults | ansible.builtin.combine(customization) }}" @@ -80,6 +84,12 @@ EXAMPLES: | # recursive=true: defaults' 'a' is updated with customization's 'a', i.e., 'b' is untouched and 'c' is updated from 4 to 20 defaults_with_customization_recursive_true: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" + foo_with_list: + a: [1, 20] + + bar_with_list: + a: [20] + # { 'a': [ 20 ] } list_merge_replace: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='replace') }}" From 3335fd634101348b7d770e1f2ba3ad0a28a98fbd Mon Sep 17 00:00:00 2001 From: Sebastian Schmitt Date: Mon, 11 Dec 2023 11:07:59 +0100 Subject: [PATCH 4/4] Use one-liners --- lib/ansible/plugins/filter/combine.yml | 86 +++++++++----------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/lib/ansible/plugins/filter/combine.yml b/lib/ansible/plugins/filter/combine.yml index d51fe98af7a..fe08f45c357 100644 --- a/lib/ansible/plugins/filter/combine.yml +++ b/lib/ansible/plugins/filter/combine.yml @@ -34,81 +34,51 @@ DOCUMENTATION: EXAMPLES: | - # ab => {'a':1, 'b':3, 'c': 4} - ab: {{ {'a':1, 'b':2} | ansible.builtin.combine({'b':3, 'c':4}) }} + # combine_ab_bc => { 'a' : 1, 'b' : 3, 'c' : 4 } + combine_ab_bc: "{{ {'a' : 1, 'b' : 2} | ansible.builtin.combine({'b' : 3, 'c' : 4}) }}" - many: "{{ dict1 | ansible.builtin.combine(dict2, dict3, dict4) }}" + # combine_ab_bc_cd => { 'a' : 1, 'b' : 3, 'c' : 5, 'd' : 6 } + combine_ab_bc_cd: "{{ {'a' : 1, 'b' : 2} | ansible.builtin.combine({'b' : 3, 'c' : 4}, {'c' : 5, 'd' : 6}) }}" - # defaults => {'a':{'b':3, 'c':4}, 'd': 5} - # customization => {'a':{'c':20}} - # final => {'a':{'b':3, 'c':20}, 'd': 5} + # list_combine_ab_bc_cd => { 'a' : 1, 'b' : 3, 'c' : 5, 'd' : 6 } + list_combine_ab_bc_cd: "{{ [{'a' : 1, 'b' : 2}, {'b' : 3, 'c' : 4}, {'c' : 5, 'd' : 6}] | ansible.builtin.combine }}" + + # defaults => {'a' : {'b' : 3, 'c' : 4}, 'd' : 5} + # customization => {'a' : {'c' : 20}} + # final => {'a' : {'b' : 3, 'c' : 20}, 'd' : 5} final: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" - ab: - a: 1 - b: 2 - - bc: - b: 3 - c: 4 - - # { 'a': 1, 'b': 3, 'c': 4 } - combine_ab_bc: "{{ ab | ansible.builtin.combine(bc) }}" - - cd: - c: 5 - d: 6 - - # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } - combine_ab_bc_cd: "{{ ab | ansible.builtin.combine(bc, cd) }}" - - # { 'a': 1, 'b': 3, 'c': 5, 'd': 6 } - list_combine_ab_bc_cd: "{{ [ab, bc, cd] | ansible.builtin.combine }}" - - defaults: - a: - b: 3 - c: 4 - d: 5 - - customization: - a: - c: 20 - d: 30 - - # { 'a': { 'c': 20 }, 'd': 30 } + # defaults => {'a' : {'b' : 3, 'c' : 4}, 'd' : 5} + # customization => {'a' : {'c' : 20}, 'd' : 30} + # defaults_with_customization => { 'a' : { 'c' : 20 }, 'd' : 30 } # :recursive=false: (which is the default) defaults' 'a' is replaced with customization's 'a' defaults_with_customization: "{{ defaults | ansible.builtin.combine(customization) }}" - # { 'a': { 'b': 3, 'c': 20 }, 'd': 30 } + # defaults => {'a' : {'b' : 3, 'c' : 4}, 'd' : 5} + # customization => {'a' : {'c' : 20}, 'd' : 30} + # defaults_with_customization_recursive_true => { 'a' : { 'b' : 3, 'c' : 20 }, 'd' : 30 } # recursive=true: defaults' 'a' is updated with customization's 'a', i.e., 'b' is untouched and 'c' is updated from 4 to 20 defaults_with_customization_recursive_true: "{{ defaults | ansible.builtin.combine(customization, recursive=true) }}" - foo_with_list: - a: [1, 20] + # list_merge_replace => { 'a' : [ 20 ] } + list_merge_replace: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='replace') }}" - bar_with_list: - a: [20] + # list_merge_keep => { 'a' : [ 1, 20 ] } + list_merge_keep: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='keep') }}" - # { 'a': [ 20 ] } - list_merge_replace: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='replace') }}" + # list_merge_append => { 'a' : [ 1, 20, 20 ] + list_merge_append: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='append') }}" - # { 'a': [ 1, 20 ] } - list_merge_keep: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='keep') }}" + # list_merge_prepend => { 'a' : [ 20, 1, 20 ] } + list_merge_prepend: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='prepend') }}" - #{ 'a': [ 1, 20, 20 ] - list_merge_append: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='append') }}" - - # { 'a': [ 20, 1, 20 ] } - list_merge_prepend: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='prepend') }}" - - # { 'a': [ 1, 20 ] } + # list_merge_append_rp => { 'a' : [ 1, 20 ] } # note that there is only a single entry with value 20 - list_merge_append_rp: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='append_rp') }}" + list_merge_append_rp: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='append_rp') }}" - # { 'a': [ 20, 1 ] } + # list_merge_prepend_rp => { 'a' : [ 20, 1 ] } # note that there is only a single entry with value 20 - list_merge_prepend_rp: "{{ foo_with_list | ansible.builtin.combine(bar_with_list, list_merge='prepend_rp') }}" + list_merge_prepend_rp: "{{ {'a' : [1, 20]} | ansible.builtin.combine({'a' : [20]}, list_merge='prepend_rp') }}" RETURN: _value: