Одной из ключевых особенностей Ansible является использование фильтров, основанных на системе шаблонов Jinja2, позволяющих трансформировать данные и управлять ими в процессе выполнения задач. На синтаксическом уровне, фильтры это функции, применяемые к переменным или выражениям для их изменения или форматирования.
Фильтры применяются к переменным или значениям внутри двойных фигурных скобок {{ }}
с использованием символа вертикальной черты |
. Например, {{ some_variable | filter_name }}
. Ниже, несколько примеров:
- hosts: all
gather_facts: no
vars:
numbers: [3, 2, 1, 3, 2]
tasks:
- name: get min number
ansible.builtin.debug: msg={{ numbers | min }}
- name: get max number
ansible.builtin.debug: msg={{ numbers | max }}
- name: get unique values
ansible.builtin.debug: var={{ item }}
loop: "{{ numbers | unique }}"
- name: get random value
ansible.builtin.debug: msg={{ ['a', 'b', 'c'] | random }}
Здесь применяются различные фильтры к списку чисел (переменная numbers
). Синтаксически это выглядит как имя функции фильтрации, указанное после вертикальной черты. Вот что делают эти фильтры:
min
находит минимальное значениеmax
находит максимальное значениеunique
находит уникальные значения (результатом является список, поэтому для вывода на печать используем цикл)random
позволяет выбрать случайное значение из списка
При выполнении этого плейбука мы получим вот такой результат:
ansible-playbook playbook.yml -i inventory.ini
TASK [get min number] *************************
ok: [localhost] => {
"msg": "1"
}
TASK [get max number] *************************
ok: [localhost] => {
"msg": "3"
}
TASK [get unique values] **********************
ok: [localhost] => (item=numbers | unique) => {
"ansible_loop_var": "item",
"item": "numbers | unique",
"numbers | unique": [
3,
2,
1
]
}
TASK [get random value] ***********************
ok: [localhost] => {
"msg": "a"
}
Какие реальные задачи можно решать с помощью этих фильтров? Предположим, что мы хотим выбрать сервер из списка по определенным параметрам. Как мы можем применить фильтры:
- Найти сервер с самым большим количеством CPU.
- Найти сервер с наименьшим количеством оперативной памяти.
Ниже еще несколько примеров фильтров, которые встречаются достаточно часто в реальной жизни:
- hosts: all
gather_facts: no
vars:
path: /var/log/upstart/nginx.log
tasks:
- ansible.builtin.debug: msg={{ '192.0.2.1/24' | ipaddr('address') }}
- ansible.builtin.debug: msg={{ 'test1' | hash('sha1') }}
- ansible.builtin.debug: msg={{ path | basename }}
- ansible.builtin.debug: msg={{ path | dirname }}
- ansible.builtin.debug: msg={{ "~/Movies" | expanduser }}
Рассмотрим фильтры, которые мы использовали, более подробно:
- Фильтр
ipaddr
позволяет извлекать из ip-адреса различные его части. В примере выше извлекается адрес. - Фильтр
hash
создает хэш, который затем может быть использован, например, в файлах конфигурации. - Фильтры
basename
иdirname
работают с путями. С помощью них можно выделить имя файла и путь к директории expanduser
раскрывает путь. ~/Movies, для пользователя hexlet превратится в /home/hexlet/Movies.
Другие популярные фильтры:
default
: Устанавливает значение по умолчанию для переменной, если она не определена.map
: Преобразует каждый элемент в списке.json_query
: Позволяет запросить структуры JSON с помощью специального запроса.regex_replace
: Заменяет текст, используя регулярные выражения.
Ansible позволяет разработчикам создавать собственные фильтры на Python, что расширяет возможности кастомизации и адаптации инструмента под конкретные задачи.
Самостоятельная работа
Воспользуемся простым фильтром, который приводит строку к верхнему регистру
- Создайте новую переменную, которая содержит строку
This is server web1!
, гдеweb1
это динамическое имя сервиса (взятое из фактов) - В шаблоне HTML файла templates/index.html.j2 Выведите сообщение в верхнем регистре с помощью фильтра
upper
.
- Создайте новую переменную, которая содержит строку
Также выведем текущую дату. Используйте факты, и выведите текущую дату в любом формате.
Залейте изменения на Github
В результате получится следующее:
<html lang="en"><head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<h2>THIS IS SERVER WEB1!</h2> <!-- Эта строка была приведена в верхний регистр с помощью фильтра -->
<small>Deployed at: Вт 21 дек 2021 20:18:03</small> <!-- Локализованная дата -->
</body>
</html>
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.