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

如何从Ansible的register.results变量生成指定结构的字典

问题:从Proxmox KVM任务结果中筛选changed项生成指定字典结构

需要从provisioning_vm变量中筛选出changed状态为true的项,生成如下结构的vm_dict字典:

vm_dict:
  80001:
    host_name: ansible-clone1
    host_ip_address: 10.10.0.1
  80002:
    host_name: ansible-clone2
    host_ip_address: 10.10.0.2

现有尝试及问题

使用set_fact和combine过滤器的代码如下,但存在两个问题:无法同时添加host_name和host_ip_address两个值,且changed状态判断逻辑错误:

- name: Populate dict
  set_fact:
   _dict: "{{ _dict|default({}) | combine( {item.item.key: item.item.value.host_name} ) }}"
  loop: "{{ provisioning_vm.results }}"
  when: provisioning_vm.changed == true

任务结果变量结构

provisioning_vm的具体结构:

{
    "provisioning_vm": {
        "changed": false,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "invocation": {
                    "module_args": {
                        "acpi": null,
                        "agent": null,
                        "api_host": "10.0.10.1:8006",
                        "api_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                        "api_token_id": null,
                        "api_token_secret": null,
                        "api_user": "ansible_admin@pve",
                        "args": null,
                        "autostart": null,
                        "balloon": null,
                        "bios": null,
                        "boot": null,
                        "bootdisk": null,
                        "cicustom": null,
                        "cipassword": null,
                        "citype": null,
                        "ciuser": null,
                        "clone": "arbitrary_template",
                        "cores": null,
                        "cpu": null,
                        "cpulimit": null,
                        "cpuunits": null,
                        "delete": null,
                        "description": null,
                        "digest": null,
                        "efidisk0": null,
                        "force": null,
                        "format": "raw",
                        "freeze": null,
                        "full": true,
                        "hostpci": null,
                        "hotplug": null,
                        "hugepages": null,
                        "ide": null,
                        "ipconfig": null,
                        "keyboard": null,
                        "kvm": null,
                        "localtime": null,
                        "lock": null,
                        "machine": null,
                        "memory": null,
                        "migrate_downtime": null,
                        "migrate_speed": null,
                        "name": "ansible-clone1.dev.test.com",
                        "nameservers": null,
                        "net": null,
                        "newid": 80001,
                        "node": "proxmox01",
                        "numa": null,
                        "numa_enabled": null,
                        "onboot": null,
                        "ostype": null,
                        "parallel": null,
                        "pool": null,
                        "protection": null,
                        "proxmox_default_behavior": "no_defaults",
                        "reboot": null,
                        "revert": null,
                        "sata": null,
                        "scsi": null,
                        "scsihw": null,
                        "searchdomains": null,
                        "serial": null,
                        "shares": null,
                        "skiplock": null,
                        "smbios": null,
                        "snapname": null,
                        "sockets": null,
                        "sshkeys": null,
                        "startdate": null,
                        "startup": null,
                        "state": "present",
                        "storage": "CEPH-DEV",
                        "tablet": null,
                        "tags": null,
                        "target": null,
                        "tdf": null,
                        "template": null,
                        "timeout": 400,
                        "update": false,
                        "validate_certs": false,
                        "vcpus": null,
                        "vga": null,
                        "virtio": null,
                        "vmid": 987654,
                        "watchdog": null
                    }
                },
                "item": {
                    "key": 80001,
                    "value": {
                        "host_ip_address": "10.10.0.1",
                        "host_name": "ansible-clone1.dev.test.com"
                    }
                },
                "msg": "VM with name <ansible-clone1.dev.test.com> already exists",
                "vmid": 80001
            },
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "invocation": {
                    "module_args": {
                        "acpi": null,
                        "agent": null,
                        "api_host": "10.0.10.1:8006",
                        "api_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                        "api_token_id": null,
                        "api_token_secret": null,
                        "api_user": "ansible_admin@pve",
                        "args": null,
                        "autostart": null,
                        "balloon": null,
                        "bios": null,
                        "boot": null,
                        "bootdisk": null,
                        "cicustom": null,
                        "cipassword": null,
                        "citype": null,
                        "ciuser": null,
                        "clone": "arbitrary_template",
                        "cores": null,
                        "cpu": null,
                        "cpulimit": null,
                        "cpuunits": null,
                        "delete": null,
                        "description": null,
                        "digest": null,
                        "efidisk0": null,
                        "force": null,
                        "format": "raw",
                        "freeze": null,
                        "full": true,
                        "hostpci": null,
                        "hotplug": null,
                        "hugepages": null,
                        "ide": null,
                        "ipconfig": null,
                        "keyboard": null,
                        "kvm": null,
                        "localtime": null,
                        "lock": null,
                        "machine": null,
                        "memory": null,
                        "migrate_downtime": null,
                        "migrate_speed": null,
                        "name": "ansible-clone2.dev.test.com",
                        "nameservers": null,
                        "net": null,
                        "newid": 80002,
                        "node": "proxmox01",
                        "numa": null,
                        "numa_enabled": null,
                        "onboot": null,
                        "ostype": null,
                        "parallel": null,
                        "pool": null,
                        "protection": null,
                        "proxmox_default_behavior": "no_defaults",
                        "reboot": null,
                        "revert": null,
                        "sata": null,
                        "scsi": null,
                        "scsihw": null,
                        "searchdomains": null,
                        "serial": null,
                        "shares": null,
                        "skiplock": null,
                        "smbios": null,
                        "snapname": null,
                        "sockets": null,
                        "sshkeys": null,
                        "startdate": null,
                        "startup": null,
                        "state": "present",
                        "storage": "CEPH-DEV",
                        "tablet": null,
                        "tags": null,
                        "target": null,
                        "tdf": null,
                        "template": null,
                        "timeout": 400,
                        "update": false,
                        "validate_certs": false,
                        "vcpus": null,
                        "vga": null,
                        "virtio": null,
                        "vmid": 987654,
                        "watchdog": null
                    }
                },
                "item": {
                    "key": 80002,
                    "value": {
                        "host_ip_address": "10.10.0.2",
                        "host_name": "ansible-clone2.dev.test.com"
                    }
                },
                "msg": "VM with name <ansible-clone2.dev.test.com> already exists",
                "vmid": 80002
            },
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "invocation": {
                    "module_args": {
                        "acpi": null,
                        "agent": null,
                        "api_host": "10.0.10.1:8006",
                        "api_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                        "api_token_id": null,
                        "api_token_secret": null,
                        "api_user": "ansible_admin@pve",
                        "args": null,
                        "autostart": null,
                        "balloon": null,
                        "bios": null,
                        "boot": null,
                        "bootdisk": null,
                        "cicustom": null,
                        "cipassword": null,
                        "citype": null,
                        "ciuser": null,
                        "clone": "arbitrary_template",
                        "cores": null,
                        "cpu": null,
                        "cpulimit": null,
                        "cpuunits": null,
                        "delete": null,
                        "description": null,
                        "digest": null,
                        "efidisk0": null,
                        "force": null,
                        "format": "raw",
                        "freeze": null,
                        "full": true,
                        "hostpci": null,
                        "hotplug": null,
                        "hugepages": null,
                        "ide": null,
                        "ipconfig": null,
                        "keyboard": null,
                        "kvm": null,
                        "localtime": null,
                        "lock": null,
                        "machine": null,
                        "memory": null,
                        "migrate_downtime": null,
                        "migrate_speed": null,
                        "name": "ansible-clone4.dev.test.com",
                        "nameservers": null,
                        "net": null,
                        "newid": 80004,
                        "node": "proxmox01",
                        "numa": null,
                        "numa_enabled": null,
                        "onboot": null,
                        "ostype": null,
                        "parallel": null,
                        "pool": null,
                        "protection": null,
                        "proxmox_default_behavior": "no_defaults",
                        "reboot": null,
                        "revert": null,
                        "sata": null,
                        "scsi": null,
                        "scsihw": null,
                        "searchdomains": null,
                        "serial": null,
                        "shares": null,
                        "skiplock": null,
                        "smbios": null,
                        "snapname": null,
                        "sockets": null,
                        "sshkeys": null,
                        "startdate": null,
                        "startup": null,
                        "state": "present",
                        "storage": "CEPH-DEV",
                        "tablet": null,
                        "tags": null,
                        "target": null,
                        "tdf": null,
                        "template": null,
                        "timeout": 400,
                        "update": false,
                        "validate_certs": false,
                        "vcpus": null,
                        "vga": null,
                        "virtio": null,
                        "vmid": 987654,
                        "watchdog": null
                    }
                },
                "item": {
                    "key": 80004,
                    "value": {
                        "host_ip_address": "10.10.10.4",
                        "host_name": "ansible-clone4.dev.test.com"
                    }
                },
                "msg": "VM with name <ansible-clone4.dev.test.com> already exists",
                "vmid": 80004
            }
        ],
        "skipped": false
    }
}

