使用 Ansible 创建字典过滤不同值的列表

Create list of dict filtering different value with Ansible

我正在寻找一个更好的解决方案来通过键 A 和 return 键 B 的值列表来过滤字典列表。更具体地说 - 每个主机都有一个字典:

infrastructure:
  name: "x..."
network:
  address: "1..."

存在定义了 network.address 的主机,也存在未定义 network.address 的主机。我现在需要一个所有 infrastructure.name 定义为 network.address.

的列表
- name: "Define Alias fact"
  set_fact:
    alias: []

- name: "Add Aliases for all hosts with network.address is defined"
  set_fact:
    alias: "{{ alias + [hostvars[host].infrastructure.name + '-alias'] }}"
  when:
    - "hostvars[host].network is defined"
    - "hostvars[host].network.address is defined"
  with_items: "{{ groups['all'] }}"
  loop_control:
    loop_var: host

可行,但有点乱,因为我多次调用 set_fact 并将项目添加到列表中。

当我看的时候:

- name: "Define addresses fact"
  set_fact:
    address: "{{ groups['all'] | map('extract', hostvars) | list | json_query('[*].network.address') }}"

这个要短得多,也许更容易。

我想问一下,在展平列表以“过滤掉”network.address 未定义并使用 json_query 和一些字符串操作来附加“-alias”。有没有类似的简单方法来替换第一个脚本?

以纯 JMESPath 方式,给定 JSON

[
  {
    "infrastructure": {"name": "x..."},
    "network": {"address": "1..."}
  },
  {
    "infrastructure": {"name": "y..."}
  },
  {
    "infrastructure": {"name": "z..."},
    "network": {"address": "2..."}
  },
  {
    "infrastructure": {"name": "a..."},
    "network": {}
  }
]

您可以提取与 -alias 连接的 infrastructure.name,并以这种方式设置 network.address

[?network.address].join('-', [infrastructure.name, 'alias'])

这将产生:

[
  "x...-alias",
  "z...-alias"
]

函数join主要用于将数组元素粘合在一起,但也可用于连接字符串。


因此,对于演示这一点的剧本:

- hosts: all
  gather_facts: no
      
  tasks:
    - debug: 
        msg: >-
          {{ 
            servers | to_json | from_json | 
            json_query(
              '[?network.address].join(`-`, [infrastructure.name, `alias`])'
            ) 
          }}
      vars:
        servers:
          - infrastructure:
              name: x...
            network:
              address: 1...
          - infrastructure:
              name: y...
          - infrastructure:
              name: z...
            network:
              address: 2...
          - infrastructure:
              name: a...
            network:

注意奇数构造| from_json | to_json的解释

这产生:

PLAY [all] ********************************************************************************************************

TASK [debug] ******************************************************************************************************
ok: [localhost] => {
    "msg": [
        "x...-alias",
        "z...-alias"
    ]
}

PLAY RECAP ********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0