Принципы написания формулы

Формула — это набор структурированных SLS-файлов, метаданных и, при необходимости, модулей, шаблонов и файлов, организованных в отдельной директории и предназначенных для декларативного описания и автоматизации конфигурации системы (например, установки пакетов, настройки файлов, запуска сервисов).

Структура файлов формулы

Формула — это директория, которая именуется согласно шаблону <top_level_dir>-formula.

Директория обязательно содержит поддиректорию <top_level_dir>, имя которой совпадает с именем формулы, и следующие файлы:

  • обязательные:

    • <top_level_dir>/init.sls — главный файл с состояниями формулы; может включать в себя другие файлы с расширением .sls через директиву include;

    • <top_level_dir>/clean.sls — файл отката состояний формулы;

    • pillar.example — файл с примером указания параметров формулы;

    • FORMULA — описание формулы в формате YAML;

  • необязательные:

    • docs/README.RST — файл с описанием способов применения формулы и входящих в нее состояний;

    • <top_level_dir>/any.sls — другие файлы с расширением .sls, содержащие состояния, которые включены в init.sls или clean.sls директивой include;

    • <top_level_dir>/any_dir — другие поддиректории, содержащие файлы с расширением .sls, которые включены в init.sls или clean.sls директивой include;

    • <top_level_dir>/map.jinja — файл, который описывает особенности конфигурации под конкретную ОС или другие статические конфигурации.

Файл FORMULA

Файл FORMULA включает атрибуты формулы:

  • name — имя формулы;

    Значение поля name должно быть уникальным среди всех формул, поскольку при их объединении в одну большую формулу дублирование значений может привести к проблемам с применением конфигураций.
  • os — семейства ОС, поддерживающие формулу;

  • os_family — семейства ОС, поддерживающие формулу;

  • version — версия пакета с формулой, указанная в формате YYYYMM; если в месяце было несколько выпусков (release), то минорный месячный выпуск проставляется в атрибуте release;

  • release — выпуск версии; атрибут расширяет версионность формулы, если в месяце было несколько выпусков;

  • summary — краткое описание формулы;

  • description — подробное описание формулы;

  • top_level_dir — имя поддиректории, где расположены файлы с расширением .sls.

SLS-файлы

SLS-файлы формулы составляются в синтаксисе YAML и содержат описания состояний, которые достигает система при применении формулы.

Имена SLS-файлов, а также имена директорий:

  • не могут содержать точки, кроме точки между именем и расширением .sls;

  • могут включать строчные прописные латинские символы, цифры от 0 до 9, символ - (минус) и символ _ (подчеркивание) и соответствовать маске [a-zA-z0-9-_]+.

Доступные состояния

Каждому состоянию присваивается уникальный идентификатор в рамках продукта.

Состояние {{formula-name}}

Мета-состояние (состояние, которое включает в себя другие состояния).

Устанавливает пакет {{formula-name}} из целевого репозитория. Может иметь зависимости от {{formula-name}}.repository, {{\formula-name}}.package через список include.

Состояние {{formula-name}}.repository (если применимо)

Имеет зависимость от {{formula-name}}.repository.install через список include.

Состояние {{formula-name}}.repository.install (если применимо)

Импортирует репозиторий, если значение repo.name указано в хранилище Pillars (или не пустое по умолчанию) и имеет зависимость от:

  • {{formula-name}}.repository.package.install через список include;

  • {{formula-name}}.repository.key.install через список include и реквизит require.

Состояние {{formula-name}}.repository.package.install (если применимо)

Устанавливает пакеты repo.required_packages.

Состояние {{formula-name}}.repository.key.install (если применимо)

Загружает repo.key_file на агент (minion) и декодирует данные файла из формата base64 в бинарный.

Состояние {{formula-name}}.package

Устанавливает пакет {{formula-name}}.

Состояние {{formula-name}}.clean

Мета-состояние (состояние, которое включает в себя другие состояния).

