我有一个 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
]
我尝试使用地图和联合收割机,但到目前为止没有任何效果。 有什么想法吗?
字典可能更方便。例如,
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
以防万一人们感兴趣,下面的 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 }}"
这里有一种方法可以通过任务/播放/组变量来使用,并且不涉及使用缓慢的任务循环:
{%- set result = [] %}
{%- for host, hostdata in combined_data.items() %}
{%- set _ = result.append({host: hostdata | json_query('sum([*].disk)')}) %}
{%- endfor %}
{{- result }}
使用 jmespath 来选择和求和磁盘值很有用,因为它还可以确保如果值不存在,也不会出错。