Ansible playbook – конкатенация переменных в условии

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

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

- name: "Перенос файлов модуля my-pc home"
  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

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

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

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

[WARNING]: условные выражения не должны содержать разделителей jinja2, таких как {{ }} или {% %}. Обнаружено: '{{ migration_source_path }}{{ item }}' is exists

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

    - vars["" + migrate_source_path + item] is exists
    - vars[migrate_source_path + item] is exists
    - vars[migrate_source_path ~ item] is exists
    - vars[migrate_source_path]vars[item] is exists
    - '' + migrate_source_path + item is exists
    - lookup('/home/k/test/test2/' + item) is exists
    - "{{ lookup('vars', 'migrate_source_path' + 'item') is exists }}"
    - "{{ lookup('vars', 'migrate_source_path') + lookup('vars', 'item') is exists }}"
    - lookup('vars', 'migrate_source_path')lookup('vars', 'item') is exists

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

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

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

ОБНОВЛЕНИЕ:

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

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

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

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

    - (migration_source_path ~ item) is exists

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

Вы были более-менее близки с:

    - '' + migration_source_path + item is exists

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

    - "'' + migration_source_path + item is exists"
    - migration_source_path + item is exists

она попытается добавить migration_source_path и item is exists, так как вы не задали правильный порядок с помощью скобок.

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

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

С наилучшими пожеланиями.

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

Создание Ansible плейбуков может быть достаточно сложным процессом, особенно когда вы сталкиваетесь с необходимостью использования переменных и условных операторов. Ваш текущий сценарий связан с копированием определенных файлов из домашнего каталога на основе предоставленных условий. Однако, вы столкнулись с проблемой, связанной с использованием Jinja2-шаблонов в условных операторах, вызвав ошибку или предупреждение в вашем плейбуке. Давайте подробно разберем возможные пути решения этой задачи.

Теория

Ansible — это инструмент автоматизации, который использует YAML для описания конфигураций в плейбуках. Одним из его компонентов является Jinja2, мощный шаблонизатор, который позволяет вставлять переменные в ваш код. Однако использование Jinja2 в условных выражениях в разделе when часто приводит к ошибкам, так как Ansible пытается интерпретировать условие как Jinja-выражение по умолчанию. Поэтому использование фигурных скобок в этих местах является избыточным и может приводить к ошибкам.

Пример

Рассмотрим ваш текущий код:

- 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

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

- 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

Применение

Теперь давайте применим эти знания на вашем конкретном примере.

  1. Объединение строк в условии: Для задания полной строки с использованием нескольких переменных вместо использования Jinja-шаблонов, просто объедините строки с помощью оператора ~:

    - (migration_source_path ~ item) is exists

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

  2. Логика копирования: Используйте модуль copy для переноса файлов. Этот модуль автоматически проверяет существование исходных файлов и может выдать ошибку, если файл не существует. Если вы не хотите, чтобы ошибки прерывали выполнение, рассмотрите возможность использования регистра для фиксации ошибки и, возможно, отметки задачи как failed_when: false.

  3. Упрощение контролируемого копирования: Когда список путей к копируемым файлам фиксирован, можно использовать with_items:. Это создаст более точно описанный и менее подверженный ошибкам код. Если вам все же необходимо гибко выбирать файлы, продолжайте использовать цикл loop.

  4. Поддержка и отладка: Добавьте логирование и отладочную информацию, чтобы отслеживать, какие файлы были успешно скопированы, а какие нет. Это помогает сокращать расходы на поддержку вашего плейбука.

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

Таким образом, корректное использование Ansible для автоматизации сложных сценариев связано с правильной организацией логики плейбуков и минимизацией шаблонов там, где это возможно. Это не только предотвращает ошибки, но и делает код более чистым и управляемым. Надеемся, что эти рекомендации помогут вам достичь ваших целей, связанных с миграцией домашних директорий на вашем ПК.

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

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