mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
parent
b80854ff50
commit
0f88c71f59
5 changed files with 100 additions and 0 deletions
23
changelogs/fragments/604-lists_mergeby-new-filter.yml
Normal file
23
changelogs/fragments/604-lists_mergeby-new-filter.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
minor_changes:
|
||||
- |
|
||||
A new filter ``lists_mergeby`` to merge two lists of dictionaries by an attribute.
|
||||
For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
[{'n': 'n1', 'p1': 'A', 'p2': 'F'},
|
||||
{'n': 'n2', 'p2': 'B'}] | community.general.lists_mergeby(
|
||||
[{'n': 'n1', 'p1': 'C'},
|
||||
{'n': 'n2', 'p2': 'D'},
|
||||
{'n': 'n3', 'p3': 'E'}], 'n') | list
|
||||
|
||||
evaluates to
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
[{'n': 'n1', 'p1': 'C', 'p2': 'F'},
|
||||
{'n': 'n2', 'p2': 'D'},
|
||||
{'n': 'n3', 'p3': 'E'}]
|
||||
|
||||
(https://github.com/ansible-collections/community.general/pull/604).
|
47
plugins/filter/list.py
Normal file
47
plugins/filter/list.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Vladimir Botka <vbotka@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common._collections_compat import Mapping, Sequence
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
|
||||
|
||||
def lists_mergeby(l1, l2, index):
|
||||
''' merge lists by attribute index. Example:
|
||||
- debug: msg="{{ l1|community.general.lists_mergeby(l2, 'index')|list }}" '''
|
||||
|
||||
if not isinstance(l1, Sequence):
|
||||
raise AnsibleFilterError('First argument for community.general.lists_mergeby must be list. %s is %s' %
|
||||
(l1, type(l1)))
|
||||
|
||||
if not isinstance(l2, Sequence):
|
||||
raise AnsibleFilterError('Second argument for community.general.lists_mergeby must be list. %s is %s' %
|
||||
(l2, type(l2)))
|
||||
|
||||
if not isinstance(index, string_types):
|
||||
raise AnsibleFilterError('Third argument for community.general.lists_mergeby must be string. %s is %s' %
|
||||
(index, type(index)))
|
||||
|
||||
d = defaultdict(dict)
|
||||
for l in (l1, l2):
|
||||
for elem in l:
|
||||
if not isinstance(elem, Mapping):
|
||||
raise AnsibleFilterError('Elements of list arguments for lists_mergeby must be dictionaries. Found {0!r}.'.format(elem))
|
||||
if index in elem.keys():
|
||||
d[elem[index]].update(elem)
|
||||
return sorted(d.values(), key=itemgetter(index))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
''' Ansible list filters '''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'lists_mergeby': lists_mergeby,
|
||||
}
|
2
tests/integration/targets/filter_list/aliases
Normal file
2
tests/integration/targets/filter_list/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
shippable/posix/group2
|
||||
skip/python2.6 # filters are controller only, and we no longer support Python 2.6 on the controller
|
6
tests/integration/targets/filter_list/tasks/main.yml
Normal file
6
tests/integration/targets/filter_list/tasks/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: Test lists merged by attribute name
|
||||
assert:
|
||||
that:
|
||||
- "(list1 | community.general.lists_mergeby(list2, 'name') | list |
|
||||
difference(list3) | length) == 0"
|
22
tests/integration/targets/filter_list/vars/main.yml
Normal file
22
tests/integration/targets/filter_list/vars/main.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
list1:
|
||||
- name: myname01
|
||||
param01: myparam01
|
||||
- name: myname02
|
||||
param01: myparam02
|
||||
|
||||
list2:
|
||||
- name: myname01
|
||||
param01: myparam03
|
||||
- name: myname02
|
||||
param02: myparam04
|
||||
- name: myname03
|
||||
param03: myparam03
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01: myparam03
|
||||
- name: myname02
|
||||
param01: myparam02
|
||||
param02: myparam04
|
||||
- name: myname03
|
||||
param03: myparam03
|
Loading…
Reference in a new issue