Паттерн map.jinja
Тема дорожной карты · SaltStack
map.jinja — соглашение из мира Salt-формул: вся OS-специфика и все значения по умолчанию собираются в один файл-словарь, а SLS-файлы формулы остаются чистыми и не содержат ни одного if по операционной системе. Идея проста: вместо того чтобы в каждом состоянии ветвиться «на Debian пакет называется apache2, на RedHat — httpd», формула один раз строит словарь соответствий по grains['os_family'], домешивает поверх него переопределения из pillar и дальше везде обращается к готовым значениям: {{ apache.pkg }}, {{ apache.service }}, {{ apache.config }}. Этот паттерн — часть официальных конвенций формул, и почти каждая публичная формула с GitHub-организации saltstack-formulas построена вокруг своего map.jinja.
Как это работает
Классический map.jinja в корне формулы:
{% import_yaml 'apache/defaults.yaml' as defaults %}
{% set apache = salt['grains.filter_by'](
defaults,
grain='os_family',
merge=salt['pillar.get']('apache:lookup', {})
) %}
defaults.yaml хранит словарь, где ключи — значения grain: под Debian лежит pkg: apache2, под RedHat — pkg: httpd. Функция grains.filter_by выбирает ветку по os_family миньона, а аргумент merge накладывает сверху словарь из pillar — так администратор конкретного окружения может переопределить любое значение, не трогая формулу. SLS-файл импортирует результат:
{% from 'apache/map.jinja' import apache with context %}
apache_pkg:
pkg.installed:
- name: {{ apache.pkg }}
with context обязателен: без него импортируемый шаблон не увидит grains и pillar миньона, и filter_by внутри отработает не так, как ожидалось. Проверить итоговый словарь можно прямо с миньона: salt-call slsutil.renderer salt://apache/map.jinja покажет, что именно получилось после выбора ветки и merge.
Когда применять
map.jinja обязателен для любой формулы, которая претендует на переиспользование: несколько дистрибутивов, несколько окружений, чужие руки. Трёхслойная модель — дефолты формулы, ветка по ОС, переопределения из pillar — покрывает почти все случаи кастомизации без правки кода формулы. Тот же приём работает и внутри одной инфраструктуры: даже если у вас только Debian, вынос всех «магических значений» (пути, версии, имена сервисов) в map.jinja отделяет данные от логики и упрощает будущие миграции. Не нужен паттерн там, где формула из одного SLS с двумя состояниями и без вариативности — словарь ради словаря только удлиняет код. Ключ pillar для переопределений принято называть <formula>:lookup — отступление от конвенции запутает тех, кто привык к стандартным формулам.
Типичные ошибки
Самая коварная — забытый with context при импорте: шаблон рендерится, но grains внутри map.jinja пусты, filter_by уходит в ветку по умолчанию, и на RedHat-миньоне внезапно ставится apache2. Вторая — ветвление по os вместо os_family: словарь пухнет отдельными записями под Ubuntu, Debian, Mint, хотя всем нужно одно и то же. Третья — данные окружения, зашитые в defaults.yaml формулы: пароли, адреса и размеры кластера должны приходить из pillar через merge, иначе формулу нельзя ни публиковать, ни переносить. Четвёртая — расхождение структуры между defaults.yaml и pillar-переопределениями: merge объединяет словари по ключам, и опечатка в имени ключа не даст ошибку, а просто молча не переопределит значение.
Связанные понятия
Полезные ресурсы
Проверить знания (2)
Загрузка вопросов…