ansible.utils.index_of 查找 – 查找列表中符合某些条件的项的索引

注意

此查找插件是 ansible.utils 集合 (版本 5.1.2) 的一部分。

如果您正在使用 ansible 包,您可能已经安装了此集合。它不包含在 ansible-core 中。要检查是否已安装,请运行 ansible-galaxy collection list

要安装它,请使用: ansible-galaxy collection install ansible.utils

要在 playbook 中使用它,请指定: ansible.utils.index_of

ansible.utils 1.0.0 中的新增功能

概要

  • 此插件返回列表中符合某些条件的项的索引。

  • 当处理字典列表时,可以指定要评估的键。

  • 为了方便起见,index_of 也可用作过滤器插件

  • 使用以下参数 - lookup('ansible.utils.index_of', data, test, value, key, fail_on_missing, wantlist)。

关键字参数

这描述了查找的关键字参数。这些是以下示例中的值 key1=value1key2=value2 等:lookup('ansible.utils.index_of', key1=value1, key2=value2, ...)query('ansible.utils.index_of', key1=value1, key2=value2, ...)

参数

注释

数据

列表 / 元素=任意 / 必需

要枚举并测试的项列表。

fail_on_missing

布尔值

当提供字典列表时,如果一个或多个字典中缺少键,则会失败。

选择

  • false

  • true

字符串

当提供的数据是字典列表时,针对此字典键运行测试。

当使用时,数据必须仅包含字典。

请参阅下面的fail_on_missing,以确定当数据中的字典缺少时的行为。

测试

字符串 / 必需

要针对列表运行的测试名称,有效的 jinja2 测试或 ansible 测试插件。

Jinja2 包括以下测试 https://jinja.flask.org.cn/templates/#builtin-tests

ansible 中包含的测试概述 https://docs.ansible.org.cn/ansible/latest/user_guide/playbooks_tests.html

任何

用于测试每个列表项的值。

对于简单测试(例如,truefalseevenodd)不是必需的

可以是 stringbooleannumberregular expression dict 等,具体取决于所使用的 test

wantlist

布尔值

当仅匹配数据中的单个条目时,该条目的索引将作为整数返回。

如果设置为 True,则返回值将始终是一个列表,即使仅匹配单个条目也是如此。

也可以使用 queryq 而不是 lookup 来完成此操作。

https://docs.ansible.org.cn/ansible/latest/plugins/lookup.html

选择

  • false

  • true

示例

#### Simple examples

- ansible.builtin.set_fact:
    data:
      - 1
      - 2
      - 3

- name: Find the index of 2
  ansible.builtin.set_fact:
    indices: "{{ lookup('ansible.utils.index_of', data, '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: "{{ lookup('ansible.utils.index_of', data, '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: "{{ lookup('ansible.utils.index_of', data=data, 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: "{{ lookup('ansible.utils.index_of', data, 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

- 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] *****************************
# ok: [nxos101] => (item=1) =>
#   msg: 2 is > than 1
# ok: [nxos101] => (item=2) =>
#   msg: 3 is > than 1


#### Working with lists of dictionaries

- 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: "{{ lookup('ansible.utils.index_of', data, '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: "{{ lookup('ansible.utils.index_of', data, '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: "{{ lookup('ansible.utils.index_of', data, 'regex', expression, 'name') }}"
  vars:
    expression: '\.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: "{{ lookup('ansible.utils.index_of', item.1.ipv4 | d([]), '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

- 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: |
      {{ lookup('ansible.utils.index_of',
             data.interfaces.interface,
                 'eq', int_name, 'name') }}
    subint_idx: |
      {{ lookup('ansible.utils.index_of',
             data.interfaces.interface[int_idx|int].subinterfaces.subinterface,
                 'eq', sub_index, 'index') }}

# TASK [Find the description of loopback111, subinterface index 10] ************
# ok: [sw01] =>
#   msg: subinterface configured by Ansible - 3

返回值

描述

返回值

字符串

匹配的列表项的一个或多个从零开始的索引。

如果始终需要列表,请参阅 wantlist

返回:成功

作者

  • Bradley Thornton (@cidrblock)

提示

每种条目类型的配置条目都具有从低到高的优先级顺序。例如,列表中较低的变量将覆盖较高的变量。