Ansible если файл существует
Ansible – это современный инструмент управления конфигурацией. Для связи и выполнения команд на управляемых серверах (нодах) он использует только SSH и Python – то есть вам не нужно устанавливать агентское программное обеспечение на удаленные ноды. В этой серии мануалов вы познакомитесь с основными функциями Ansible, которые можно использовать для написания сценариев автоматизации серверов. В конце серии вы найдете практический пример плейбука для автоматизации настройки удаленного веб-сервера Nginx и развертывания на нем статического HTML-сайта.
Примечание: Этот мануал является частью серии по работе с Ansible. Другие мануалы из этой серии вы найдете по тегу ansible-practice. Весь код можно найти в этом репозитории.
В Ansible можно определять условия, которые будут оцениваться перед выполнением задачи: если условие не выполнено, задача пропускается. Условия определяются с помощью ключевого слова when. Оно принимает выражения, которые, как правило, основаны на переменной или факте.
В следующем примере мы определили две переменные: create_user_file и user. Если create_user_file оценивается как true, в домашнем каталоге пользователя, заданном переменной user, будет создан новый файл.
Создайте новый файл по имени playbook-04.yml в каталоге ansible-practice:
Затем добавьте в новый плейбук следующие строки:
Сохраните и закройте файл.
Чтобы запустить этот плейбук на серверах из вашего инвентаря, используйте команду ansible-playbook с теми же аргументами подключения, которые вы использовали ранее (при запуске других плейбуков из этой серии мануалов). Мы снова будем использовать файл инвентаря по имени inventory и пользователя 8host для подключения к удаленным серверам (замените эти данные своими):
ansible-playbook -i inventory playbook-04.yml -u 8host
Если условие выполнено, вы увидите статус changed в выводе плея:
Если вы измените значение create_user_file на no, условие будет оценено как false. В таком случае в выводе плея вы увидите статус skipping, указывающий, что задача не была выполнена:
Чаще всего в контексте сценариев Ansible условия объединяются с register. Это ключевое слово, которое создает новую переменную и присваивает ей полученный результат команды. Таким образом, для оценки выполнения задачи вы можете использовать любую внешнюю команду.
Важно отметить: если команда, которую вы используете для оценки условия, не срабатывает, по умолчанию Ansible прерывает плей. Чтобы отключить это поведение, нужно добавить в задачу директиву ignore_errors со значением yes, и это заставит Ansible перейти к следующей задаче и продолжить обработку плея.
В нашем каталоге ansible-practice создайте новый файл с именем playbook-05.yml:
Затем добавьте в новый плейбук следующий контент:
Сохраните и закройте файл.
Затем запустите команду ansible-playbook с аргументами подключения из предыдущих примеров (мы, как обычно, используем инвентарь по имени inventory и пользователя 8host, но вам следует соответствующим образом изменить эти значения):
ansible-playbook -i inventory playbook-05.yml -u 8host
При первом запуске этого плейбука выполнение команды завершится ошибкой, поскольку такой файл не существует по этому пути. Затем будет выполнена задача, создающая файл, а последняя задача будет пропущена:
По выходным данным вы можете увидеть, что задача «create file for user» вызвала изменение на сервере, следовательно, файл был создан. Теперь запустите плейбук еще раз:
ansible-playbook -i inventory playbook-05.yml -u 8host
и вы получите другой результат:
Больше информации об условиях в плейбуках Ansible вы найдете в официальной документации инструмента.
Мне нужно проверить, существует ли файл в формате /etc/ . Если файл существует, мне нужно пропустить задачу. Вот код, который я использую:
Вы можете сначала проверить, существует ли целевой файл или нет, а затем принять решение на основе его результата:
когда: stat_result.stat.exists определен и stat_result.stat.exists Спасибо за это. Кроме того, если вы узнали, вы можете написать: when: stat_result.stat.exists == False в, when: not stat_result.stat.exists если хотите, чтобы текст читался более естественно. Не могли бы вы использовать «not Foo» вместо «Foo == False»?Модуль stat сделает это, а также получит много другой информации для файлов. Из примерной документации:
Похоже, что в последних версиях есть предупреждение при использовании «полнотекстовых сравнений», например, «is» и т. Д. Вместо «=», «<», «>» и т. Д.Этого можно добиться с помощью модуля stat, чтобы пропустить задачу, когда файл существует.
Обычно это делается с помощью модуля stat . Но у командного модуля есть creates опция, которая делает это очень просто:
Думаю, ваша сенсорная команда - это просто пример? Лучше всего вообще ничего не проверять и позволить ansible делать свою работу - с правильным модулем. Поэтому, если вы хотите убедиться, что файл существует, вы должны использовать файловый модуль:
Я бы посчитал первый пример в этом ответе правильным ответом на этот вопрос, основанный на конкретных обстоятельствах вопроса пользователя, использовании пользователем командного модуля и доступных передовых практиках. Вы не поясняете свой ответ, а что when: mypath is not exists в данном случае значит? Разве это не mypath простая строка? Шаблон Jinja2 помогает здесь проверить путь. Больше примеров в Ansible Docs Обратите внимание, что это проверяет файлы на контроллере, а не на пульте дистанционного управления.Я считаю, что выполнение большого количества таких .stat.exists проверок может раздражать и приводить к ошибкам . Например, им требуется дополнительная осторожность, чтобы заставить --check работать check mode ( ).
Многие ответы здесь предполагают
- получить и зарегистрироваться
- применяется, когда выражение регистра истинно
Однако иногда это запах кода, поэтому всегда ищите более эффективные способы использования Ansible, в частности, использование правильного модуля дает много преимуществ. например
Но когда невозможно использовать один модуль, также выясните, можете ли вы зарегистрироваться и проверить результат предыдущей задачи. например
Обратите внимание на when: то, creates: что --check это не ошибка
Я упоминаю об этом, потому что часто эти неидеальные практики используются парами, т.е. без пакета apt / yum, поэтому мы должны 1) загрузить и 2) разархивировать
Я пытаюсь включить файл, только если он существует. Это позволяет настраивать «задачи/роли» между существующими «задачами/ролями», если это необходимо пользователю моей роли. Я нашел это:
Но Ansible документы утверждают, что:
Сбой, если включаемый файл не существует. Я предполагаю, что может быть другой механизм, позволяющий пользователю добавлять задачи в существующий рецепт. Я не могу позволить пользователю добавить роль после моей, потому что он не будет контролировать порядок: его роль будет выполнена после моей.
Спасибо всем за помощь! Я задаю свой вопрос после того, как, наконец, попробую все ответы и код своего вопроса в сегодняшнем Ansible: ansible 2.0.1.0
Кажется, мой оригинальный код работает, за исключением того, что необязательный файл, который я искал, был на моем локальном компьютере, поэтому мне пришлось запустить stat через local_action и установить become: no для этих конкретных задач, чтобы ansible не пытался выполнить Sudo на моем локальном компьютере и ошибка: "Sudo: требуется пароль\n"
Условие with_first_found может выполнить это без stat или local_action . Это условие будет проходить через список локальных файлов и выполнять задачу с параметром item , установленным на путь первого существующего файла. Включение skip: true в опции with_first_found предотвратит его сбой, если файл не существует.
Я использовал что-то похожее, но для файлового модуля, и что для меня помогло проверить определение переменной, попробуйте что-то вроде:
задача будет выполняться только тогда, когда переменная существует.
Используя ansible-2.1.0, я могу использовать подобные фрагменты в моей книге игр:
Я не получаю ошибок/сбоев, когда local.yml не существует, и playbook выполняется (как playbook, то есть начинается со строки hosts: и т.д.)
Вы можете сделать то же самое на уровне задач вместо этого с похожим кодом . Использование stat работает правильно.
Я мог бы потратить здесь время, чтобы разобраться с положениями об обработке ошибок ansible, но вкратце вы правы и не можете использовать модуль stat для этой цели по указанным причинам.
Самое простое решение для большинства возможных проблем - сделать это за пределами возможных. Например.
* failed_when добавлен во избежание исключения хоста из дальнейших задач, когда файл не существует.
Инструкция представляет из себя шпаргалку по работе с Ansible. У автора не стоит задачи подробного пояснения всех операций — только описание задачи и пример того, как ее можно решить с помощью ansible. Для более подробного описания я постараюсь указать ссылки на официальную документацию. Также в данную шпаргалку не войдут все возможные действия, которые можно выполнить с помощью данной системы — только популярные и те, с которыми приходилось сталкиваться самому автору. По мере возможности, их список будет пополняться.
Для удобства, мы попробуем разбить примеры на операции, которые логически можно объединить в одну группу.
Получение информации
Сюда войдут примеры, которые позволят собирать информацию, выводить ее на экран, помогать в отладке и всякое такое.
1. Показать информацию об удаленной системе, на которой запускается ansible.
Выполняется с помощью модуля debug, который должен показать содержимое ansible_facts:
- name: Print all available facts
ansible.builtin.debug:
var: ansible_facts
* ansible_facts содержит массив данных с информацией о системе. Однако, функция сборки информации может быть отключена (так как на ее работу тратится, относительно, много времени) в настройках плейбука с помощью опции gather_facts: false — в этом случае, значение нужно изменить на true.
Также мы можем обратиться к конкретному элементу массива ansible_facts, получив информацию о конкретной настройке или опции:
* например, имя компьютера.
2. Отображение на экран переменной.
Выше мы уже использовали debug для отображения переменной — принцип тот же:
* при выполнении задачи на экране мы увидим значение переменной variable. Обратите внимание, что запись ansible.builtin.debug и debug — это одно и то же, то есть, ansible.builtin можно не писать.
3. Сохранение результата в переменную.
Выполняется с помощью register:
- name: Run a shell command and register its output as a variable
shell: command
register: command_result
* в данном примере мы запишем в переменную command_result все то, что мы получили с помощью команды command.
Вывести на экран содержимое можно с помощью debug:
- name: Show Value of Variable
debug:
var: command_result.stdout
* обратите внимание, что мы выводим не все содержимое, а только stdout, то есть то, что должна была вывести в консоль команда.
4. Получить список сервисов.
Для этого существует service_facts:
- name: Populate service facts
ansible.builtin.service_facts:
- name: Print all available facts
ansible.builtin.debug:
var: ansible_facts.services
* цель достигается двумя задачами. В первой мы собираем информацию о сервисах с помощью service_facts, второй — выводим на экран содержимое.
Проверки и условия
В данную группу войдут действия, которые помогут нам ограничить выполнение задач.
1. Проверка на пустую папку.
Задачи сводится к двум операциям:
- получении списка файлов в целевом каталоге (например, с помощью команды ls) и регистрации полученного значения в переменную с помощью register.
- проверка содержимого переменной, которую мы получили на шаге 1 с помощью when.
Пример будет таким:
- name: Register Contents of PGDATA Folder
shell: ls /var/lib/postgresql/11/main
register: pg_contents
- name: Init PostgreSQL DB
shell: /opt/pgpro/std-11/bin/pg-setup initdb
environment:
PGDATA: "/var/lib/postgresql/11/main"
when: pg_contents["stdout_lines"] | length == 0
2. Проверить, определена ли переменная.
Для этого используется опция is defined (определена) или is not defined (не определена):
when: pgpro is defined
when: pgpro is not defined
* в данном примере мы проверим наличие переменной pgpro. На практике такая проверка имеет значение, так как если мы попробуем выполнить действия с несуществующей переменной, Ansible нам вернет ошибку.
В официальной документации про это сказано в статье о when (ссылка выше).
3. Выполнение команды, если сервис в рабочем состоянии.
Нам необходимо получить информацию о службах с помощью service_facts, после чего можно уже делать проверку с помощью when:
- name: Populate service facts
ansible.builtin.service_facts:
- name: Stop Service If Running One
shell: systemctl stop apache2
when: ansible_facts.services["apache2.service"] is defined and ansible_facts.services["apache2.service"].state == "running"
* в данном примере мы проверим, есть ли служба apache2 и запущена ли она. Если это так, то мы ее останавливаем.
Подробнее о service_facts можно прочитать в документации (ссылка выше в разделе 4. Получить список сервисов).
Установки пакетов, модулей и расширений
В данном разделе мы коснемся всего, что приводит к установке чего бы то ни было. А именно:
- Установки пакетов в систему.
- Загрузки исходников.
- Установке дополнительных модулей.
- Распаковке архивов.
Рассмотрим это подробнее.
1. Установка модуля в nodejs.
Установка модулей в nodejs выполняется с помощью npm. Для него в ansible есть отдельная функция:
- name: Install nodejs modules.
npm:
name: newman
global: yes
* в данном примере будет выполнена установка newman, которая будет доступна всем проектам (опция global).
2. Загрузка из GIT.
Выполняется с помощью модуля git:
* в данном примере мы сделаем клон репозитория в каталог /tmp/docker-compose.
3. Распаковка архива.
Выполняется с помощью unarchive:
* в данном примере мы распакуем исходник для nginx в каталог /tmp. Обратите внимание на две вещи:
- Мы используем переменную nginx_ver. Данная переменная должна быть определена при запуске плейбука, или в инвентарном файле, или в var, или в default.
- Опция creates позволит не выполнять операцию, если существует файл /tmp/nginx->.tar.gz.
Настройка системы
В данном разделе мы рассмотрим процессы, которые больше подходят для категории настройки системы.
1. Добавить задание в cron.
Выполняется с помощью модуля cron:
* в данном примере мы создадим задание для запуска команды /scripts/command.sh каждый день, каждые 6 часов.
2. Добавить публичный ключ хоста в known_hosts.
Делается с помощью known_hosts. Пример из официальной документации:
3. Создание новых SSH-ключей для сервера.
Создание ключей реализуется с помощью модуля openssh_keypair:
* в данном примере мы создадим 4 ключа разных типов: dsa, ecdsa, ed25519, rsa. Так как у каждого из них свои требования к размеру, перечень представлен в виде двумерного массива. Ключи будут созданы в каталоге /etc/ssh/.
4. Создание системной учетной записи.
Для этого есть модуль user. У него много опций, но для создания системной учетной записи нам достаточно:
- name: Create User Consul
user:
name: consul
system: yes
comment: "Consul Agent"
* в данном примере будет создана учетная запись consul.
5. Работа с systemd.
Для данной настройки есть одноименный модуль systemd. Рассмотрим варианты его использования.
а) перечитать конфигурацию (необходимо делать каждый раз, когда мы меняем настройки юнита):
- name: systemd reload
systemd:
daemon_reload: yes
б) разрешить сервис (автозапуск):
- name: mysql enable
systemd:
name: mysql
enabled: yes
* для сервиса mysql.
в) перезапустить сервис:
- name: mysql reload
systemd:
name: mysql
state: restarted
* для сервиса mysql.
6. Настройка брандмауэра.
Выполняется разными модулями в зависимости от используемой системы управления netfilter:
Рассмотрим небольшие примеры.
- name: Block specific IP
iptables:
chain: INPUT
source: 8.8.8.8
jump: DROP
Добавить 80 порт:
Добавить порты с циклом:
Работа с папками и файлами
Рассмотрим задачи, которые помогут нам создавать, копировать и работать с файлами.
1. Создание каталогов и файлов.
Создание файлов и каталогов выполняется с помощью модуля file.
а) для каталога в качестве state указываем directory:
б) для создания файла указываем убираем опцию state (или даем ей значение file):
- name: Create File
file:
path: "/var/www/site1/index.php"
owner: www-data
group: www-data
mode: 0644
* в данном примере мы созданим файл index.php в каталоге /var/www/site1.
2. Копирование файлов из каталога.
Для копирования данных мы используем модуль copy:
- name: Copy Cert File If Different
copy:
src: ">"
dest: /etc/ssl/dmosk
remote_src: no
mode: 0644
owner: root
group: root
with_fileglob:
- files/*
* в данном примере мы прочитаем все содержимое каталога files на компьютере с ansible, и скопируем его в каталог /etc/ssl/dmosk на целевом компьютере.
3. Используем шаблон.
Копирование из шаблона отличается от копирования из файла тем, что в шаблоне могут использоваться переменные, которые будет заменяться их значениями в момент копирования. Для самого процесса копирования из шаблона используется модуль template:
- name: Create Config for Consul Agent
template:
src: templates/consul/config.json.j2
dest: /etc/consul.d/config.json
* в данном примере мы возьмом шаблон templates/consul/config.json.j2 на компьютере ansible и разместим его в по пути /etc/consul.d/config.json на целевом компьютере.
4. Удалить последние 30 файлов.
Задача решается в два этапа:
- ищем содержимое целевого каталога.
- сотритуем список найденных по времени изменения файлов и удаляем все, что идут после определенного числа объектов.
Поиск выполняем с помощью модуля find, удаление — file:
- name: "Get list of backup files"
find:
paths: "/backup"
file_type: file
register: founds
* в данном примере мы ищем файлы в каталоге /backup, после чего сортируем найденное и удаляем по списку все файлы, которые идут после 30-го.
Для этого используется модуль uri. Простой пример:
* в данном примере мы скачаем файл с ресурса, где требуется аутентификация по токену, который передается в заголовке. Заголовки мы передаем с помощью параметра headers. Также мы задаем права на загруженный файл и делаем в качестве владельца пользователя и группу dmosk.
Виртуализация VMware
Работа с виртуальными машинами на платформе VMware выполняется с помощью модуля vmware_guest.
Мы рассмотрим несколько примеров.
1. Базовое подключение.
Для выполнения действий над виртуальными машинами мы должны подключиться к хосту VMware. Для этого используем данные строки:
* параметр validate_certs, выставленный в no, позволит избежать ошибки, если у нас на хосте используется самоподписанный сертификат (как правило, так и есть).
2. Переименовать виртуальную машину.
Для выполнения действия нам нужно знать идентификатор виртуальной машины:
* где uuid — идентификатор виртуальной машины; name — новое имя виртуальной машины.
3. Конвертировать виртуальную машину в шаблон.
Для этого нужно просто задать признак is_template:
Разное
В данном разделе будет рассказано о дополнительных опциях, которые позволяют менять поведение выполнения задач, добавляет функциональности или все то, для чего не найдена отдельная подходящая категория.
1. Шифрование строки.
С помощью ansible-vault мы можем шифровать файлы и папки. Это позволит нам хранить секреты не в открытом виде. Данные расшифровываются в момент выполнения задач.
Данной командой мы получаем шифрованную строку:
Система запросит ввести дважды пароль и предложит ввести строку, которую нужно зашифровать. После мы должны нажать 2 раза Ctrl + D — мы получим строку, которая начинается с !Vault и различные символы.
Для того, чтобы в момент выполнения задачи ansible расшифровал данные, при запуске плейбука мы должны указать ключ --ask-vault-pass:
2. Игнорировать ошибки.
Если ansible столкнется с ошибкой при выполнении задачи, работа плейбука будет завершена. Иногда, нужно пропустить ошибку при выполнении определенной задачи, чтобы выполнение было продолжено. Для этого существует опция ignore.
а) чтобы пропустить ошибки выполнения, в настройка задачи используем:
- name: Bad Task
.
ignore_errors: yes
б чтобы игнорировать ошибки при подключении к хосту:
- name: Bad Task
.
ignore_unreachable: yes
3. Начинать выполнение с определенной задачи.
При выполнении отладки, полезно запустить плейбук, но начать выполнение с определенной задачи. Остальные пропустить.
Это можно сделать с помощью опции --start-at-task:
ansible-playbook . --start-at-task="Start Job"
* в данном примере плейбук начнет выполнять задания с задачи Start Job.
4. Завершить выполнение плейбука после определенной задачи.
С помощью данной конструкции:
5. Зависимые роли.
С помощью файла meta/main.yml в роли мы можем определить пред-роль, от которой зависит выполнение текущей роли. Для этого настраивается опция dependencies:
dependencies:
- role: pred
6. Вставка роли и ее задач.
Позволяет в процессе выполнения задачи подключить роль. Делается при помощи include_role:
- name: "Include Other Role"
include_role:
name: other_role
А это пример, как подключить роль и сделать так, чтобы все ее задачи выполнились на определенном хосте:
7. Замены в строке.
Замены выполняются с помощью модуля replace:
* в данном примере мы добавляем комментарий к строке server.address=127.0.0.1.
8. Повторы при выполнении задачи.
Мы можем управлять цикличностью выполнения задач с помощью retries (количиство повторов), delay (задержка в секундах).
Рассмотрим пример повтора выполнения задачи при возникновении ошибки:
- name: Run anything command
command: /foo/bar/cmd
register: result
retries: 3
delay: 60
until: result is not failed
* в данном примере мы будем выполнять команду /foo/bar/cmd пока ее выполнение не закончится без ошибок. Количество повторов будет равен 3 с интервалом в 60 секунд.
Читайте также: