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

Ansible v2.16.2数据合并报错:如何构建含主机事实的结构化数据

解决方案

步骤1:构建包含主机facts的基础字典

你需要将目标主机的facts汇总为字典结构(而非数组),键为主机名,值包含对应facts信息。推荐在localhost上执行汇总操作,避免在每个目标主机重复维护数据:

---
- name: 收集并整合主机数据
  hosts: myhosts
  gather_facts: yes
  tasks:
    # 在每个主机上暂存自身facts到localhost
    - name: 暂存当前主机facts
      set_fact:
        _host_fact:
          "{{ inventory_hostname }}":
            facts: [ "{{ ansible_facts | to_json | from_json }}" ]
      delegate_to: localhost
      delegate_facts: no

- name: 汇总所有主机数据到provided_hosts
  hosts: localhost
  vars:
    provided_hosts: {}
  tasks:
    - name: 合并所有主机facts
      set_fact:
        provided_hosts: "{{ provided_hosts | combine(item, recursive=true) }}"
      loop: "{{ hostvars | json_query('*.hostvars.localhost._host_fact') }}"

执行后会生成你期望的基础结构:

"provided_hosts": {
  "SomeHost001": {
    "facts": [ { ...ansible_facts... } ]
  },
  "AnotherHost002": {
    "facts": [ { ...ansible_facts... } ]
  },
  "RandomHost-003": {
    "facts": [ { ...ansible_facts... } ]
  }
}

步骤2:添加vCenter关联信息

假设你有主机与vCenter的映射关系(可根据实际业务逻辑调整,比如自定义变量、主机名规则或facts字段),以下是基于自定义映射表的实现:

# 在localhost的Play中追加以下任务
- name: 定义主机与vCenter映射(示例)
  set_fact:
    host_vcenter_map:
      SomeHost001: vcenter1
      AnotherHost002: vcenter2
      RandomHost-003: vcenter1

- name: 为每个主机添加vCenter信息
  set_fact:
    provided_hosts: >-
      {{
        provided_hosts | combine(
          {
            item.key: provided_hosts[item.key] | combine(
              { 'vcenter': vcenters[item.value] }
            )
          },
          recursive=true
        )
      }}
  loop: "{{ host_vcenter_map | dict2items }}"

如果关联逻辑基于主机facts(比如ansible_virtualization_host),可直接替换映射表来源:

host_vcenter_map: "{{ hostvars | dict2items | items2dict(key_name='key', value_name='value.ansible_virtualization_host') }}"

关键错误修正说明

你之前的Playbook存在两个核心问题:

  1. 初始数据结构错误:将provided_hosts设为列表(groups['myhosts']是列表),但你需要的是字典结构,键为主机名。
  2. combine过滤器用法错误:combine的正确语法是dict1 | combine(dict2, recursive=true, list_merge='append'),你错误传入字符串'vcenters'作为参数,导致语法报错。

最终效果

完成后provided_hosts会包含完整结构:

"provided_hosts": {
  "SomeHost001": {
    "facts": [ { ...ansible_facts... } ],
    "vcenter": {
      "hostname": "vc01.somewhere.com",
      "ip_addr": "192.168.10.90"
    }
  },
  ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:50:40