繁体   English   中英

合并 Ansible 中具有相同键的字典

[英]merge dictionaries in Ansible that have the same keys

我再次尝试用 Ansible 完成一些事情。

我为每个看起来像这样的服务器构建了一个带有变量的自定义字典。

- name: Create and Add items to server_list
  set_fact: 
    server_list: "{{ server_list | default({}) | combine ({ item.key : item.value }) }}"
  with_items:
    - { 'key': 'Servername' , 'value': "{{ ansible_hostname }}"}
    - { 'key': 'IP-Adresse' , 'value': "{{ ansible_default_ipv4.address }}"}
    - { 'key': 'OS' , 'value': "{{ ansible_os_family }} {{ ansible_distribution_major_version }}"}
    - { 'key': 'Plattform' , 'value': "{{ ansible_system }}"}

- name: DEBUG server_list
  debug:
    var=server_list

那行得通。 但是现在 ansible 为每个服务器输出这个,如下所示:

ok: [XXX] => {
    "server_list": {
        "IP-Adresse": "x.x.x.x",
        "OS": "Debian 11",
        "Plattform": "Linux",
        "Servername": "XXX"
    }
}
ok: [YYY] => {
    "server_list": {
        "IP-Adresse": "x.x.x.y",
        "OS": "Debian 11",
        "Plattform": "Linux",
        "Servername": "YYY"
    }
}

...

我现在想要的是每个服务器都有一个完整的“全局”字典。 我认为这看起来像这样。 我想要的示例为 output (此处命名为server_list_dict ):

{
    "server_list_dict": {
        "0": {
            "Servername": "XXX",
            "IP-Adresse": "x.x.x.x",
            "OS": "Debian 11",
            "Plattform": "Linux"
        },
        "1": {
            "Servername": "YYY",
            "IP-Adresse": "x.x.x.y",
            "OS": "Debian 11",
            "Plattform": "Linux"
        }
    }
}

仅用于澄清我想要实现的目标

我稍后要做的是创建一个 html 表,它应该 output 是这样的。 我要创建的示例 html:

<table style="width:50%">
    <!-- table header -->
    <tr>
        <th>Servername</th>
        <th>IP</th>
        <th>OS</th>
        <th>Platform</th>
    </tr>  
    <!-- table rows -->
    <tr>
        <td>Hostname1</td>
        <td>X.X.X.X</td>
        <td>Debian</td>
        <td>Linux</td>
    </tr>
    <tr>
        <td>Hostname2</td>
        <td>X.X.X.Y</td>
        <td>Debian</td>
        <td>Linux</td>
    </tr>
</table>

我已经有一个模板可以使用。 这将 go 通过我的“全局”字典与每个服务器一起使用,并使用其中的所有键和值。 (希望,无法测试它,因为 idk 如何合并我的听写)

<table style="width:100%">
  <!-- table header -->
  {% if server_list_dict %}
  <tr>
     {% for key in server_list_dict[0] %}
     <th> {{ key }} </th>
     {% endfor %}
  </tr>
  {% endif %}

  <!-- table rows -->
  {% for dict_item in server_list_dict %}
  <tr>
     {% for value in dict_item.values() %}
     <td> {{ value }} </td>
     {% endfor %}
  </tr>
  {% endfor %}
</table>

有人知道如何在完整的字典中合并具有相同键的字典吗? 我找不到任何有用的东西。 提前谢谢大家!

提取变量server_list的列表

server_lsts: "{{ ansible_play_hosts|
                 map('extract', hostvars, 'server_list')|list }}"

server_lsts:
  - IP-Adresse: x.x.x.x
    OS: Debian 11
    Plattform: Linux
    Servername: XXX
  - IP-Adresse: x.x.x.y
    OS: Debian 11
    Plattform: Linux
    Servername: YYY

并创建字典

server_dict: "{{ dict(ansible_play_hosts|zip(server_lsts)) }}"

server_dict:
  XXX:
    IP-Adresse: x.x.x.x
    OS: Debian 11
    Plattform: Linux
    Servername: XXX
  YYY:
    IP-Adresse: x.x.x.y
    OS: Debian 11
    Plattform: Linux
    Servername: YYY

  • 完整剧本示例
- hosts: all vars: server_lsts: "{{ ansible_play_hosts| map('extract', hostvars, 'server_list')|list }}" server_dict: "{{ dict(ansible_play_hosts|zip(server_lsts)) }}" tasks: - debug: var: server_dict run_once: true
  • 将字典的声明放入group_vars 例如
shell> cat group_vars/all.yml server_list: Servername: "{{ ansible_hostname }}" IP-Adresses: "{{ ansible_all_ipv4_addresses }}" OS: "{{ ansible_os_family }} {{ ansible_distribution_major_version }}" Plattform: "{{ ansible_system }}"

剧本

- hosts: test_11:test_12 vars: server_lsts: "{{ ansible_play_hosts| map('extract', hostvars, 'server_list')|list }}" server_dict: "{{ dict(ansible_play_hosts|zip(server_lsts)) }}" tasks: - debug: var: server_dict run_once: true

server_dict: test_11: IP-Adresses: - 10.1.0.61 OS: FreeBSD 13 Plattform: FreeBSD Servername: test_11 test_12: IP-Adresses: - 10.1.0.62 OS: FreeBSD 13 Plattform: FreeBSD Servername: test_12
  • 如果要索引字典,请创建序列。 例如
shell> cat pb.yml - hosts: test_11:test_12 vars: server_lsts: "{{ ansible_play_hosts| map('extract', hostvars, 'server_list')|list }}" params: "start=0 count={{ ansible_play_hosts|length }}" server_dict: "{{ dict(q('sequence', params)|zip(server_lsts)) }}" tasks: - debug: var: server_dict run_once: true

server_dict: '0': IP-Adresses: - 10.1.0.61 OS: FreeBSD 13 Plattform: FreeBSD Servername: test_11 '1': IP-Adresses: - 10.1.0.62 OS: FreeBSD 13 Plattform: FreeBSD Servername: test_12

... Ansible 为每个服务器输出这个...我现在有多个 dicts (由于set_fact ,每个服务器都有)...

这是因为gather_facts模块 - 收集有关远程主机的事实set_fact模块 - 设置主机变量和事实在远程节点和预期行为上分布运行。

我现在想要的是每个服务器都有一个完整的“全局”字典。

我了解您的问题,您希望首先将事实委托给其中一个主机,即控制节点(部署主机或本地主机),您可以在其中创建文件或使用模板进行进一步分发。 在那里,所有信息都将聚合在一个数据结构(字典)中。

另一种方法可能是通过缓存插件使用缓存事实

文档

您可以按预期直接使用 jinja 创建您的 var:

  tasks:
    - name: Create and Add items to server_list
      set_fact: 
        server_list: >- 
              {%- set result = {} -%}
              {%- for server in ansible_play_hosts -%}
              {%- set idx = loop.index0 -%}
              {%- set name = hostvars[server].ansible_hostname -%}
              {%- set ip = hostvars[server].ansible_default_ipv4.address -%}
              {%- set os = hostvars[server].ansible_os_family -%}
              {%- set pf = hostvars[server].ansible_system -%}
              {%- set _= result.update({idx:{"Servername": name, "IP": ip, "OS": os, "Platform": pf} }) -%}
              {%- endfor -%}
              {{ result }}
      
    - debug:
        msg: "{{server_list}}" 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM