2020-10-15 12:52:14 +00:00
.. _ansible.utils.index_of_lookup:
***** ***** ***** ***** **
ansible.utils.index_of
***** ***** ***** ***** **
2020-12-03 06:03:43 +00:00
**Find the indices of items in a list matching some criteria**
2020-10-15 12:52:14 +00:00
2020-12-03 06:03:43 +00:00
Version added: 1.0.0
2020-10-15 12:52:14 +00:00
.. contents ::
:local:
:depth: 1
Synopsis
--------
2020-12-03 06:03:43 +00:00
- 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.
2021-03-31 17:43:38 +00:00
- **index_of** is also available as a **filter plugin** for convenience.
2020-12-03 06:03:43 +00:00
- Using the parameters below- `` lookup('ansible.utils.index_of', data, test, value, key, fail_on_missing, wantlist `` ).
2020-10-15 12:52:14 +00:00
Parameters
----------
.. raw :: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
2022-04-25 14:57:04 +00:00
/ <span style="color: purple">elements=raw</span>
2020-10-15 12:52:14 +00:00
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
2020-12-03 06:03:43 +00:00
<div>A list of items to enumerate and test against.</div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>fail_on_missing</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li>yes</li>
</ul>
</td>
<td>
</td>
<td>
2020-12-03 06:03:43 +00:00
<div>When provided a list of dictionaries, fail if the key is missing from one or more of the dictionaries.</div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>key</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
2022-05-25 22:53:41 +00:00
<div>When the data provided is a list of dictionaries, run the test against this dictionary key.</div>
<div>When using a <em>key</em>, the <em>data</em> must only contain dictionaries.</div>
<div>See <em>fail_on_missing</em> below to determine the behaviour when the <em>key</em> is missing from a dictionary in the <em>data</em>.</div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>test</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
2022-05-25 22:53:41 +00:00
<div>The name of the test to run against the list, a valid jinja2 test or ansible test plugin.</div>
<div>Jinja2 includes the following tests <a href='http://jinja.palletsprojects.com/templates/#builtin-tests'>http://jinja.palletsprojects.com/templates/#builtin-tests</a>.</div>
<div>An overview of tests included in ansible <a href='https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html'>https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html</a>.</div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>value</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
2022-05-25 22:53:41 +00:00
<div>The value used to test each list item against.</div>
<div>Not required for simple tests (e.g. <code>true</code>, <code>false</code>, <code>even</code>, <code>odd</code>)</div>
<div>May be a <code>string</code>, <code>boolean</code>, <code>number</code>, <code>regular expression</code> <code>dict</code> and so on, depending on the <b>test</b> used.</div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>wantlist</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li>yes</li>
</ul>
</td>
<td>
</td>
<td>
2022-05-25 22:53:41 +00:00
<div>When only a single entry in the <em>data</em> is matched, the index of that entry is returned as an integer.</div>
<div>If set to <code>True</code>, the return value will always be a list, even if only a single entry is matched.</div>
<div>This can also be accomplished using <code>query</code> or <code>q</code> instead of <code>lookup</code>.</div>
<div><a href='https://docs.ansible.com/ansible/latest/plugins/lookup.html'>https://docs.ansible.com/ansible/latest/plugins/lookup.html</a></div>
2020-10-15 12:52:14 +00:00
</td>
</tr>
</table>
<br/>
Examples
--------
2020-10-20 19:14:23 +00:00
.. code-block :: yaml
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
#### Simple examples
2020-10-15 12:52:14 +00:00
2021-01-25 11:27:04 +00:00
- ansible.builtin.set_fact:
2020-10-15 12:52:14 +00:00
data:
2023-11-13 05:58:43 +00:00
- 1
- 2
- 3
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
- name: Find the index of 2
2021-01-25 11:27:04 +00:00
ansible.builtin.set_fact:
2020-10-21 17:45:34 +00:00
indices: "{{ lookup('ansible.utils.index_of', data, 'eq', 2) }}"
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
# TASK [Find the index of 2] ***** ***** ***** ***** ***** ***** ***** ***** ***** *** *
# ok: [nxos101] => changed=false
2020-10-15 12:52:14 +00:00
# ansible_facts:
2020-10-21 17:45:34 +00:00
# indices: '1'
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
- name: Find the index of 2, ensure list is returned
2021-01-25 11:27:04 +00:00
ansible.builtin.set_fact:
2020-10-21 17:45:34 +00:00
indices: "{{ lookup('ansible.utils.index_of', data, 'eq', 2, wantlist=True) }}"
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
# TASK [Find the index of 2, ensure list is returned] ***** ***** ***** ***** *** *
# ok: [nxos101] => changed=false
2020-10-15 12:52:14 +00:00
# ansible_facts:
2020-10-21 17:45:34 +00:00
# indices:
2020-10-15 12:52:14 +00:00
# - 1
- name: Find the index of 3 using the long format
2021-01-25 11:27:04 +00:00
ansible.builtin.set_fact:
2020-10-21 17:45:34 +00:00
indices: "{{ lookup('ansible.utils.index_of', data=data, test='eq', value=value, wantlist=True) }}"
2020-10-15 12:52:14 +00:00
vars:
value: 3
# TASK [Find the index of 3 using the long format] ***** ***** ***** ***** ***** **
2020-10-21 17:45:34 +00:00
# ok: [nxos101] => changed=false
2020-10-15 12:52:14 +00:00
# ansible_facts:
2020-10-21 17:45:34 +00:00
# indices:
2020-10-15 12:52:14 +00:00
# - 2
- name: Find numbers greater than 1, using loop
debug:
msg: "{{ data[item] }} is {{ test }} than {{ value }}"
2020-10-21 17:45:34 +00:00
loop: "{{ lookup('ansible.utils.index_of', data, test, value) }}"
2020-10-15 12:52:14 +00:00
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
- name: Find numbers greater than 1, using with
debug:
msg: "{{ data[item] }} is {{ params.test }} than {{ params.value }}"
with_ansible.utils.index_of: "{{ params }}"
vars:
params:
data: "{{ data }}"
test: '>'
value: 1
# TASK [Find numbers greater than 1, using with] ***** ***** ***** ***** ***** *** *
2020-10-21 17:45:34 +00:00
# ok: [nxos101] => (item=1) =>
2020-10-15 12:52:14 +00:00
# msg: 2 is > than 1
2020-10-21 17:45:34 +00:00
# ok: [nxos101] => (item=2) =>
2020-10-15 12:52:14 +00:00
# msg: 3 is > than 1
#### Working with lists of dictionaries
2021-01-25 11:27:04 +00:00
- ansible.builtin.set_fact:
2020-10-15 12:52:14 +00:00
data:
2023-11-13 05:58:43 +00:00
- name: sw01.example.lan
type: switch
- name: rtr01.example.lan
type: router
- name: fw01.example.corp
type: firewall
- name: fw02.example.corp
type: firewall
2020-10-15 12:52:14 +00:00
- name: Find the index of all firewalls using the type key
2021-01-25 11:27:04 +00:00
ansible.builtin.set_fact:
2020-10-21 17:45:34 +00:00
firewalls: "{{ lookup('ansible.utils.index_of', data, 'eq', 'firewall', 'type') }}"
2020-10-15 12:52:14 +00:00
# TASK [Find the index of all firewalls using the type key] ***** ***** ***** ***
2020-10-21 17:45:34 +00:00
# ok: [nxos101] => changed=false
2020-10-15 12:52:14 +00:00
# ansible_facts:
2020-10-21 17:45:34 +00:00
# firewalls:
2020-10-15 12:52:14 +00:00
# - 2
# - 3
2020-10-21 17:45:34 +00:00
- name: Find the index of all firewalls, use in a loop
2020-10-15 12:52:14 +00:00
debug:
msg: "The type of {{ device_type }} at index {{ item }} has name {{ data[item].name }}."
2020-10-21 17:45:34 +00:00
loop: "{{ lookup('ansible.utils.index_of', data, 'eq', device_type, 'type') }}"
2020-10-15 12:52:14 +00:00
vars:
device_type: firewall
2020-10-21 17:45:34 +00:00
# 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.
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
- name: Find the index of all devices with a .corp name
2020-10-15 12:52:14 +00:00
debug:
msg: "The device named {{ data[item].name }} is a {{ data[item].type }}"
2020-10-21 17:45:34 +00:00
loop: "{{ lookup('ansible.utils.index_of', data, 'regex', expression, 'name') }}"
2020-10-15 12:52:14 +00:00
vars:
2023-11-13 05:58:43 +00:00
expression: '\.corp$'
2020-10-15 12:52:14 +00:00
2020-10-21 17:45:34 +00:00
# TASK [Find the index of all devices with a .corp name] ***** ***** ***** ***** *
# ok: [nxos101] => (item=2) =>
2020-10-15 12:52:14 +00:00
# msg: The device named fw01.example.corp is a firewall
2020-10-21 17:45:34 +00:00
# ok: [nxos101] => (item=3) =>
2020-10-15 12:52:14 +00:00
# msg: The device named fw02.example.corp is a firewall
2020-10-21 17:45:34 +00:00
#### Working with complex structures from resource modules
2020-10-15 12:52:14 +00:00
- 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
2020-10-21 17:45:34 +00:00
- name: Find the indices interfaces with a 192.168.101.xx ip address
2021-01-25 11:27:04 +00:00
ansible.builtin.set_fact:
2020-10-15 12:52:14 +00:00
found: "{{ found + entry }}"
with_indexed_items: "{{ current_l3.gathered }}"
vars:
found: []
ip: '192.168.101.'
2023-11-13 05:58:43 +00:00
address: "{{ lookup('ansible.utils.index_of', item.1.ipv4 | d([]), 'search', ip, 'address', wantlist=True) }}"
2020-10-15 12:52:14 +00:00
entry:
2023-11-13 05:58:43 +00:00
- interface_idx: "{{ item.0 }}"
address_idxs: "{{ address }}"
2020-10-15 12:52:14 +00:00
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 }}"
2020-10-21 17:45:34 +00:00
# TASK [Show all interfaces and their address] ***** ***** ***** ***** ***** ***** *
# ok: [nxos101] => (item=[{'interface_idx': '128', 'address_idxs': [0]}, 0]) =>
2020-10-15 12:52:14 +00:00
# msg: mgmt0 has ip 192.168.101.14/24
2020-10-21 17:45:34 +00:00
#### Working with deeply nested data
2020-10-15 12:52:14 +00:00
2021-01-25 11:27:04 +00:00
- ansible.builtin.set_fact:
2020-10-15 12:52:14 +00:00
data:
interfaces:
interface:
2020-10-21 17:45:34 +00:00
- config:
description: configured by Ansible - 1
2023-11-13 05:58:43 +00:00
enabled: true
loopback-mode: false
2020-10-21 17:45:34 +00:00
mtu: 1024
name: loopback0000
type: eth
2020-10-15 12:52:14 +00:00
name: loopback0000
2020-10-21 17:45:34 +00:00
subinterfaces:
subinterface:
- config:
description: subinterface configured by Ansible - 1
2023-11-13 05:58:43 +00:00
enabled: true
2020-10-21 17:45:34 +00:00
index: 5
index: 5
- config:
description: subinterface configured by Ansible - 2
2023-11-13 05:58:43 +00:00
enabled: false
2020-10-21 17:45:34 +00:00
index: 2
index: 2
- config:
description: configured by Ansible - 2
2023-11-13 05:58:43 +00:00
enabled: false
loopback-mode: false
2020-10-21 17:45:34 +00:00
mtu: 2048
name: loopback1111
type: virt
2020-10-15 12:52:14 +00:00
name: loopback1111
2020-10-21 17:45:34 +00:00
subinterfaces:
subinterface:
- config:
description: subinterface configured by Ansible - 3
2023-11-13 05:58:43 +00:00
enabled: true
2020-10-21 17:45:34 +00:00
index: 10
index: 10
- config:
description: subinterface configured by Ansible - 4
2023-11-13 05:58:43 +00:00
enabled: false
2020-10-21 17:45:34 +00:00
index: 3
index: 3
2020-10-15 12:52:14 +00:00
- name: Find the description of loopback111, subinterface index 10
debug:
msg: |-
{{ data.interfaces.interface[int_idx|int]
2020-10-21 17:45:34 +00:00
.subinterfaces.subinterface[subint_idx|int]
.config.description }}
2020-10-15 12:52:14 +00:00
vars:
# the values to search for
int_name: loopback1111
sub_index: 10
# retrieve the index in each nested list
int_idx: |
2020-10-21 17:45:34 +00:00
{{ lookup('ansible.utils.index_of',
data.interfaces.interface,
'eq', int_name, 'name') }}
2020-10-15 12:52:14 +00:00
subint_idx: |
2020-10-21 17:45:34 +00:00
{{ lookup('ansible.utils.index_of',
data.interfaces.interface[int_idx|int].subinterfaces.subinterface,
'eq', sub_index, 'index') }}
2020-10-15 12:52:14 +00:00
# TASK [Find the description of loopback111, subinterface index 10] ***** ***** **
# ok: [sw01] =>
# msg: subinterface configured by Ansible - 3
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values> `_ , the following are the fields unique to this lookup:
.. raw :: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>_raw</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td></td>
<td>
2020-12-03 06:03:43 +00:00
<div>One or more zero-based indicies of the matching list items.</div>
<div>See <code>wantlist</code> if a list is always required.</div>
2020-10-15 12:52:14 +00:00
<br/>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Bradley Thornton (@cidrblock)
.. hint ::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.