Руководство разработчика
Смежные документы: ARCHITECTURE.md — почему всё устроено именно так; MODULES.md — что делает каждый модуль; CONFIGURATION.md — все настройки.
Архитектура
install.sh ──┬── config/defaults.conf (настройки, всё переопределяемо env)
├── lib/core.sh (логирование, состояние, откат, systemd)
├── lib/os.sh (семейство ОС: пакеты, файрвол, PG-раскладка)
├── lib/tui.sh (виджеты: gum → whiptail → dialog → plain)
├── lib/preflight.sh (проверки окружения)
└── modules/NN-*.sh (изолированные единицы установки:
01-system … 19-pg-vip, 99-cleanup)
mitdev ───┬── те же lib/ и config/
└── /var/lib/mitdev/install.env (факты установки)
Принципы:
install.sh— оркестратор, он не знает, как ставится компонент; модуль не знает, когда и в каком порядке его запускают.- Каждый модуль выполняется в строгом subshell (
set -Eeuo pipefail). Падение модуля не убивает инсталлятор; оркестратор решает, что дальше (откат / продолжить / прервать). - Состояние — файлы. Маркеры выполнения (
/var/lib/mitdev/state/<id>.done) и стек отката (rollback.stack) переживают subshell'ы и перезапуски. - TUI и логика разделены. Модули не вызывают TUI: весь пользовательский ввод собирается оркестратором заранее и передаётся через окружение.
Контракт модуля
Файл modules/NN-имя.sh обязан определить:
MODULE_NAME="имя" # id для маркеров состояния
MODULE_DESC="Описание" # строка для UI
module_install() { ... } # установка; return != 0 — сбой
module_verify() { ... } # быстрая проверка «компонент работает»
module_rollback(){ ... } # полный откат модуля (для tests и ручного отката)
module_remove() { ... } # удаление компонента (mitdev remove <модуль>)
Правила внутри module_install:
- Каждое действие — через
run_step "описание" команда…— оно логируется и проверяется. Голые команды допустимы только для тривиальных операций с явной обработкой ошибок. - Идемпотентность обязательна: проверяйте «уже установлено/настроено»
до изменения (
pkg_installed,id user,grep -qпо конфигу…). - Мутировали систему — зарегистрируйте откат:
rollback_register "команда отмены". Откат выполняется в обратном порядке. - Не трогайте stdin/stdout для UI — модуль работает под спиннером, его вывод уходит в лог.
- Финал успешной установки:
state_mark "$MODULE_NAME". - Секреты:
generate_password+save_credential <служба> <ключ> <значение>; никогда не пишите пароли в лог.
Как добавить модуль
- Создайте
modules/19-имя.shпо контракту выше (возьмите за образец13-redis.sh— небольшой и типовой; со сложной ролевой логикой —18-postgresql-cluster.sh). - Зарегистрируйте его в
MODULE_REGISTRYвinstall.sh:"имя|19-имя.sh|no|off|Метка для UI". Зависимость от другого модуля — строкойmodule_selected имя && add_dependency зависимость "Метка". Для поддержкиmitdev remove <модуль>продублируйте строку вREMOVABLE_MODULESв файлеmitdev("имя|19-имя.sh|Метка") и реализуйтеmodule_remove()— обратную операцию кmodule_install; данные удаляйте только под[[ "${MITDEV_PURGE:-no}" == "yes" ]]. - Нужен пользовательский ввод? Добавьте отдельную фазу-опрос по образцу
collect_pg_cluster_config(вызов — вmainдоconfirm_plan), значения передавайте черезexport. - Добавьте файл в
REQUIRED_FILESи, при наличии шаблонов, в проверки плейсхолдеров вtests/smoke.sh. - Добавьте
check имя 19-имя.shвtests/verify.sh. - Заведите страницу модуля
docs/modules/<NN>-<имя>.mdпо образцу соседних (зачем нужен → что делает → файлы и порты → настройка → проверка → типовые задачи → частые ошибки → откат и удаление), добавьте строку в таблицуdocs/MODULES.md, переменные — вdocs/CONFIGURATION.md, команды — вdocs/COMMANDS.md. bash tests/smoke.shи прогон на чистой Ubuntu 22.04 (VM/LXD).
API lib/core.sh (главное)
| Функция | Назначение |
|---|---|
run_step desc cmd… |
выполнить, залогировать, проверить код выхода |
pkg_install pkgs… / apt_update |
apt с ретраями, неинтерактивно |
pkg_installed pkg |
установлен ли пакет |
svc_enable_start unit / svc_active unit |
systemd |
state_mark/state_done/state_clear id |
маркеры выполнения |
rollback_register cmd / rollback_to n |
стек отката |
render_template src dst KEY=val… |
подстановка __KEY__ |
backup_file path |
резервная копия конфига с меткой времени |
generate_password / save_credential |
секреты |
retry n delay cmd… |
повторы |
log_info/log_ok/log_warn/log_error/die |
логирование |
API lib/tui.sh
tui_init, tui_header, tui_section, tui_confirm, tui_input,
tui_password, tui_choose, tui_checklist, tui_run (спиннер),
tui_progress, tui_success_screen, tui_error_screen.
Каждый виджет реализован для gum, whiptail/dialog и plain-фолбэка.
Стиль кода
set -Eeuo pipefailв каждой исполняемой точке входа.- ShellCheck обязателен:
shellcheck -x install.sh mitdev lib/*.sh modules/*.sh(допустимые исключения — SC1090/SC1091/SC2034, см. tests/smoke.sh). - Кавычки вокруг всех подстановок;
localдля переменных функций;readonlyдля констант, где уместно. - Никаких
TODO/заглушек — smoke-тест ловит их и падает.
Локальная разработка
Тестируйте на одноразовых VM:
# LXD
lxc launch ubuntu:22.04 mitdev-test
lxc file push -r ./mitdev mitdev-test/root/
lxc exec mitdev-test -- bash -c 'cd /root/mitdev && ./install.sh'
lxc delete -f mitdev-test
# Multipass
multipass launch 22.04 -n mitdev-test
multipass transfer -r ./mitdev mitdev-test:/home/ubuntu/
multipass exec mitdev-test -- sudo bash -c 'cd /home/ubuntu/mitdev && ./install.sh'
TUI_BACKEND можно принудительно проверить, временно удалив gum
(apt remove gum) — интерфейс должен деградировать без потери функций.