Можно ли заполнить список значений в defaults/main.yml для Ansible?

Вопрос или проблема

Имея пользовательские структуры данных инвентаря и входные аргументы роли, я хочу заполнить эти входные аргументы из структур данных инвентаря. Можно ли как-то заполнить список в цикле?

Например, это структура инвентаря:

---
install_disk:
  vtbd0:
    scheme: GPT
    target: bsdinstall
    partitions:
      1:
        size: 512k
        type: freebsd-boot
        gptlabel: CSMBOOT
      2:
        size: 55m
        type: efi
        gptlabel: EFIBOOT
        fslabel: efiprtn
      3:
        size: 3g
        type: freebsd-ufs
        gptlabel: UFSBOOT
        fslabel: ufsprtn
      4:
        type: freebsd-zfs
        gptlabel: ZFSMAIN
        poolname: zpool
        ashift: 12
        swapsize: 6G
        mountdir: /tmp/newbsd
        geli:
          algo: AES-XTS
          length: 256
          sector: 4096
          keyfile: zpool.key
          keydir: geli
          keypath: /usr/local
          keycount: 3

И вот как я создаю первый элемент списка:

---
target_dsk:
  dev_name: "{{ install_disk.keys() | first }}"
  prt_scheme: "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','scheme') | map(attribute="value") | first }}"
  prt_list:
    - index:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute="value") | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute="key") | first }}"
      type: "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute="value") | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute="value.type") | first }}"
      gptlabel:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute="value") | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute="value.gptlabel") | first }}"
      size:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute="value") | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute="value.size") | first }}"

Может быть, кто-то сможет предложить более оптимальное понимание списка? Насколько я вижу, мои не самые оптимальные.

В любом случае, я хочу знать, можно ли заполнять элементы списка в цикле или каким-то образом, чтобы не жестко задавать количество элементов списка в defaults/main.yml?

Ответ или решение

Возможность автоматически заполнять список значений в Ansible через файл defaults/main.yml является актуальной задачей для автоматизации и упрощения управления конфигурацией. В особенности, если рассматриваем необходимость извлечения и обработки данных из кастомных структур инвентаря для роли Ansible.

Возможности и ограничения Ansible для динамического заполнения списков

В Ansible основная функция по управлению переменными заключается в использовании файлов, таких как defaults/main.yml. Однако, Ansible не поддерживает прямое выполнение циклов внутри YAML-файлов по аналогии с циклом for в традиционных языках программирования. Тем не менее, динамическое заполнение возможно с использованием комбинации фильтров и модулей Ansible.

Динамическое формирование списка — подход

Чтобы динамически формировать список на основании структуры данных инвентаря, можно воспользоваться механизмами loop, with_items и фильтрами Jinja2 в задах Ansible. Вместо попытки наполнения списка в defaults/main.yml, будет разумнее использовать playbooks и tasks для достижения необходимых целей.

---
- name: Формирование списка разделов
  hosts: all
  tasks:
    - name: Извлечение устройств из инвентаря
      set_fact:
        install_disks: "{{ install_disk | dict2items }}"

    - name: Итерация по разделам
      set_fact:
        partitions: "{{ partitions | default([]) + [{
          'index': item.value.partitions | dict2items,
          'scheme': item.value.scheme
        }] }}"
      loop: "{{ install_disks }}"

Оптимизация выборок из структуры инвентаря

Для улучшения читаемости и поддержки кода вы можете использовать несколько вспомогательных фильтров. Например, фильтр dict2items позволяет преобразовать словарь в список, что упрощает его итерацию. Кроме того, использование фильтров selectattr и map позволяет точно извлекать нужные данные.

Зачем избегать жесткого кодирования в defaults/main.yml?

Отказ от жесткого кодирования позволяет:

  1. Упростить поддержку и расширяемость конфигурации.
  2. Уменьшить риски, связанные с человеческими ошибками.
  3. Позволяет переиспользование логики для других дисков или структур данных.

Заключение

Заполнение списка значений в Ansible возможно, но требует работы с фактическими задачами в playbook или включения logics в handler’ах и task’ах, а не в defaults/main.yml. Это позволяет сохранить структуру кода более универсальной и легкой для адаптации к изменяющимся требованиям.

Используя подходы, описанные выше, можно достичь эффективной автоматизации конфигураций с использованием Ansible и сохранить ясность в структурах данных.

Оцените материал
Добавить комментарий

Капча загружается...