You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible如何从嵌套字典提取各客户的唯一服务器列表?

提取嵌套字典中每个客户的唯一服务器列表(Ansible实现)

需求

从指定的嵌套字典customers中提取每个客户的唯一服务器名称列表,无需考虑集群编号或服务器角色。

给定的嵌套字典

"customers": {
    "customer_1": [
        {
            "c1_cluster_1": [
                {
                    "primary": [
                        "c1_server_1"
                    ]
                },
                {
                    "secondaries": [
                        "c1_server_2",
                        "c1_server_3"
                    ]
                },
                {
                    "tiebreakers": [
                        "c1_server_4",
                        "c1_server_5"
                    ]
                }
            ]
        },
        {
            "c1_cluster_2": [
                {
                    "primary": [
                        "c1_server_1"
                    ]
                },
                {
                    "secondaries": [
                        "c1_server_2",
                        "c1_server_3"
                    ]
                },
                {
                    "tiebreakers": [
                        "c1_server_4",
                        "c1_server_5"
                    ]
                }
            ]
        },
        {
            "c1_cluster_3": [
                {
                    "primary": [
                        "c1_server_1"
                    ]
                },
                {
                    "secondaries": [
                        "c1_server_2",
                        "c1_server_3"
                    ]
                },
                {
                    "tiebreakers": [
                        "c1_server_4",
                        "c1_server_5"
                    ]
                }
            ]
        }
    ],
    "customer_2": [
        {
            "c2_cluster_1": [
                {
                    "primary": [
                        "c2_server_1"
                    ]
                },
                {
                    "secondaries": [
                        "c2_server_2",
                        "c2_server_3"
                    ]
                },
                {
                    "tiebreakers": [
                        "c2_server_4",
                        "c2_server_5"
                    ]
                }
            ]
        },
        {
            "c2_cluster_2": [
                {
                    "primary": [
                        "c2_server_1"
                    ]
                },
                {
                    "secondaries": [
                        "c2_server_2",
                        "c2_server_3"
                    ]
                },
                {
                    "tiebreakers": [
                        "c2_server_4",
                        "c2_server_5"
                    ]
                }
            ]
        }
    ]
}

期望结果

customer_servers:
  customer_1:
    - "c1_server_1"
    - "c1_server_2"
    - "c1_server_3"
    - "c1_server_4"
    - "c1_server_5"
  customer_2:
    - "c2_server_1"
    - "c2_server_2"
    - "c2_server_3"
    - "c2_server_4"
    - "c2_server_5"

已尝试的方法

方法1:Jinja2模板结合set_fact

- name: use Jinja to extract only the customer names and server names from customers 
      ansible.builtin.set_fact:
        cust_servers: |
          {% for cust in customers %}
          {{ cust.key }}:
          {% for serv in cust.value %}
          {% for k, v in serv.items() %}
            - {{v}}
          {% endfor %}
          {% endfor %}
          {% endfor %}
    
    - name: Convert cust_servers to a dictionary 
      ansible.builtin.set_fact:
        cust_servers_dict: "{{cust_servers|from_yaml}}"

方法2:debug模块拆解字典结构

- name: print the customer dictionary component parts
  debug:
    msg:
      - "ClusterName is {{customers[0].key}} and it's value is"
      - "{{customers[0].value}}"
      - " ----------------------------------------------------- "
      - "{{customers[0].value[0].values()}}"

正确解决方案

方案1:使用json_query快速提取(简洁高效)

利用json_query递归提取所有服务器名称,结合flatten和unique去重,最终构建目标字典:

- name: 初始化结果字典
  ansible.builtin.set_fact:
    customer_servers: {}

- name: 提取每个客户的唯一服务器列表
  ansible.builtin.set_fact:
    customer_servers: "{{ customer_servers | combine({ item.key: server_list | unique }) }}"
  loop: "{{ customers | dict2items }}"
  vars:
    # 递归提取当前客户的所有服务器并展平为一维列表
    server_list: "{{ item.value | json_query('[].values()[][].values()') | flatten }}"

方案2:Jinja2嵌套循环提取(直观易懂)

通过多层循环遍历集群、角色,收集所有服务器后去重:

- name: 初始化结果字典
  ansible.builtin.set_fact:
    customer_servers: {}

- name: 遍历每个客户收集服务器
  ansible.builtin.set_fact:
    customer_servers: "{{ customer_servers | combine({ cust_key: servers | unique }) }}"
  loop: "{{ customers | dict2items }}"
  vars:
    cust_key: "{{ item.key }}"
    servers: >-
      {% set server_list = [] %}
      {% for cluster_item in item.value %}
        {% for role_groups in cluster_item.values() | first %}
          {% for server_names in role_groups.values() %}
            {% do server_list.extend(server_names) %}
          {% endfor %}
        {% endfor %}
      {% endfor %}
      {{ server_list }}

两种方案都能得到符合预期的结果,方案1依赖json_query(需要jmespath库,Ansible默认已安装),代码更简洁;方案2纯Jinja2实现,逻辑更直观。

内容的提问来源于stack exchange,提问作者piercjs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:20:23