ansible.utils.index_of filter – Find the indices of items in a list matching some criteria
Note
This filter plugin is part of the ansible.utils collection (version 2.10.3).
You might already have this collection installed if you are using the ansible
package.
It is not included in ansible-core
.
To check whether it is installed, run ansible-galaxy collection list
.
To install it, use: ansible-galaxy collection install ansible.utils
.
To use it in a playbook, specify: ansible.utils.index_of
.
New in ansible.utils 1.0.0
Synopsis
This plugin returns the indices of items matching some criteria in a list.
When working with a list of dictionaries, the key to evaluate can be specified.
index_of is also available as a lookup plugin for convenience.
Using the parameters below-
data|ansible.utils.index_of(test, value, key, fail_on_missing, wantlist
)
Keyword parameters
This describes keyword parameters of the filter. These are the values key1=value1
, key2=value2
and so on in the following example: input | ansible.utils.index_of(key1=value1, key2=value2, ...)
.
Parameter |
Comments |
---|---|
A list of items to enumerate and test against. This option represents the value that is passed to the filter plugin in pipe format. For example |
|
When provided a list of dictionaries, fail if the key is missing from one or more of the dictionaries. Choices:
|
|
When the data provided is a list of dictionaries, run the test against this dictionary key. When using a key, the data must only contain dictionaries. See fail_on_missing below to determine the behavior when the key is missing from a dictionary in the data. |
|
The name of the test to run against the list, a valid jinja2 test or ansible test plugin. Jinja2 includes the following tests http://jinja.palletsprojects.com/templates/#builtin-tests. An overview of tests included in ansible https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html |
|
The value used to test each list item against. Not required for simple tests (eg: May be a |
|
When only a single entry in the data is matched, the index of that entry is returned as an integer. If set to Choices:
|
Examples
#### Simple examples
- name: Define a list
ansible.builtin.set_fact:
data:
- 1
- 2
- 3
- name: Find the index of 2
ansible.builtin.set_fact:
indices: "{{ data|ansible.utils.index_of('eq', 2) }}"
# TASK [Find the index of 2] *************************************************
# ok: [nxos101] => changed=false
# ansible_facts:
# indices: '1'
- name: Find the index of 2, ensure list is returned
ansible.builtin.set_fact:
indices: "{{ data|ansible.utils.index_of('eq', 2, wantlist=True) }}"
# TASK [Find the index of 2, ensure list is returned] ************************
# ok: [nxos101] => changed=false
# ansible_facts:
# indices:
# - 1
- name: Find the index of 3 using the long format
ansible.builtin.set_fact:
indices: "{{ data|ansible.utils.index_of(test='eq', value=value, wantlist=True) }}"
vars:
value: 3
# TASK [Find the index of 3 using the long format] ***************************
# ok: [nxos101] => changed=false
# ansible_facts:
# indices:
# - 2
- name: Find numbers greater than 1, using loop
debug:
msg: "{{ data[item] }} is {{ test }} than {{ value }}"
loop: "{{ data|ansible.utils.index_of(test, value) }}"
vars:
test: '>'
value: 1
# TASK [Find numbers great than 1, using loop] *******************************
# ok: [sw01] => (item=1) =>
# msg: 2 is > than 1
# ok: [sw01] => (item=2) =>
# msg: 3 is > than 1
#### Working with lists of dictionaries
- name: Define a list with hostname and type
ansible.builtin.set_fact:
data:
- name: sw01.example.lan
type: switch
- name: rtr01.example.lan
type: router
- name: fw01.example.corp
type: firewall
- name: fw02.example.corp
type: firewall
- name: Find the index of all firewalls using the type key
ansible.builtin.set_fact:
firewalls: "{{ data|ansible.utils.index_of('eq', 'firewall', 'type') }}"
# TASK [Find the index of all firewalls using the type key] ******************
# ok: [nxos101] => changed=false
# ansible_facts:
# firewalls:
# - 2
# - 3
- name: Find the index of all firewalls, use in a loop
debug:
msg: "The type of {{ device_type }} at index {{ item }} has name {{ data[item].name }}."
loop: "{{ data|ansible.utils.index_of('eq', device_type, 'type') }}"
vars:
device_type: firewall
# TASK [Find the index of all firewalls, use in a loop, as a filter] *********
# ok: [nxos101] => (item=2) =>
# msg: The type of firewall at index 2 has name fw01.example.corp.
# ok: [nxos101] => (item=3) =>
# msg: The type of firewall at index 3 has name fw02.example.corp.
- name: Find the index of all devices with a .corp name
debug:
msg: "The device named {{ data[item].name }} is a {{ data[item].type }}"
loop: "{{ data|ansible.utils.index_of('regex', expression, 'name') }}"
vars:
expression: '\.corp$' # ends with .corp
# TASK [Find the index of all devices with a .corp name] *********************
# ok: [nxos101] => (item=2) =>
# msg: The device named fw01.example.corp is a firewall
# ok: [nxos101] => (item=3) =>
# msg: The device named fw02.example.corp is a firewall
#### Working with complex structures from resource modules
- name: Retrieve the current L3 interface configuration
cisco.nxos.nxos_l3_interfaces:
state: gathered
register: current_l3
# TASK [Retrieve the current L3 interface configuration] *********************
# ok: [sw01] => changed=false
# gathered:
# - name: Ethernet1/1
# - name: Ethernet1/2
# <...>
# - name: Ethernet1/128
# - ipv4:
# - address: 192.168.101.14/24
# name: mgmt0
- name: Find the indices interfaces with a 192.168.101.xx ip address
ansible.builtin.set_fact:
found: "{{ found + entry }}"
with_indexed_items: "{{ current_l3.gathered }}"
vars:
found: []
ip: '192.168.101.'
address: "{{ item.1.ipv4|d([])|ansible.utils.index_of('search', ip, 'address', wantlist=True) }}"
entry:
- interface_idx: "{{ item.0 }}"
address_idxs: "{{ address }}"
when: address
# TASK [debug] ***************************************************************
# ok: [sw01] =>
# found:
# - address_idxs:
# - 0
# interface_idx: '128'
- name: Show all interfaces and their address
debug:
msg: "{{ interface.name }} has ip {{ address }}"
loop: "{{ found|subelements('address_idxs') }}"
vars:
interface: "{{ current_l3.gathered[item.0.interface_idx|int] }}"
address: "{{ interface.ipv4[item.1].address }}"
# TASK [Show all interfaces and their address] *******************************
# ok: [nxos101] => (item=[{'interface_idx': '128', 'address_idxs': [0]}, 0]) =>
# msg: mgmt0 has ip 192.168.101.14/24
#### Working with deeply nested data
- name: Define interface configuration facts
ansible.builtin.set_fact:
data:
interfaces:
interface:
- config:
description: configured by Ansible - 1
enabled: True
loopback-mode: False
mtu: 1024
name: loopback0000
type: eth
name: loopback0000
subinterfaces:
subinterface:
- config:
description: subinterface configured by Ansible - 1
enabled: True
index: 5
index: 5
- config:
description: subinterface configured by Ansible - 2
enabled: False
index: 2
index: 2
- config:
description: configured by Ansible - 2
enabled: False
loopback-mode: False
mtu: 2048
name: loopback1111
type: virt
name: loopback1111
subinterfaces:
subinterface:
- config:
description: subinterface configured by Ansible - 3
enabled: True
index: 10
index: 10
- config:
description: subinterface configured by Ansible - 4
enabled: False
index: 3
index: 3
- name: Find the description of loopback111, subinterface index 10
debug:
msg: |-
{{ data.interfaces.interface[int_idx|int]
.subinterfaces.subinterface[subint_idx|int]
.config.description }}
vars:
# the values to search for
int_name: loopback1111
sub_index: 10
# retrieve the index in each nested list
int_idx: |
{{ data.interfaces.interface|
ansible.utils.index_of('eq', int_name, 'name') }}
subint_idx: |
{{ data.interfaces.interface[int_idx|int]
.subinterfaces.subinterface|
ansible.utils.index_of('eq', sub_index, 'index') }}
# TASK [Find the description of loopback111, subinterface index 10] ************
# ok: [sw01] =>
# msg: subinterface configured by Ansible - 3