所有主机的AnsApp append dict结果 [英] Ansible append dict results for all hosts

查看:75
本文介绍了所有主机的AnsApp append dict结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Ansible将命令发送到几个返回dict的主机.然后,我想附加每个主机的dict结果以累积所有主机的结果.最后,我想打印累积结果的字典以供以后处理或写入文件.由于结果显示为字符串,因此我似乎无法合并这些字典.有没有办法解决这个问题?另外,有没有一种更有效的Ansible方法来实现这一目标?

I am attempting to use Ansible to send a command to several hosts that returns a dict. I then want to append the the dict results of each host to accumulate the results of all the hosts. Finally, I want to print the dict of accumulated results for later processing or to write to a file. It appears I am failing to combine the dicts due to results showing as string. Is there a way to remedy this? Also, is there a more Ansible efficient way to accomplish this?

剧本示例:

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

推荐答案

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

You can create that hashmap in a single task running on localhost after you gathered all the info on all the hosts.

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

You can browse facts from any hosts in the hostvars hashmap, and access a list of all machines in a group through groups['name_of_group'].

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

Knowing those 2 info, the basic idea is:

  • 提取所有主机变量为您组中的机器,并确保我们从=>中获得列表. groups ["myhosts"] |map("extract",hostvars)|列表
  • 过滤结果以仅保留 result_dict .我们可以使用 map 过滤器再次=> map(attribute ="result_dict").我们已经非常接近您要寻找的内容,它将是哈希表的列表(每个主机一个元素).但是您正在寻找一个哈希表,所以...
  • 根据此结果创建一个单独的哈希图,并为每个主机添加一个条目.
  • Extract all hostvars for the machines in your group and make sure we get a list out of that => groups["myhosts"] | map("extract", hostvars) | list
  • Filter that result to retain only the result_dict. We can do this using the map filter again => map(attribute="result_dict"). We are already very close to what your are looking for, it will be a list of hashmaps (one element for each host). But you are looking for a single hashmap, so....
  • Loop on this result to create a single hashmap with an entry for each host.

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

The following play ran after your other tasks should meet your requirements:

- 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)
          | map(attribute="result_dict")
          | list
        }}

    - name: Display consolidated result
      debug:
        var: my_final_map

注释后的注释:如果组中有一些主机没有运行任务(因为它们不可达或由于其他原因),则可以排除具有未定义 result_dict <的主机/code>使用 selectattr 过滤器

Note after comment: If you have some host in the group that did not run the task (because they were unreachable or for other reasons), you can exclude hosts with undefined result_dict using the selectattr filter

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

这篇关于所有主机的AnsApp append dict结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