You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible如何查询hostvars并根据列表项某键值获取对应其他键值

编辑更新

我找到了实现需求的方法,使用index_of插件即可,以下代码可输出预期结果:

---
- hosts: CASPOSR1BDAT003
  connection: local
  gather_facts: no
  become: false
  tasks:
    - ansible.builtin.set_fact:
        mac_address: "{{ hostvars[inventory_hostname]['interfaces'][int_idx|int]['mac_address'] }}"
      vars:
        int_name: 'PCI1.1'
        int_idx: "{{ lookup('ansible.utils.index_of', hostvars[inventory_hostname]['interfaces'], 'eq', int_name, 'name') }}"
    - debug:
        var: mac_address

输出结果:

PLAY [CASPOSR1BDAT003] ***********************************************************************************************************************************************************************************************

TASK [ansible.builtin.set_fact] **************************************************************************************************************************************************************************************
ok: [CASPOSR1BDAT003]

TASK [debug] *********************************************************************************************************************************************************************************************************
ok: [CASPOSR1BDAT003] => 
  mac_address: 20:67:7C:00:36:A0

需求
  • 使用Netbox动态库存插件(已正常运行,可拉取所需全部信息)
  • 查询指定主机的hostvars,获取名为PCI1.1的接口对应的MAC地址值
已尝试的方案
  1. 将hostvars转为JSON后使用json_query查询:未成功,查阅相关资料后得知hostvars不属于"普通"字典
  2. 使用sequence循环配合when条件获取值:在使用debug模块时可部分生效,但无法直接返回该值。
可行的测试结果

我测试了以下代码,可以正常输出预期的mac_address变量值,逻辑是先获取列表长度,再通过条件匹配接口名称。执行时会收到使用Jinja2模板分隔符的警告,但这不是本问题的关注重点。

---
- hosts: CASPOSR1BDAT003
  connection: local
  gather_facts: no
  become: false
  tasks:
    - debug:
        var: hostvars[inventory_hostname]['interfaces'][{{ item }}]['mac_address']
      with_sequence: start=0 end="{{ end_at }}"
      vars:
        - end_at: "{{ (hostvars[inventory_hostname]['interfaces'] | length) - 1 }}"
      when: hostvars[inventory_hostname]['interfaces'][{{ item }}]['name'] == "PCI1.1"

运行结果:

TASK [debug] *************************************************************************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found:
hostvars[inventory_hostname]['interfaces'][{{ item }}]['name'] == "PCI1.1"
skipping: [CASPOSR1BDAT003] => (item=0) 
skipping: [CASPOSR1BDAT003] => (item=1) 
skipping: [CASPOSR1BDAT003] => (item=2) 
skipping: [CASPOSR1BDAT003] => (item=3) 
skipping: [CASPOSR1BDAT003] => (item=4) 
ok: [CASPOSR1BDAT003] => (item=5) => 
  ansible_loop_var: item
  hostvars[inventory_hostname]['interfaces'][5]['mac_address']: 20:67:7C:00:36:A0
  item: '5'
skipping: [CASPOSR1BDAT003] => (item=6) 
skipping: [CASPOSR1BDAT003] => (item=7) 
skipping: [CASPOSR1BDAT003] => (item=8) 
skipping: [CASPOSR1BDAT003] => (item=9) 

我希望用set_fact存储这个mac_address变量以便后续多处使用,但似乎无法对该hostvars数据(或其他hostvars数据)执行set_fact。例如以下代码:

---
- hosts: CASPOSR1BDAT003
  connection: local
  gather_facts: no
  become: false
  tasks:
    - ansible.builtin.set_fact:
        interfaces: "{{ hostvars[inventory_hostname]['interfaces'][item]['mac_address'] }}"
      with_sequence: start=0 end="{{ end_at }}"
      vars:
        - end_at: "{{ (hostvars[inventory_hostname]['interfaces'] | length) - 1 }}"
      when: hostvars[inventory_hostname]['interfaces'][{{ item }}]['name'] == "PCI1.1"
    - debug:
        var: interfaces

会返回报错:

fatal: [CASPOSR1BDAT003]: FAILED! => 
  msg: |-
    The task includes an option with an undefined variable. The error was: 'list object' has no attribute '5'
  
    The error appears to be in '/Users/kivlint/Documents/GitHub/vmware-automation/ansible/prepare-pxe.yml': line 19, column 7, but may
    be elsewhere in the file depending on the exact syntax problem.
  
    The offending line appears to be:
  
        #   when: hostvars[inventory_hostname]['interfaces'][{{ item }}]['name'] == "PCI1.1"
        - ansible.builtin.set_fact:
          ^ here

如果我硬编码数字5,则可以正常运行:

TASK [ansible.builtin.set_fact] ******************************************************************************************************************
ok: [CASPOSR1BDAT003]

TASK [debug] *************************************************************************************************************************************
ok: [CASPOSR1BDAT003] => 
  interfaces: 20:67:7C:00:36:A0

如果我在任务变量中指定'5',也可以正常运行:

---
- hosts: CASPOSR1BDAT003
  connection: local
  gather_facts: no
  become: false
  tasks:
    - ansible.builtin.set_fact:
        interfaces: "{{ hostvars[inventory_hostname]['interfaces'][int_index]['mac_address'] }}"
      vars:
        - int_index: 5

我想了解:这是set_fact与循环配合使用时的bug/特性吗?毕竟相同的循环在debug中可以正常运行。还是我需要调整思路,先使用set_fact设置列表索引变量(如上例中的5)?或者有其他解决方案?


内容的提问来源于stack exchange,提问作者TommyKTheDJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 02:24:05