[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
|
- key: Environment
|
||||||
value: dev
|
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_filter:
|
||||||
|
|
||||||
Random Number Filter
|
Random Number Filter
|
||||||
|
|
|
@ -473,6 +473,52 @@ def flatten(mylist, levels=None):
|
||||||
return ret
|
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):
|
def dict_to_list_of_dict_key_value_elements(mydict):
|
||||||
''' takes a dictionary and transforms it into a list of dictionaries,
|
''' 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 '''
|
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,
|
'extract': extract,
|
||||||
'flatten': flatten,
|
'flatten': flatten,
|
||||||
'dict2items': dict_to_list_of_dict_key_value_elements,
|
'dict2items': dict_to_list_of_dict_key_value_elements,
|
||||||
|
'subelements': subelements,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue