首页 > 解决方案 > 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吗?

标签: pythondictionaryansible

解决方案


下面的任务完成了这项工作

    - 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)

json_query

下面的任务产生相同的结果

    - 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"

推荐阅读