Условия и циклы
Тема дорожной карты · SaltStack
Условия {% if %} и циклы {% for %} в Jinja превращают SLS-файл из статичного списка состояний в генератор. Один шаблон может разворачиваться в разный YAML в зависимости от миньона и данных. Условия обычно ветвятся по grains (дистрибутив, версия, роль машины) и pillar (включена ли фича, какое окружение), а циклы — разворачивают списки и словари из pillar в наборы однотипных состояний: пользователи, виртуальные хосты, точки монтирования. Важно помнить, что это логика времени рендеринга, а не исполнения. К моменту применения состояний все if и for уже сгенерировали YAML.
Как это работает
Условие ветвит текст шаблона:
{% if grains['os_family'] == 'RedHat' %}
{% set svc = 'httpd' %}
{% elif grains['os_family'] == 'Debian' %}
{% set svc = 'apache2' %}
{% else %}
{% set svc = 'apache' %}
{% endif %}
Цикл по словарю из pillar генерирует состояния. Каждый ID должен быть уникален, поэтому в него включают переменную цикла:
{% for site, cfg in salt['pillar.get']('vhosts', {}).items() %}
vhost_{{ site }}:
file.managed:
- name: /etc/nginx/conf.d/{{ site }}.conf
- source: salt://nginx/files/vhost.conf.jinja
- template: jinja
{% endfor %}
Дефисы в тегах — {%- if ... -%} — съедают пробелы и переводы строк вокруг тега. Без них циклы оставляют пустые строки в результате, что затрудняет чтение вывода slsutil.renderer. Глобально поведение регулируется опциями jinja_trim_blocks и jinja_lstrip_blocks в конфигурации, но по умолчанию они выключены. Менять их для общих формул рискованно, так как шаблоны, написанные под другие настройки, начнут рендериться иначе.
Когда применять
Ветвление по grains['os_family'] — правильный уровень общности. Семейство покрывает целую линейку дистрибутивов, тогда как проверка точного grains['os'] быстро превращается в лестницу из elif. Циклы по pillar — стандартный способ отдать управление данными: добавление нового виртуального хоста становится правкой pillar, а не SLS-файла. Проверка «есть ли данные» перед циклом не нужна, если использовать pillar.get с пустым дефолтом ({} или []) — цикл по пустой коллекции просто ничего не сгенерирует. А вот когда условия начинают определять десятки значений (пакет, сервис, путь, владелец — и всё по ОС), это признак, что пора переходить на паттерн map.jinja и держать данные словарём, а не веткой кода.
Типичные ошибки
Главная ошибка — дублирующиеся ID состояний в цикле: если ID не включает переменную итерации, каждая следующая итерация затирает предыдущую, и применяется только последняя — без ошибок, молча. Вторая ошибка — сравнение с неверным регистром или значением grain: grains['os'] возвращает, например, Ubuntu, а не ubuntu; при сомнении проверьте реальное значение через salt '*' grains.item os os_family. Третья ошибка — вложенные циклы и условия на три-четыре уровня: такой шаблон невозможно ревьюить, а ошибка отступа в глубине даёт YAML-ошибку со смещённым номером строки. Четвёртая ошибка — логика, зависящая от порядка итерации по словарю, когда конфиг собирается из фрагментов: делайте результат нечувствительным к порядку или сортируйте явно.
Связанные понятия
Полезные ресурсы
🔤 Английские термины в этой теме
Слова из этой темы, которые русскоязычные часто произносят неверно. Кнопка 🔊 произносит голосом браузера.
- written /ˈrɪtn/ «ритн», двойное t произносится как одно, i краткое разбор: Письменная коммуникация
- result /rɪˈzʌlt/ ударение на второй слог разбор: Behavioral questions и метод STAR
- deploy /dɪˈplɔɪ/ ударение на второй слог, не «дЕплой» разбор: Рунглиш vs английский: когда что уместно
- variable /ˈvɛəriəbl/ ударение на первый слог, а не «вэриЭйбл» разбор: Как читать код вслух
- review /rɪˈvjuː/ ударение на второй слог; «рЕвью» — рунглиш разбор: Глаголы: задеплоить, пофиксить, замержить, заапрувить