解决方案

问题分析

  1. changed状态判断错误:原代码判断的是整个循环任务的provisioning_vm.changed,但需要判断每个子任务结果的item.changed
  2. 字典值缺失:原代码只传入了host_name,需要将包含host_name和host_ip_address的整个item.item.value(或处理后的结构)传入combine

实现方式1:循环生成字典

适合需要对字段做额外处理(比如去掉域名)的场景:

- name: 生成changed状态的VM字典
  set_fact:
    vm_dict: "{{ vm_dict | default({}) | combine( {
        item.item.key: {
          'host_name': item.item.value.host_name.split('.')[0],
          'host_ip_address': item.item.value.host_ip_address
        }
      }) }}"
  loop: "{{ provisioning_vm.results }}"
  when: item.changed

实现方式2:过滤器链式生成(更高效)

利用Ansible过滤器一次性处理,无需循环:

- name: 一次性生成changed状态的VM字典
  set_fact:
    vm_dict: >-
      {% set changed_items = provisioning_vm.results | selectattr('changed', 'equalto', true) | map(attribute='item') %}
      {% set processed = [] %}
      {% for item in changed_items %}
        {% do processed.append({
          'key': item.key,
          'value': {
            'host_name': item.value.host_name.split('.')[0],
            'host_ip_address': item.value.host_ip_address
          }
        }) %}
      {% endfor %}
      {{ processed | items2dict }}

如果不需要去掉域名,直接使用原host_name,可以简化为:

- name: 一次性生成changed状态的VM字典(保留完整域名)
  set_fact:
    vm_dict: "{{ provisioning_vm.results | selectattr('changed', 'true') | map(attribute='item') | items2dict }}"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:46:15