python - Ansible:使用原始字典中的重复值构建反向字典
问题描述
我有一个看起来像这样的Ansible
字典事实:vm_templates
{
"HostedEngine": "00000000-0000-0000-0000-000000000000",
"cpu-node0": "2d826ed8-1dbe-4b10-93a1-5ac9734462cb",
"cpu-node1": "2d826ed8-1dbe-4b10-93a1-5ac9734462cb",
"cpu-node2": "2d826ed8-1dbe-4b10-93a1-5ac9734462cb",
"cpu-node3": "2d826ed8-1dbe-4b10-93a1-5ac9734462cb",
"fp_gpu-node0": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node1": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node10": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node11": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node2": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node3": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node4": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node5": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node6": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node7": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node8": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"fp_gpu-node9": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node0": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node1": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node2": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node3": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node4": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node5": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node6": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"hp_gpu-node7": "a08901c0-50a5-4e2f-b6d7-b11b69a32613",
"infra-vm": "00000000-0000-0000-0000-000000000000"
}
我想从上面构建一个翻转字典,考虑到具有重复值的键。因此,我想将第一个字典中的每个值与其在列表中的键相关联,并且旧字典中具有重复值的键将位于相同的列表值中。
这是我试图得到的结果,使用ansible
:
{
"00000000-0000-0000-0000-000000000000": ["HostedEngine", "infra-vm"],
"2d826ed8-1dbe-4b10-93a1-5ac9734462cb": ["cpu-node0", "cpu-node1", "cpu-node2", "cpu-node3"],
"a08901c0-50a5-4e2f-b6d7-b11b69a32613": ["fp_gpu-node0", "fp_gpu-node1", "fp_gpu-node10", "fp_gpu-node11", "fp_gpu-node2", "fp_gpu-node3", "fp_gpu-node4", "fp_gpu-node5", "fp_gpu-node6", "fp_gpu-node7", "fp_gpu-node8", "fp_gpu-node9", "hp_gpu-node0", "hp_gpu-node1", "hp_gpu-node2", "hp_gpu-node3", "hp_gpu-node4", "hp_gpu-node5", "hp_gpu-node6", "hp_gpu-node7"]
}
在 python 中,我会写一些类似的东西:
reverse_templates = {}
for key, value in vm_template.items():
if value not in reverse_templates:
reverse_templates[value] = [key]
else:
reverse_templates[value].append(key)
这是我尝试过的ansible
,但不起作用:
- name: "Associate each template with related VMs list"
set_fact:
reverse_templates: "{{reverse_templates|default({})|combine({item.value:{% if item.value not in reverse_teplates %}value[item.key]{% else %}reverse_templates[item.value] + [item.key]{% endif %}})}}"
loop: "{{lookup('dict', vm_templates)}}"
这是错误:
任务 [将每个模板与相关 VM 列表关联] **************************************** ****************************************************** ****************************************************** *********** 致命:[本地主机]:失败!=> {"msg": "模板错误,同时模板字符串:意外'%'。字符串:{{reverse_templates|default({})|combine({item.value:{% if item.value not in reverse_teplates %}value [item.key]{% else %}reverse_templates[item.value] + [item.key]{% endif %}})}}"}
有什么好的方法可以到达那里Ansible
吗?
解决方案
下面的任务完成了这项工作
- set_fact:
reverse_templates: "{{ reverse_templates|default([]) +
[{item: vm_templates|
dict2items|
selectattr('value', 'eq', item)|
map(attribute='key')|
list}] }}"
loop: "{{ vm_templates.values()|unique|list }}"
- debug:
var: reverse_templates
给
reverse_templates:
- a08901c0-50a5-4e2f-b6d7-b11b69a32613:
- fp_gpu-node0
- fp_gpu-node1
- fp_gpu-node10
- fp_gpu-node11
- fp_gpu-node2
- fp_gpu-node3
- fp_gpu-node4
- fp_gpu-node5
- fp_gpu-node6
- fp_gpu-node7
- fp_gpu-node8
- fp_gpu-node9
- hp_gpu-node0
- hp_gpu-node1
- hp_gpu-node2
- hp_gpu-node3
- hp_gpu-node4
- hp_gpu-node5
- hp_gpu-node6
- hp_gpu-node7
- 00000000-0000-0000-0000-000000000000:
- HostedEngine
- infra-vm
- 2d826ed8-1dbe-4b10-93a1-5ac9734462cb:
- cpu-node0
- cpu-node1
- cpu-node2
- cpu-node3
Ansible 代码类似于 Python
for key in set(vm_templates.values()):
reverse_templates[key] = [k for k,v in vm_templates.items() if v == key]
print(reverse_templates)
下面的任务产生相同的结果
- set_fact:
reverse_templates: "{{ reverse_templates|default([]) +
[{item: vm_templates|
dict2items|
json_query(query)}] }}"
loop: "{{ vm_templates.values()|unique|list }}"
vars:
query: "[?value == '{{ item }}'].key"