Отчасти к счастью, отчасти к сожалению, но работа системного администратора фрилансера связана с огромным количеством технологий, меняющихся от проекта к проекту. С одной стороны, это позволяет держать свой мозг в тонусе. С другой стороны, иногда, возвращаясь к той или иной технологии, забываются уже давно изученные вещи. В данном документе и репозитории собраны некоторые примеры по работе с системой автоматизации Ansible. Возможно это поможет не только мне.
Во многих разделах идёт ссылка на файл пример из директории examples. Все файлы примеры написаны с использованием модуля debug
и просто работают с параметрами или синтаксисом, показывая возможное применение и возможные ошибки. Запуск этих файлов-примеров не приводит к каким-либо изменениям на локальной или удалённой системе.
Язык файлов примеров - английский.
Примеры в самом тексте могут повторятся в нескольких разделах. Это сделано намеренно и позволяет разобрать примеры с разных сторон. Например, примеры в разделе списки и with_items одинаковые, но показывают работу разных вещей.
Ansible - проект с активной разработкой. Это значит, что некоторый старый синтаксис уже не работает в новых версиях. Данный документ написан и протестирован в Ansible версии 2.3.1.0.
Раздел структура данных подробно описывает различные стуктуры данных, используемые в Ansible. Раздел сильно связан с разделом Циклы, рекомендую просмотреть оба раздела.
Списки - это простейшая структура данных в Ansible. Задаётся путём присваиванию списку имени и перечислению самого списка с новой строки, через тире и пробел. Как и во всём yaml
в качестве отступов используются пробелы, размер и порядок отступов (пробелов) имеет значнение! Использование табуляций приведёт к ошибкам выполнения. Например, список устанавливаемого софта будет выглядеть следующим образом:
soft:
- htop
- atop
- tshark
- mtr
Простые и сложные списки чаще всего используется с командой with_items
. В примере выше сам список будет иметь имя "{{ soft }}"
, а само указание на объект списка соответствует служебному "{{ item }}"
.
Практическое использование будет выглядеть следующим образом:
- name: Utils | Ubuntu | Install basic utilities
apt:
pkg: "{{ item }}"
state: present
with_items: "{{ soft }}"
Мало деталей? Более подробно в файле примере.
В некоторых случаях вам может потребоваться записать список в виде строки. Список заключается в квадратные скобки и пишется через запятую. В подобном синтаксисе наш список софта будет выглядеть следующим образом:
soft: ['htop', 'atop', 'tshark', 'mtr']
Обратите внимание, все значения в списке заключены в кавычки. Это не обязательно, но позволяет избежать проблем с типами.
В базовом виде словари представляют из себя простую форму состоящую из ключ:значение
. В простейшем случае это удобно для объединения параметров, относящихся к одному объекту. Давайте разберём пример.
swap_file:
filename: "swapfile"
location: "/"
size: 512
status: "install"
В данном примере описан простейший пример. Здесь swap_file
название словаря, filename
, location
, size
, status
- ключи. swapfile
, /
, 512
, install
значения этих ключей.
Подобная запись позволяет вам обращаться в коде ваших функций непосредственно к именам параметров (ключам), делая разбор кода значительно проще. Допустим код ниже выдаст фразу: "We want to install file to /. File should be called swapfile and use 512 MB of disk space."
- name: Simple dictionary pointing.
debug:
msg: "We want to {{ swap_file.status }} file to {{ swap_file.location }}. File should be called {{ swap_file.filename }} and use {{ swap_file.size }} MB of disk space."
Как видно в этом простейшем коде мы используем имена ключей, чтобы Ansible подставил значения из этих ключей.
Иногда требуется сделать что-то, для каждого ключа в словаре. Чаще это используется в случае словаря словарей, но можно использовать и для простейших случаев. Для этого используется with_dict
. В простейшем случае в качестве указателя используются {{ item.key }}
и {{ item.value }}
. Данный код покажет значение каждого ключа в словаре.
- name: Usage of with_dict helps here.
debug:
msg: "Current key is {{ item.key }}. Current key value is {{ item.value }}."
with_dict: "{{ swap_file }}"
Для словарей, аналогично спискам есть альтернативная запись в строчку. Используются фигурные скобки, запятая разделяет пары ключей и значений, сами ключи и значения разделяются двоеточием. Наш словарь в линейной записи будет выглядеть следующим образом:
swap_file: {filename: "swapfile", location: "/", size: 512, status: "install"}
Для демонстрации в примерах есть файл с удобным синтаксисом и альтернативный файл с синтаксисом в линию. Запустите оба из них и найдите 10 различий. Их нет.
Чем дальше вглубь, тем полезнее структуры. Теперь давайте разберём часто используемую структуру списков словарей. Структура комбинирует обычный список и структуру словарей. То есть объекты сгруппированы в список, а параметры объекта в словарь.
В нашем примере случай будет аналогичный случаю из словарей, но теперь у нас будет несколько свап файлов (да, да, такое редко, но нужно). Будем использовать следующую структуру данных.
swap_files:
- filename: "first_swapfile"
location: "/"
size: 512
status: "install"
- filename: "second_swapfile"
location: "/other"
size: 1024
status: "install"
Эта структура позволяет нам безболезненно использовать цикл with_items
, при этом указывая конкретный параметр каждого объекта. Это делает код легко читаемым и понятным в дальнейшей разработке. Помните наш пример из раздела словари с генерацией строки, где мы использовали конструкции "{{ swap_file.status }}"
, "{{ swap_file.location }}"
, "{{ swap_file.filename }}"
, "{{ swap_file.size }}"
?
Когда мы используем список словарей, то данная конструкция будет дополнена оператором циклов with_items
, а непостредственное название словаря будет заменено на слежебное item
.
- name: "Same strings for several dictionary items:"
debug:
msg: "We want to {{ item.status }} file to '{{ item.location }}'. File should be called '{{ item.filename }}' and use {{ item.size }} MB of disk space."
with_items: "{{ swap_files }}"
С этой конструкцией вы будете встречаться значительно чаще, чем с обычными словарями, так как она позволяет писать код, автоматически расширяемый под нужное количество объектов. Никто не запрещает вам использовать список словарей с одним словарём.
Так как это список словарей, а не словарь, то все конструкции с with_dict
работать не будут.
Команда with_items
выполняет заданную команду, для заданного списка. Список может задаваться непосредственно в команде или предварительно в переменных.
Если задавать список непосредственно в команде, то код будет выглядеть следующим образом:
- name: Utils | Ubuntu | Install basic utilities
apt:
pkg: "{{ item }}"
state: present
with_items:
- htop
- atop
- tshark
- mtr
Однако, такая конструкция используется достаточно редко, так как не позволяет выносить список в файл конфигурации и делать его уникальным для каждого хоста или группы. Значительно чаще используется конструкция с именнованным списком. В этом случае список задаётся в файле конфигурации хоста\группы\роли и имеет следующий формат:
soft:
- htop
- atop
- tshark
- mtr
Тогда исполняемый код будет преобразован в следующий:
- name: Utils | Ubuntu | Install basic utilities
apt:
pkg: "{{ item }}"
state: present
with_items: "{{ soft }}"
Использование with_items
со списками словарей типично для многих задач. Такое использование позволяет писать понятный и более читаемый код, когда нужно в одном месте использовать несколько параметров, относящихся к одному объекту. Это было показано подробно, в коде раздела списки словарей.