Создайте список фильтрации различных значений dict с помощью Ansible

Я ищу лучшее решение для фильтрации списка диктов по ключу A и возврата списка значений ключа B. Чтобы быть более конкретным - у каждого хоста есть dict:

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') }}"

Это намного короче, может быть, проще.

Я хотел бы спросить, могу ли я использовать map и extract и «список диктов», прежде чем сгладить список, чтобы «отфильтровать» все элементы, где network.address не определен, и использовать json_query вместе с некоторой строковой операцией для добавления '-псевдоним'. Есть ли аналогичный простой способ заменить первый скрипт?

Введение в Ansible Roles
Введение в Ansible Roles
Ansible - это отличный инструмент управления конфигурацией, который можно использовать для автоматизации настройки или развертывания на большом...
2
0
222
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В чистом виде JMESPath, учитывая JSON

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

Вы можете извлечь infrastructure.name, объединенный с -alias, с установленным network.address следующим образом:

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

Это даст:

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

Функция join в первую очередь предназначена для склеивания элементов массива, но ее также можно использовать для конкатенации строк.


И так для playbook, демонстрирующего это:

- 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:

Note that the odd construct | from_json | to_json is explained in this other answer

Это дает:

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   

В моем случае «серверный» dict является частью hostvars, и, похоже, мне не нужно фильтровать | to_json | from_json, но он работает, как и ожидалось.

TRW 14.12.2020 16:46

Ах, да, действительно, это проблема с данными YAML / Ansible, если у вас есть это как факт из предыдущей задачи / хоста, то вам должно быть хорошо без этого.

β.εηοιτ.βε 14.12.2020 19:23

Другие вопросы по теме