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

如何从Ansible组中所有主机提取多个hostvars变量?

问题描述

需从主机中提取INSTANCE_CLASS变量,主机变量以无扩展名文件存储在hostvars目录中,文件名对应主机名,例如host12的变量内容如下:

---
ansible_host: 10.11.12.15
INSTANCE_CLASS: vm_host
...

此前已实现多主机提取hostvar的方法,但现在需要生成字典列表而非字符串列表,两次尝试均未达到预期:

尝试1:循环赋值导致变量覆盖

使用循环逐个生成字典,但每次set_fact都会覆盖ne_hosts,最终仅保留最后一个元素:

- hosts: general
  gather_facts: false
  vars:
    ip_list: "{{ ansible_play_hosts_all | map('extract', hostvars, 'ansible_hostname') }}"
  tasks:
    - name: Get all IPs
      set_fact:
        ne_hosts:
          - ip: "{{ hostvars[item]['ansible_host'] }}"
            instance_class: "{{ hostvars[item]['INSTANCE_CLASS'] }}"
      loop: "{{ ip_list }}"
      delegate_to: localhost
      delegate_facts: true
      run_once: true
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Display gathered IPs
      debug:
        var: ne_hosts

执行结果:

TASK [Display gathered IPs] ***************************************************************************************************************************************
ok: [localhost] => {
    "ne_hosts": [
        {
            "instance_class": "mdd_controller",
            "ip": "10.11.12.19"
        }
    ]
}

尝试2:IP列表完整但INSTANCE_CLASS仅取最后一个

直接赋值列表和单个变量,导致INSTANCE_CLASS只拿到当前主机的最后一个值:

- hosts: general
  gather_facts: false
  vars:
    ip_list: "{{ ansible_play_hosts_all | map('extract', hostvars, 'ansible_host') }}"
  tasks:
    - name: Get all IPs
      set_fact:
        ne_hosts: "ip: {{ ip_list }}, instance_class: {{ INSTANCE_CLASS }}"
      delegate_to: localhost
      delegate_facts: true
      run_once: true
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Display gathered IPs
      debug:
        var: ne_hosts

执行结果:

TASK [Display gathered IPs] ***************************************************************************************************************************************
ok: [localhost] => {
    "ne_hosts": "ip: ['10.11.12.15', '10.11.12.19'], instance_class: mdd_controller"
}

预期结果

期望生成包含每个主机对应IP和INSTANCE_CLASS的字典列表:

"ne_hosts": [
    {ip: '10.11.12.15', instance_class: vm_host},
    {ip: '10.11.12.19', instance_class: mdd_controller}
]

解决方案

可以利用Ansible过滤器直接生成目标列表,无需循环赋值,提供两种简洁实现方式:

方式1:使用map+zip+dict过滤器

- hosts: general
  gather_facts: false
  tasks:
    - name: Generate hosts dictionary list
      set_fact:
        ne_hosts: "{{ ansible_play_hosts_all | map('extract', hostvars, ['ansible_host', 'INSTANCE_CLASS']) | map('zip', ['ip', 'instance_class']) | map('dict') | list }}"
      delegate_to: localhost
      delegate_facts: true
      run_once: true
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Display result
      debug:
        var: ne_hosts

方式2:使用json_query(语法更直观)

- hosts: general
  gather_facts: false
  tasks:
    - name: Generate hosts dictionary list with json_query
      set_fact:
        ne_hosts: "{{ ansible_play_hosts_all | map('extract', hostvars) | json_query('[].{ip: ansible_host, instance_class: INSTANCE_CLASS}') }}"
      delegate_to: localhost
      delegate_facts: true
      run_once: true
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Display result
      debug:
        var: ne_hosts

方案说明

  • 方式1逻辑:先从每个主机hostvars中提取指定变量得到元组列表,再将元组与目标键名配对,最后转换为字典并组成列表。
  • 方式2利用JMESPath表达式,直接通过json_query筛选并构造所需的字典结构,可读性更强。

内容的提问来源于Stack Exchange,提问作者AbreQueVoy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:11:28