所有主机的Ansible追加dict结果

2024-05-12 19:18:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用Ansible向多个主机发送一个返回dict的命令。然后,我想将每个主机的dict结果附加起来,以累加所有主机的结果。最后,我想打印累积结果的dict,以便以后处理或写入文件。由于结果显示为字符串,我似乎无法合并dicts。有办法补救吗?还有,有没有更可靠有效的方法来实现这一点?你知道吗

示例剧本:

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

调试输出:

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

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

- set_fact:
   mydict: "{{ mydict | combine(output.stdout) }}"
- debug: var=mydict

失败结果:

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'}}]}\""}

累积结果的期望输出:

{'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'}}]}

Tags: debugiphostoutputportservicestdoutftp
1条回答
网友
1楼 · 发布于 2024-05-12 19:18:45

在收集了所有主机上的所有信息之后,可以在localhost上运行的单个任务中创建hashmap。你知道吗

您可以在hostvarshashmap中浏览来自任何主机的事实,并通过'groups['name\u of \u group']访问组中所有计算机的列表。你知道吗

了解这两个信息,基本思路是:

  • Extract组中计算机的所有hostvars,并确保从中得到一个列表=>;groups["myhosts"] | map("extract", hostvars) | list
  • 筛选该结果以仅保留result_dict。我们可以通过^{}=>;json_query("[].result_dict")来实现。我们已经非常接近你要找的东西了,它将是一个hashmaps列表(每个主机一个元素)。但是您正在寻找一个hashmap,所以。。。。你知道吗
  • 循环此结果以创建单个hashmap,其中每个主机都有一个条目。你知道吗

在执行其他任务之后运行的以下播放应满足您的要求:

- name: consolidate and display my result
  hosts: localhost

  tasks:
    - name: Consolidate result in a single hashmap
      set_fact:
        my_final_map: "{{ my_final_map | default({}) | combine(item) }}"
      loop: >-
        {{
          groups["myhosts"]
          | map("extract", hostvars)
          | list
          | json_query("[].result_dict")
        }}

    - name: Display consolidated result
      debug:
        var: my_final_map

注释后注意:如果使用json_query是一个问题,在这种情况下它不是绝对强制的。我们可以再select the needed attribute with ^{}。基本相同,这是修改后的任务:

    - name: Consolidate result in a single hashmap
      set_fact:
        my_final_map: "{{ my_final_map | default({}) | combine(item) }}"
      loop: >-
        {{
          groups["myhosts"]
          | map("extract", hostvars)
          | map(attribute="result_dict")
          | list
        }}

相关问题 更多 >