在 Ansible 中对字典中的键求和并组合

问题描述 投票:0回答:3

我有一个 Ansible 事实(它可能有很多虚拟机管理程序):

"combined_data": {
    "hypervisor-01": [
        {
            "disk": 150,
            "id": "okd-service-01"
        },
        {
            "disk": 25,
            "id": "okd-master-02"
        },
        {
            "disk": 25,
            "id": "okd-master-01"
        }
    ],
    "hypervisor-02": [
        {
            "disk": 20,
            "id": "okd-bootstrap-01"
        },
        {
            "disk": 30,
            "id": "okd-worker-01"
        },
        {
            "disk": 25,
            "id": "okd-master-03"
        }
    ]
}

我需要创建另一个事实,数据总结如下:

"result": [
    "hypervisor-01": 200,
    "hypervisor-02": 75
]

我尝试使用地图和联合收割机,但到目前为止没有任何效果。 有什么想法吗?

ansible jinja2
3个回答
0
投票

字典可能更方便。例如,

  cd_keys: "{{ combined_data.keys()|list }}"
  cd_vals: "{{ combined_data.values()|map('sum', attribute='disk')|list }}"
  result: "{{ dict(cd_keys|zip(cd_vals)) }}"

给予

  result:
    hypervisor-01: 200
    hypervisor-02: 75

您可以选择使用json_query。下面的声明给出了相同的结果

  cd_query2: '[].[key, sum(value[].disk)]'
  result: "{{ dict(combined_data|dict2items|json_query(cd_query2)) }}"

如果您想获取列表,请使用 community.general.dict。例如,

  cd_query3: '[].[[key, sum(value[].disk)]]'                                                
  result: "{{ combined_data|dict2items|json_query(cd_query3)|                              
              map('community.general.dict') }}"

给予

  result:
  - hypervisor-01: 200
  - hypervisor-02: 75

用于测试的完整剧本示例

- hosts: all

  vars:

    combined_data:
      hypervisor-01:
        - {disk: 150, id: okd-service-01}
        - {disk: 25, id: okd-master-02}
        - {disk: 25, id: okd-master-01}
      hypervisor-02:
        - {disk: 20, id: okd-bootstrap-01}
        - {disk: 30, id: okd-worker-01}
        - {disk: 25, id: okd-master-03}

    cd_keys: "{{ combined_data.keys()|list }}"
    cd_vals: "{{ combined_data.values()|map('sum', attribute='disk')|list }}"
    result1: "{{ dict(cd_keys|zip(cd_vals)) }}"

    cd_query2: '[].[key, sum(value[].disk)]'
    result2: "{{ dict(combined_data|dict2items|json_query(cd_query2)) }}"

    cd_query3: '[].[[key, sum(value[].disk)]]'
    result3: "{{ combined_data|dict2items|json_query(cd_query3)|
                 map('community.general.dict') }}"

  tasks:

     - debug:
         var: result1
     - debug:
         var: result2
     - debug:
         var: result3

0
投票

以防万一人们感兴趣,下面的 set_fact 就可以了:

- set_fact:
    data_sum: "{{ data_sum|default([]) + [{item: my_attribute}] }}"
  vars:
    my_attribute: "{{ kubeinit_validations_libvirt_combined_disk_usage[item] | map(attribute='disk') | list | sum }}"
  with_items: "{{ kubeinit_validations_libvirt_combined_disk_usage.keys() | list }}"

0
投票

这里有一种方法可以通过任务/播放/组变量来使用,并且不涉及使用缓慢的任务循环:

{%- set result = [] %}
{%- for host, hostdata in combined_data.items() %}
{%- set _ = result.append({host: hostdata | json_query('sum([*].disk)')}) %}
{%- endfor %}
{{- result }}

使用 jmespath 来选择和求和磁盘值很有用,因为它还可以确保如果值不存在,也不会出错。

© www.soinside.com 2019 - 2024. All rights reserved.