所有主机的 Ansible 附加字典结果

MBa*_*ith 4 python dictionary python-3.x ansible

我正在尝试使用 Ansible 向多个主机发送返回字典的命令。然后我想附加每个主机的字典结果来累积所有主机的结果。最后,我想打印累积结果的字典以供以后处理或写入文件。由于结果显示为字符串,我似乎无法合并字典。有办法解决这个问题吗?另外,是否有更 Ansible 有效的方法来完成此任务?

示例手册:

---
  - hosts: myhosts
    gather_facts: False
    vars:
      mydict: {}
    tasks:
    - name: Get dict result
      shell: "cat /path/dict_output"
      register: output
    - set_fact:
       result_dict="{{ output.stdout}}"

    - debug: var=result_dict
Run Code Online (Sandbox Code Playgroud)

调试输出:

TASK [debug] ****************************************************************************************************************************************************************
ok: [host-a] => {
    "result_dict": {
        "host_b": [
            {
                "ip-1": {
                    "port": "22", 
                    "service": "ssh"
                }
            }, 
            {
                "ip-2": {
                    "port": "21", 
                    "service": "ftp"
                }
            }
        ]
    }
}
ok: [host-b] => {
    "result_dict": {
        "host_a": [
            {
                "ip-1": {
                    "port": "22", 
                    "service": "ssh"
                }
            }, 
            {
                "ip-2": {
                    "port": "21", 
                    "service": "ftp"
                }
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试合并每个主机的结果:

- set_fact:
   mydict: "{{ mydict | combine(output.stdout) }}"
- debug: var=mydict
Run Code Online (Sandbox Code Playgroud)

失败结果:

TASK [set_fact] *************************************************************************************************************************************************************
    fatal: [host-b]: FAILED! => {"msg": "|combine expects dictionaries, got u\"{'host_b': [{'ip-1': {'service': 'ssh', 'port': '22'}}, {'ip-2': {'service': 'ftp', 'port': '21'}}]}\""}
    fatal: [host-a]: FAILED! => {"msg": "|combine expects dictionaries, got u\"{'host_a': [{'ip-1': {'service': 'ssh', 'port': '22'}}, {'ip-2': {'service': 'ftp', 'port': '21'}}]}\""}
Run Code Online (Sandbox Code Playgroud)

期望输出的累积结果:

{
    "host_a": [
        {
            "ip-1": {
                "port": "22",
                "service": "ssh"
            }
        },
        {
            "ip-2": {
                "port": "21",
                "service": "ftp"
            }
        }
    ],
    "host_b": [
        {
            "ip-1": {
                "port": "22",
                "service": "ssh"
            }
        },
        {
            "ip-2": {
                "port": "21",
                "service": "ftp"
            }
        }
    ]
}

Run Code Online (Sandbox Code Playgroud)

Zei*_*tor 7

收集所有主机上的所有信息后,您可以在本地主机上运行的单个任务中创建该哈希图。

您可以浏览哈希图中任何主机的事实hostvars,并通过 访问组中所有机器的列表groups['name_of_group']

知道这两个信息,基本思想是:

  • 提取您组中机器的所有主机变量,并确保我们从中获得一个列表 =>groups["myhosts"] | map("extract", hostvars)
  • 过滤该结果以删除任何result_dict未定义的项目(例如,如果主机出现故障)。这是通过selectattr过滤器完成的
  • 减少该结果以仅保留result_dict列表中每个元素的键。我们可以再次使用map过滤器map(attribute="result_dict")来做到这一点=> 。我们已经非常接近您正在寻找的内容,它将是一个哈希图列表(每个主机一个元素)。但你正在寻找一个哈希图,所以......
  • 使用combine过滤器将该列表中的词典合并为一个词典。

在您的其他任务应该满足您的要求之后运行以下游戏:

- name: Consolidate and display my result
  hosts: localhost

  vars:
    my_final_map: >-
        {{
          groups["myhosts"]
          | map("extract", hostvars)
          | selectattr("result_dict", "defined") 
          | map(attribute="result_dict")
          | combine
        }}

  tasks:
    - name: Display consolidated result
      debug:
        var: my_final_map
Run Code Online (Sandbox Code Playgroud)