Паттерн 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, под RedHatpkg: 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)

Загрузка вопросов…