[WIP] Start of subelements filter (#39829)
* Start of subelements filter * Add docs for subelements filter
This commit is contained in:
parent
46fbfd5d53
commit
a5f05c6fc2
2 changed files with 106 additions and 0 deletions
|
@ -184,6 +184,65 @@ into::
|
|||
- key: Environment
|
||||
value: dev
|
||||
|
||||
subelements Filter
|
||||
``````````````````
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
Produces a product of an object, and subelement values of that object, similar to the ``subelements`` lookup::
|
||||
|
||||
{{ users|subelements('groups', skip_missing=True) }}
|
||||
|
||||
Which turns::
|
||||
|
||||
users:
|
||||
- name: alice
|
||||
authorized:
|
||||
- /tmp/alice/onekey.pub
|
||||
- /tmp/alice/twokey.pub
|
||||
groups:
|
||||
- wheel
|
||||
- docker
|
||||
- name: bob
|
||||
authorized:
|
||||
- /tmp/bob/id_rsa.pub
|
||||
groups:
|
||||
- docker
|
||||
|
||||
Into::
|
||||
|
||||
-
|
||||
- name: alice
|
||||
groups:
|
||||
- wheel
|
||||
- docker
|
||||
authorized:
|
||||
- /tmp/alice/onekey.pub
|
||||
- wheel
|
||||
-
|
||||
- name: alice
|
||||
groups:
|
||||
- wheel
|
||||
- docker
|
||||
authorized:
|
||||
- /tmp/alice/onekey.pub
|
||||
- docker
|
||||
-
|
||||
- name: bob
|
||||
authorized:
|
||||
- /tmp/bob/id_rsa.pub
|
||||
groups:
|
||||
- docker
|
||||
- docker
|
||||
|
||||
An example of using this filter with ``loop``::
|
||||
|
||||
- name: Set authorized ssh key, extracting just that data from 'users'
|
||||
authorized_key:
|
||||
user: "{{ item.0.name }}"
|
||||
key: "{{ lookup('file', item.1) }}"
|
||||
loop: "{{ users|subelements('authorized') }}"
|
||||
|
||||
.. _random_filter:
|
||||
|
||||
Random Number Filter
|
||||
|
|
|
@ -473,6 +473,52 @@ def flatten(mylist, levels=None):
|
|||
return ret
|
||||
|
||||
|
||||
def subelements(obj, subelements, skip_missing=False):
|
||||
'''Accepts a dict or list of dicts, and a dotted accessor and produces a product
|
||||
of the element and the results of the dotted accessor
|
||||
|
||||
>>> obj = [{"name": "alice", "groups": ["wheel"], "authorized": ["/tmp/alice/onekey.pub"]}]
|
||||
>>> subelements(obj, 'groups')
|
||||
[({'name': 'alice', 'groups': ['wheel'], 'authorized': ['/tmp/alice/onekey.pub']}, 'wheel')]
|
||||
|
||||
'''
|
||||
if isinstance(obj, dict):
|
||||
element_list = list(obj.values())
|
||||
elif isinstance(obj, list):
|
||||
element_list = obj[:]
|
||||
else:
|
||||
raise AnsibleFilterError('obj must be a list of dicts or a nested dict')
|
||||
|
||||
if isinstance(subelements, list):
|
||||
subelement_list = subelements[:]
|
||||
elif isinstance(subelements, string_types):
|
||||
subelement_list = subelements.split('.')
|
||||
else:
|
||||
raise AnsibleFilterError('subelements must be a list or a string')
|
||||
|
||||
results = []
|
||||
|
||||
for element in element_list:
|
||||
values = element
|
||||
for subelement in subelement_list:
|
||||
try:
|
||||
values = values[subelement]
|
||||
except KeyError:
|
||||
if skip_missing:
|
||||
values = []
|
||||
break
|
||||
raise AnsibleFilterError("could not find %r key in iterated item %r" % (subelement, values))
|
||||
except TypeError:
|
||||
raise AnsibleFilterError("the key %s should point to a dictionary, got '%s'" % (subelement, values))
|
||||
if not isinstance(values, list):
|
||||
raise AnsibleFilterError("the key %r should point to a list, got %r" % (subelement, values))
|
||||
|
||||
for value in values:
|
||||
results.append((element, value))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def dict_to_list_of_dict_key_value_elements(mydict):
|
||||
''' takes a dictionary and transforms it into a list of dictionaries,
|
||||
with each having a 'key' and 'value' keys that correspond to the keys and values of the original '''
|
||||
|
@ -574,4 +620,5 @@ class FilterModule(object):
|
|||
'extract': extract,
|
||||
'flatten': flatten,
|
||||
'dict2items': dict_to_list_of_dict_key_value_elements,
|
||||
'subelements': subelements,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue