Add a get_nested filter
When accessing nested facts, such as in ansible_local sections, guard statements in the when clause can get quite long, due to having to repeate the 'in/not in' logic for every key at every level. The get_nested filter attempts to instead to move the guard into a single line, making the conditions easier to write and maintain. As example, ('openstack_ansible' not in ansible_local or 'swift' not in ansible_local['openstack_ansible'] or 'venv_tag' not in ansible_local['openstack_ansible']['swift'] or ansible_local['openstack_ansible']['swift']['venv_tag'] == swift_venv_tag) could be rewritten as get_nested(ansible_local, 'openstack_ansible.swift.venv_tag') == swift_venv_tag Change-Id: I3b43c25c8783c43cf5285f2b3e7267b2c5712ea0
This commit is contained in:
parent
ca87421e46
commit
80a1262252
@ -317,6 +317,34 @@ def git_link_parse_name(repo):
|
||||
|
||||
return git_link_parse(repo)['name']
|
||||
|
||||
def get_nested(target_dict, keys):
|
||||
"""Retrieves values through a nested dictionary.
|
||||
|
||||
If any key on the path is missing, return None
|
||||
|
||||
This helps solves convoluted guards in roles/plays such as the following:
|
||||
|
||||
('openstack_ansible' not in ansible_local or
|
||||
'swift' not in ansible_local['openstack_ansible'] or
|
||||
'venv_tag' not in ansible_local['openstack_ansible']['swift'] or
|
||||
ansible_local['openstack_ansible']['swift']['venv_tag'] == swift_venv_tag)
|
||||
|
||||
With this filter, it could be instead written:
|
||||
ansible_local|get_nested('openstack_ansible.swift.venv_tag') == swift_venv_tag
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
key, next_keys = keys.split('.', 1)
|
||||
except ValueError:
|
||||
return target_dict.get(keys, None)
|
||||
|
||||
try:
|
||||
next_dict = target_dict[key]
|
||||
except KeyError:
|
||||
return None
|
||||
return get_nested(next_dict, next_keys)
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
"""Ansible jinja2 filters."""
|
||||
@ -335,5 +363,6 @@ class FilterModule(object):
|
||||
'filtered_list': filtered_list,
|
||||
'git_link_parse': git_link_parse,
|
||||
'git_link_parse_name': git_link_parse_name,
|
||||
'deprecated': _deprecated
|
||||
'deprecated': _deprecated,
|
||||
'get_nested': get_nested
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- The `get_nested` filter has been added, allowing for simplified
|
||||
value lookups inside of nested dictionaries.
|
||||
|
||||
`ansible_local|get_nested('openstack_ansible.swift')`, for example,
|
||||
will look 2 levels down and return the result.
|
@ -120,3 +120,18 @@
|
||||
- name: Validate deprecated filter
|
||||
assert:
|
||||
that: "deprecated_value == old_var"
|
||||
|
||||
- name: Set test_dict fact
|
||||
set_fact:
|
||||
test_dict:
|
||||
a:
|
||||
b:
|
||||
c: d
|
||||
|
||||
- name: Validate get_nested returns value
|
||||
assert:
|
||||
that: "{{ test_dict|get_nested('a.b.c') == 'd' }}"
|
||||
|
||||
- name: Validate get_nested returns None on missing key
|
||||
assert:
|
||||
that: "{{ test_dict|get_nested('a.c') == None }}"
|
||||
|
Loading…
Reference in New Issue
Block a user