DSL
Soul Stack описывается тремя видами артефактов на YAML. Все они типизированы; выражения внутри — на CEL, рендер файлов — Go text/template.
| Артефакт | Что описывает | Где живёт |
|---|---|---|
| Destiny | Желаемое состояние одного хоста — набор идемпотентных шагов. | git (репозиторий destiny) |
| Scenario | Destiny плюс оркестрация: на каких хостах, в каком порядке, с какими условиями. | git (репозиторий сервиса) |
| Essence | Параметры и секреты, привязанные к хосту или группе. | git (дефолты) + база (переопределения в spec) |
Как три артефакта связаны
Заголовок раздела «Как три артефакта связаны»- Destiny — атомарный кирпичик: «как привести один хост в нужное состояние». Изолирован — видит только свой объявленный вход.
- Scenario — операция над целым кластером: «как провести
create/add_user/restartнад набором хостов». Сценарий получает весь набор блоков задач Destiny плюс оркестрационную дельту (на каких хостах, в каком порядке) и может вызывать Destiny черезapply:. - Essence — значения, которые подкладываются при рендере: настройки приложения, пароли, ключи. Сценарий видит Essence напрямую; Destiny получает значения только через явный проброс на входе.
Граница между Destiny и Scenario — рекомендация, не жёсткая стена: переиспользуемое, критичное или изолируемое выносится в отдельный Destiny; одноразовая логика конкретной операции допустима инлайн в сценарии.
Модель шаблонизатора
Заголовок раздела «Модель шаблонизатора»В Soul Stack два движка выражений, и граница между ними проходит строго по файлу:
| Контекст | Движок | Маркер |
|---|---|---|
Выражения в YAML: условия (when:, where:, …) | CEL | вся строка = выражение, без обёртки |
| Интерполяция значений внутри строк YAML | CEL | ${ … } |
Файлы шаблонов с расширением .tmpl | Go text/template | {{ … }} |
В одном файле работает только один движок: CEL никогда не выполняется внутри .tmpl, text/template никогда не выполняется внутри .yml. Это не пересечение, а последовательная передача данных — CEL вычисляет значения в YAML, а затем явно поднятые значения попадают в рендер файла.
CEL — выражения в YAML
Заголовок раздела «CEL — выражения в YAML»CEL обслуживает все выражения в YAML-артефактах. Две позиции:
-
Условные ключи (
when:,where:,changed_when:,failed_when:,until:) — вся строка трактуется как CEL-выражение, без обёртки:when: input.do_restartwhere: register.role.stdout == "master" -
Интерполяция в строковых значениях (
params:,vars:, проброс на вход) — выражение оборачивается в${ … }:params:command: "redis-cli replicaof ${ register.master.stdout } 6379"replicas: "${ input.replicas * 2 }"
CEL — это движок выражений без побочных эффектов: у него нет доступа к файловой системе, командам и произвольной сети. В выражениях доступны факты хоста (soulprint.self.<путь>), параметры (input.*, essence.*), результаты предыдущих шагов (register.*) и набор встроенных функций (проверки, размер, регулярки, работа со временем).
Go text/template — рендер файлов
Заголовок раздела «Go text/template — рендер файлов»Файлы шаблонов с расширением .tmpl рендерятся движком Go text/template. Это единственное место, где он работает, и используется он только специальным шагом, который рендерит файл на хосте.
Рендер устроен безопасно по умолчанию: строгий режим (обращение к несуществующему полю — ошибка, а не пустая строка), закрытый список разрешённых функций (без выполнения команд, чтения окружения и генерации случайностей) и изолированный контекст (шаблон видит только явно поднятые значения, а не весь контекст сценария).
Секреты
Заголовок раздела «Секреты»Секреты резолвятся через Vault на стороне сервера при рендере. Движок выражений обрабатывает их как обычные значения — иначе нельзя было бы легитимно передать секрет в параметр. Маскирование применяется на выходе: в логах, трейсах, ответах API и отчётах о прогоне секреты в открытом виде не появляются.
Статическая проверка
Заголовок раздела «Статическая проверка»Артефакты можно проверить до применения офлайн-линтером soul-lint: он разбирает YAML, сверяет имена модулей и их состояний, проверяет схемы параметров и выражения — на рабочей станции или в CI, ничего не исполняя на хостах.