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地址值
已尝试的方案
- 将hostvars转为JSON后使用json_query查询:未成功,查阅相关资料后得知hostvars不属于"普通"字典
- 使用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
相关产品推荐
相关产品推荐

