I want to remove some keys (nesting level 0) from a list of dictionnaries so that I can apply the unique
filter and get some sort of classification of my list items. If I use the ansible.utils.keep_keys filter, I get undesired results, because it only works recursively. This may result in kept unmatched keys on nesting level 0 if some subkey matches the filter. Further more, this filter behaves strangely if lists of integers are involved, e. g.:
- debug:
msg: "{{ my_list | keep_keys(target=['key0', 'key1']) | unique }}"
vars:
my_list:
- key0: A
key1: B
key2:
- 1
key3: foo
- key0: A
key1: B
key2:
- 2
key4: bar
results in:
msg:
- key0: A
key1: B
key2:
- 1
- key0: A
key1: B
key2:
- 2
instead of:
msg:
- key0: A
key1: B
remove_keys
is not an option, because it also works recursively and the number of unwanted keys is way bigger than the number of desired keys. As keep_keys
does not offer an option to work non recursively, I assume there must be another way to achieve this, but I cannot figure it out.
Is there a way to keep keys in Ansible non recursively, besides developing my own filter?
Use Jinja. For example,
keep: [key0, key1]
result: |
{% filter from_yaml %}
{% for i in my_list %}
- {{ dict(keep|zip(keep|map('extract', i))) }}
{% endfor %}
{% endfilter %}
gives
result:
- {key0: A, key1: B}
- {key0: A, key1: B}
Example of a complete playbook for testing
- hosts: localhost
vars:
my_list:
- key0: A
key1: B
key2: [1]
key3: foo
- key0: A
key1: B
key2: [2]
key4: bar
keep: [key0, key1]
result: |
{% filter from_yaml %}
{% for i in my_list %}
- {{ dict(keep|zip(keep|map('extract', i))) }}
{% endfor %}
{% endfilter %}
tasks:
- debug:
var: result|to_yaml
- debug:
var: result|unique