首页 > 解决方案 > 当值匹配时,使用字典内的列表选择嵌套值

问题描述

在字典hostvars[inventory_hostname]中,我多次出现以下内容,库存中的每台服务器都有一个。我需要提取的值proxyServer.detail.name 只有当匹配我可用的proxyServer.datail.inbound_ip变量时。

此外,我的搜索不能proxyServer硬编码,因为有多种类型的服务器,我必须遍历所有这些 - 为了找到我的 IP 地址的匹配项,然后提取相应的“名称”。

                    "proxyServer": {
                        "commonName": "outbound",
                        "proxy.example.com": {
                            "ipaddress": "10.1.100.100"
                        },
                        "detail": [
                            {
                                "inbound_ip": "10.1.100.100",
                                "outbound_ip": "192.168.1.250",
                                "name": "proxy.local"

我尝试了多种变体:

- debug:
  var: "item.key"
  with_dict: "{{ hostvars[inventory_hostname].proxyServer.detail[0] }}"
    when: "'10.1.100.100' in item.value"

但是当有匹配时,我已经“太深”了,无法再提取了name

    "ansible_loop_var": "item",
    "item": {
        "key": "internal_ip",
        "value": "10.1.100.100"
    },
    "item.key": "internal_ip"
}

我的方法也不会扩展,因为我是硬编码的detail,所以它只会匹配一个单一的字典,而不是数据中的其他任何东西。

欢迎任何指点,谢谢您的时间。

标签: ansible

解决方案


使用json_query。例如,下面的任务将为您提供选定的“proxyServer”变量列表,其中“inbound_ip”为“10.1.100.100”

    - set_fact:
        proxyServer_selected: "{{ ansible_play_hosts_all|
               map('extract', hostvars, 'proxyServer')|list|
               json_query(query) }}"
      vars:
        inbound_ip: "10.1.100.100"
        query: "[?detail[?inbound_ip == '{{ inbound_ip }}']]"
      run_once: true

然后,处理列表并提取您想要的内容。


问:这不取决于我必须在'proxyServer'值中编码吗?

答:不。它没有。可以迭代值并连接结果列表。例如

    - set_fact:
        vars_selected: "{{ vars_selected|default([]) +
                           [ansible_play_hosts_all|
                           map('extract', hostvars, item)|list|
                           json_query(query)] }}"
      vars:
        inbound_ip: "10.1.100.100"
        query: "[?detail[?inbound_ip == '{{ inbound_ip }}']]"
      run_once: true
      loop:
        - proxyServer

推荐阅读