Вопрос или проблема
У меня есть задача по переносу (копированию) определенной части моего домашнего каталога (важна вторая с конца строка):
- 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
Применение
Теперь давайте применим эти знания на вашем конкретном примере.
-
Объединение строк в условии: Для задания полной строки с использованием нескольких переменных вместо использования Jinja-шаблонов, просто объедините строки с помощью оператора
~
:- (migration_source_path ~ item) is exists
Этот подход избегает необходимости использовать HTML шаблоны, при этом позволяя корректно проверить условие на существование файла.
-
Логика копирования: Используйте модуль
copy
для переноса файлов. Этот модуль автоматически проверяет существование исходных файлов и может выдать ошибку, если файл не существует. Если вы не хотите, чтобы ошибки прерывали выполнение, рассмотрите возможность использования регистра для фиксации ошибки и, возможно, отметки задачи какfailed_when: false
. -
Упрощение контролируемого копирования: Когда список путей к копируемым файлам фиксирован, можно использовать
with_items:
. Это создаст более точно описанный и менее подверженный ошибкам код. Если вам все же необходимо гибко выбирать файлы, продолжайте использовать циклloop
. -
Поддержка и отладка: Добавьте логирование и отладочную информацию, чтобы отслеживать, какие файлы были успешно скопированы, а какие нет. Это помогает сокращать расходы на поддержку вашего плейбука.
-
Профессиональный подход: Рассмотрите целесообразность использования обработчиков и регистров для повышения читаемости кода и упрощения управления задачами.
Таким образом, корректное использование Ansible для автоматизации сложных сценариев связано с правильной организацией логики плейбуков и минимизацией шаблонов там, где это возможно. Это не только предотвращает ошибки, но и делает код более чистым и управляемым. Надеемся, что эти рекомендации помогут вам достичь ваших целей, связанных с миграцией домашних директорий на вашем ПК.