Тестирование состояний
Тема дорожной карты · SaltStack
Линтер отвечает только за аккуратность кода; следующий вопрос — приводят ли состояния систему в нужный вид. У Salt для этого есть два взаимодополняющих инструмента. Первый встроенный — режим test=True, который прогоняет состояния «вхолостую» и показывает план изменений на реальной машине. Второй — интеграционное тестирование в одноразовых окружениях: kitchen-salt (плагин к Test Kitchen) создаёт чистый контейнер или виртуальную машину, применяет к ней состояния, а testinfra — pytest-плагин для проверки серверов — убеждается, что результат совпадает с ожиданиями. Вместе они закрывают обе стороны вопроса: «что изменится на проде» и «действительно ли состояние работает на чистой системе».
Как это работает
Dry-run запускается как salt '*' state.apply test=True (или локально через salt-call). Salt рендерит SLS, строит список состояний и для каждого сообщает, что было бы изменено; у состояний с ожидающими изменениями результат помечается как None — «изменится при реальном прогоне». Система при этом не трогается. Интеграционный цикл описывается файлом .kitchen.yml: в нём задаются платформы (например, Docker-образы нескольких дистрибутивов), применяемые состояния и pillar-данные для теста. Команда kitchen converge создаёт окружение и применяет состояния, kitchen verify запускает проверки, kitchen test выполняет полный цикл с удалением окружения в конце. Проверки пишутся на Python с фикстурами testinfra: host.package("nginx").is_installed, host.service("nginx").is_running, host.socket("tcp://443").is_listening — читается почти как спецификация.
Когда применять
test=True — инструмент повседневный: перед любой выкаткой на прод, при отладке нового состояния, при проверке, не разъехался ли парк с описанным состоянием (запуск по расписанию с алертом на непустой план — дешёвый детектор дрейфа). Kitchen-цикл дороже в поддержке, поэтому его заводят там, где отдача максимальна: переиспользуемые формулы, которые должны работать на нескольких дистрибутивах (матрица платформ в .kitchen.yml проверяет все сразу), и критичные роли, регрессия в которых бьёт по всему парку. Для маленького репозитория из пары состояний достаточно линтера и дисциплины test=True; полноценные тесты добавляйте, когда состояния начинают переиспользоваться или меняться чаще раза в неделю.
Типичные ошибки
Переоценивать test=True: dry-run не исполняет cmd.run, поэтому цепочка, где второе состояние зависит от результата первого, в тестовом режиме выглядит иначе, чем при реальном применении. Гонять kitchen только в Docker: в минимальных образах нет systemd, и service.running там либо падает, либо проверяет не то — для сервисных состояний нужен образ с init-системой или полноценная ВМ. Забывать pillar в тестовой конфигурации: состояние, отрендеренное с пустым pillar, — это другое состояние. И писать проверки, дублирующие SLS: тест package.is_installed после pkg.installed почти бесполезен — проверяйте поведение системы: сервис отвечает, порт слушается, конфиг валиден.
Связанные понятия
Полезные ресурсы
Проверить знания (2)
Загрузка вопросов…