Отменяет все действия, выполненные в мета-состоянии {{formula-name}} в обратном порядке, то есть удаляет пакет и удаляет целевой репозиторий (если он был импортирован).

Имеет зависимость от {{formula-name}}.package.clean и {{formula-name}}.repository.clean через список include.

Состояние {{formula-name}}.package.clean

Удаляет пакет {{formula-name}}.

Состояние {{formula-name}}.repository.clean (если применимо)

Удаляет файл конфигурации репозитория.

Имеет зависимость от {{formula-name}}.repository.key.clean через список include.

Состояние {{formula-name}}.repository.key.clean (если применимо)

Удаляет Key-файл репозитория.

Состояние {{formula-name}}.run (если применимо)

Мета-состояние (состояние, которое динамически генерирует подсостояния на основе конфигурации в pillar).

Выполняет произвольные действия на агенте через модули, определенные в pillar:{{formula-name}}.lookup.

Безопасное хранение и передача конфиденциальных данных с помощью pillar-файлов

Для безопасного хранения и передачи конфиденциальных данных, таких как пароли и ключи, рекомендуется использовать pillar-файлы. Они содержат зашифрованную информацию, специфичную для каждого агента (minion), что обеспечивает защиту данных при передаче (подробную информацию см. в официальной документации).

В pillar-файле задайте значения конфиденциальных данных (логина и пароля) при создании версии конфигурации в пользовательском интерфейсе «Кабинет администратора».

Пример:

{
   "lookup":{
      "user": "user123",
      "password": "password"
   }
}

Чтобы пароли не попали в логи и результаты исполнения команд, передайте их в исполняемые скрипты как значение атрибута args.

Пример запуска скрипта:

run_script:
  cmd.script:
    - name: salt://{{slspath}}/files/error.sh
    - args: "-u {{ error_params.user }} -p {{ error_params.password }}"

Особенности передачи данных через pillar

При составлении формулы важно понимать, как данные передаются через pillar и как они интерпретируются формулой.

Система автоматически создает в pillar ключ, совпадающий с именем директории формулы (например, file-find, get-hostname, xrdp). В этот ключ помещаются все параметры, необходимые для работы формулы — как пользовательские (задаваемые администратором в ключе lookup), так и генерируемые автоматически (например, атрибут version_id).

Структура pillar, доступная формуле, имеет следующий общий вид:

<имя_формулы>:
  version_id: <version_id>
  lookup:
    ...

Содержимое ключа lookup определяется типом формулы:

  • для формул со статическими настройками (например, get-hostname, xrdp) lookup содержит параметры, которые переопределяют значения, заданные по умолчанию в map.jinja;

    Пример:

    get-hostname:
      lookup:
        python_path: '/opt/saltstack/salt/bin/python3'
        script_path: '/opt/saltstack/salt/get-hostname.py'
        service_path: '/etc/systemd/system/get-hostname.service'
  • для формул с динамическими задачами (например, file-find) lookup содержит набор задач, каждая из которых — это маппинг параметров для выполнения модуля (например, file_find.find_formatted).

    Пример:

    file_find:
      lookup:
        logs_recent:
          path: /var/log
          name: "*.log"
          type: f
          mtime: -1d
          size: +10k
          md5: true

Для универсальности и переиспользования формулы используется шаблон:

{%- set tplroot = tpldir.split('/')[0] %}

Это позволяет:

  • автоматически определять имя формулы на основе имени ее директории — без жесткой привязки к имени в коде: tpldir содержит путь к текущему SLS-файлу (например, file-find/run.sls → tpldir = 'file-find'), и tplroot извлекает именно имя формулы;

  • копировать формулу в новую директорию (например, file-find → file-find-custom) и менять только имя папки — без правок в SLS- или Jinja-файлах: система автоматически использует новое имя директории как ключ в pillar (например, file_find_custom), а формула продолжает корректно извлекать параметры через salt['pillar.get'](tplroot, {});

  • сохранять работоспособность при дублировании или переименовании — достаточно изменить имя директории и создать соответствующий ключ в pillar, и формула работает без изменений в логике.