Ansible playbook – объединение переменных в условии

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

У меня есть рабочая задача по миграции (копированию) определенной части моего домашнего каталога (вторая с конца строка является важной):

- name: "Миграция файлов домашнего каталога модуля my-pc"
  copy:
    src: "{{ migration_source_path }}{{ item }}"
    dest: "{{ migration_destination_path }}{{ item }}"
  loop: "{{ migration_paths_my_pc }}"
  when:
    - not is_migrating_all
    - "'{{ migration_source_path }}{{ item }}' существует"
    - m_my_pc | bool

Обе переменные ..._path всегда заканчиваются на косую черту (/).

Объяснение: Это берет список путей к файлам из migration_paths_my_pc и копирует их из migration_source_path в migration_destination_path). Это случится только если: флаг для этого модуля установлен (m_my_pc); и путь существует в исходном каталоге; и я не мигрирую все файлы из домашнего каталога в любом случае (is_migrating_all).

Мое текущее рабочее решение (выше) дает мне предупреждение:

[WARNING]: условные операторы не должны включать в себя разделители шаблона jinja2, такие как {{ }} или {% %}. Обнаружено: '{{ migration_source_path }}{{ item }}' существует

Я понимаю, что мне нужно убрать фигурные скобки {{ из секции when:, так как условные выражения имеют встроенные фигурные скобки вокруг них. Проблема в том, что я не могу понять, как заставить это работать. Несколько моих неудачных попыток:

    - vars["" + migrate_source_path + item] существует
    - vars[migrate_source_path + item] существует
    - vars[migrate_source_path ~ item] существует
    - vars[migrate_source_path]vars[item] существует
    - '' + migrate_source_path + item существует
    - lookup('/home/k/test/test2/' + item) существует
    - "{{ lookup('vars', 'migrate_source_path' + 'item') существует }}"
    - "{{ lookup('vars', 'migrate_source_path') + lookup('vars', 'item') существует }}"
    - lookup('vars', 'migrate_source_path')lookup('vars', 'item') существует

Предыстория:

Я автоматизирую настройки персональных ПК как по практическим причинам, так и чтобы лучше изучить Ansible и Ansible-playbooks.

Любые другие рекомендации или советы также приветствуются (в комментариях, думаю).

ОБНОВЛЕНИЕ:

Мои цель (функциональные стремления) для миграции заключаются в следующем:

  • Я хочу, чтобы стоимость поддержки была низкой, но хотел бы, чтобы при необходимости была доступна информация о том, какие пути были скопированы и какие были пропущены. Поэтому я подумал, что скрипт должен копировать пути, которые существуют в источнике, не останавливаясь и не выдавая ошибку в случае отсутствия пути в источнике. Предупреждения или другие простые сообщения были бы отличны. Мой текущий скрипт делает это приемлемо.
  • Было бы неплохо иметь возможность легко переключать, какие пути будут копироваться, а какие нет (например, что-то может измениться в отношении миграции). Делать это в project/vars/ показалось интуитивным и, следовательно, возможно, лучшим дизайном, чем переключение их внутри задачи. Другие переменные, которые более вероятно будут отключены или изменены, находятся в project/vars/. Комментировать что-то, то есть раскомментировать, это одна горячая клавиша обычно в продвинутых текстовых редакторах и IDE. Поэтому это довольно удобно.

Ваши попытки излишне усложнены. Разделители Jinja не должны использоваться в условиях, так как вы уже находитесь в чем-то, что интерпретируется как выражение Jinja, поэтому их просто нужно заменить чем-то, что дает желаемый результат.

В этом случае вы создаете строку, которая является конкатенацией двух переменных, поэтому вы должны заменить это на конкатенацию:

    - (migration_source_path ~ item) существует

Вы использовали как migrate_source_path, так и migration_source_path в своих примерах, поэтому я произвольно выбрал migration_source_path как правильный.

Вы были довольно близки с:

    - '' + migration_source_path + item существует

но у вас есть ненужная ведущая пустая строка, которую YAML-парсер не приемлет, и как только вы исправите это, правильно закомментировав или удалив ненужную строку:

    - "'' + migration_source_path + item существует"
    - migration_source_path + item существует

это попытается добавить migration_source_path и item существует, так как вы не использовали скобки для корректировки порядка.

Попробуйте переписать это немного по-другому. Вместо того, чтобы проходить по массиву с помощью loop, укажите директории, которые вы хотите копировать, с with или with_fileglob. Если вам действительно нужно иметь список файлов, которые вы хотите копировать из одного местоположения в другое, вы можете записать список в секцию with. Модуль проверит, существует ли исходный файл, и отобразит ошибку, что в этом случае хорошо, так как иначе ваша миграция будет некорректной.

Помните, что мы используем when, чтобы сказать Ansible, когда запускать или не запускать какую-то задачу, а не чтобы управлять задачей или её поведением. Для этого мы используем обработчики, регистры и другие ресурсы.

С уважением.

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

Для решения задачи о написании playbook для Ansible, в котором необходимо выполнить условную конкатенацию переменных без использования фигурных скобок Jinja, следует понимать, как Ansible трактует выражения «when» и как правильно использовать синтаксис Jinja внутри них.

Теория (Theory)

Ansible использует язык шаблонов Jinja2, который позволяет динамически формировать данные и логику внутри playbook’ов. Однако, когда дело касается условий, Ansible не требует явного использования фигурных скобок {{ }}, так как всё, что находится внутри блока when, уже является выражением Jinja2. Таким образом, фигурные скобки становятся избыточными и могут привести к ошибкам или предупреждениям, как в вашем случае.

Важно также учитывать, что Ansible поддерживает оператор конкатенации строк ~’, который следует использовать для объединения переменных в один путь. Это особенно важно, когда ваша цель — создание динамических строк на основе нескольких переменных, как это происходит с переменными путейmigration_source_pathиitem`.

Пример (Example)

Рассмотрим ваш исходный код и внесём необходимые исправления, чтобы избежать ненужных предупреждений. Мы заменим синтаксис использования фигурных скобок на корректный оператор конкатенации, как указано ниже:

- name: "Migrate my-pc module home files"
  copy:
    src: "{{ migration_source_path }}{{ item }}"
    dest: "{{ migration_destination_path }}{{ item }}"
  loop: "{{ migration_paths_my_pc }}"
  when:
    - not is_migrating_all
    - (migration_source_path ~ item) is exists
    - m_my_pc | bool

В данной реализации мы применяем оператор ~ для объединения переменных migration_source_path и item в одно строковое выражение. Как только это выражение сформировано, оно используется в утверждении is exists, чтобы проверить наличие файла или каталога.

Применение (Application)

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

  1. Снизить количество ошибок в playbook’ах. Исключив явное использование {{ }} из условий, мы устраняем частую причину синтаксических ошибок.

  2. Повысить читаемость и поддерживаемость кода. Простой и ясный синтаксис делает playbook более прозрачным для других разработчиков или администраторов, поддерживающих систему.

  3. Обеспечить гибкость и адаптивность. Вы можете легко адаптировать playbook для различных сценариев миграции, просто изменяя значения в соответствующих переменных, не прибегая к значительным изменениям в логике самого playbook.

  4. Сохранить текущую логику выполнения задач без прерывания. Если вы хотите сохранить текущие настройки и предупреждения при отсутствии файлов, вы всё равно сможете получать уведомления об этом с помощью встроенных механизмов Ansible, таких как регистры и уведомления (handlers).

Заключение

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

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

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