Comments 15
Молекула мертва, потому что её highly opinionated не работает IRL.
1) Большинство людей хочет проверять плейбуки, а не роли.
2) Тесты для тривиальных ролей писать особо не надо, а для нетривиальных у молекулы нет никаких возможностей правильно описать нетривиальность (например, внешние зависимости).
3) Драйвера ужасны. Любая роль, выходящая за рамки "ой мы тут сделали file: state=directory
и нам надо написать ТЕСТЫ ДЛЯ ЭТОЙ РОЛИ" тут же утыкается в то, что докер на сервера похож, мягко говоря, не совсем — привет systemd, привет reboot, привет ntp, привет /etc/hosts, и т.д. А попытка поменять драйвер с контейнерного на (хотя бы виртуалки) открывает бездны нового порядка. Например, плейбука для подъёма драйвера пишется в /tmp и используется оттуда, даже если драйвер поменяли. (Перезагрузите компьютер, чтобы всё начало работать).
Для модулей ansible-test куда более годный инструмент, хоть он и тащит много лишнего по полиси (например, требование специальных путей откуда можно запускать).
Для плейбук же ничего годного нет, приходится всё самому изобретать.
Я мельком её (его?) смотрел. Их подход работает для простых случаев, а в них и так всё хорошо. В сложных случаях же выкрутасы с ещё одним template language — ой, не надо.
Мы используем testinfra, у которой помимо мощи pytest'а под капотом ещё какая-никакая интеграция с ansible'ом (можно использовать инвентори и дёргать модули в checkmode'е, а если очень хочется, то можно и транспорт ансибла использовать).
Если бы в ансибле роли были аналогом функций, жизнь была бы сильно проще. Но это не так. Функции принимают значение, имеют локальные перменные и могут вернуть значение. Как мне вернуть значение из функции без сайд-эффектов в глобальных перменных? Я бы очень не отказался от такого синтакиса:
- call_role: rolename
return_variable: foo
И внутри роли - return: somevalue
к сожалению, ничего этого нет. Вместо этого у нас глобальные переменные с несовместимыми lifetimes.
Насчёт моего окружения вы правы. Взял молекулу, взял ансибл, сказал запускать на libvirt'е, а потом поменял драйвер на openstack, а libvirt всё ещё используется, потому что записано в /tmp (и имеет больший приоритет, чем то, что в плейбуке). Я один день на это "моё окружение" потратил и полностью для себя молекулу закопал.
Основная же проблема в том, что reusable roles в отсутствии изоляции — необоснованная фантазия. Это легко заметить по, например, даже rhel'овому коду для ансибла — openshift, ceph-ansible — у обоих всё, мягко говоря, не в рамках мечтаний о "reusable roles". Роль обычно пишется под задачу и в отсутствии задачи смысла не имеет. А тогда уже надо плейбуки тестировать.
Насчёт непонимания анисбла — да, спасибо, это вы точно заметили. Каждый раз, когда я в ansible bingo дописываю пример, я глубоко не понимаю как это можно понимать.
Скажите, сколько живёт переменная, заданная в task/vars? А переменная, заданная в play/vars? А set_fact? А если переменная set_fact из include? А если переменная из role/defaults, которая была include?
Вы знаете, мы очень много пишем на ансибле, и у нас сложилась очень сильная практическая школа. Один из принципов этой школы состоит в том, что чем проще, тем лучше (даже если решение будет неуниверсальным). Это значает, что никаких include_vars в зависимости от переменных, никогда не используется include_role, а include_tasks в loop — это code smell (который иногда нужен, но которого надо избежать). И один из принципов говорит, что нельзя бороться за универсализацию ролей. Чем более универсальна роль, тем более волшебным образом она взрывается.
Вообще, максима написания кода на Ансибле — чем меньше решений принимается на Ансибле, тем лучше. Анисбл — отличный транспорт и механизм для сайд-эффектов, но совершеннейший кошмар для программирования (принятия решений). Каждый when — это плохо. Каждый and или вложенное условие — это плохо.
Когда же вы следуете практике максимальной специализации роли, оказывается, что в отрыве от плейбуки она не особо и нужна. Так что тестировать надо плейбуки.
(Вот вам контр-пример того, как писать не надо — роль пытается принимать стопятьсот решений https://github.com/AlexeySetevoi/ansible-clickhouse/blob/master/tasks/main.yml… и взрывается, если процесс решений не совсем такой, как ожидали. Например, case sensitive file system. Баг до сих пор не заслали, но он там есть).
Ну вот видите, вроде, согласились, а потом строго наоборот перевернули. Вы говорите расхожую unix-истину "хорошо умеет делать что-то одно". Не хорошо, а минимально необходимо. Роль для postgress не умеет "хорошо настраивать постгресс", а настраивает только то, что нужно в проекте. Это снижает сложность ролей на несколько порядков и именно в этом месте попытка писать роли как программы или функции (которые делают одно, но делают хорошо), натыкается на полное отсутствие изоляции. Одна ошибка в именновании приватной перменной (ой, у нас же нет приватных перменных) и роль взрывает проект из-за того, что еёйный set_fact с database_ip оверрайдит roles/vars/database_ip в другой роли. Разумеется, существует техника defensive programming по именованию приватных переменных в роли (что увеличивает нагрузку на пишущего в несколько раз); но лучший выход из ситуации — не пытаться делать "хорошо", а делать минимально необходимое без запаса на расширение. Нужно расширение — перепиши простой предыдущий код. Это легче, чем сопровождать универсальный код.
То есть проблемы с изоляцией имён не существует. В питоне есть локальные переменные, в Ансибле нет, "но в ведь в питоне приватные перменные тоже underscore обозначают".
Насчёт "прописать IP" — этот вопрос мы ещё даже близко не затронули, потому что всё что касается хождения по чужим перменным — боль и постоянная балансировка между кривым решением, code smell и лапшой.
В целом я вашу позицию понял — вы проблем не видите, а всё остальное — моя некомпетентность. Ваша позиция мне ясна, менять её у меня стимула нет.
В итоге, как тестируете ansible роли/playbook? Молекулой с драйвером libvirt?
Я уже плохо помню этот диалог, UFO половину происходящего потёрла.
Сейчас мы остановились на связке молекулы и openstack. У нас есть хорошо написанные (под наш openstack) плейбуки на create/delete, которые переиспользуются в каждом проекте с молекулой. Для некоторых проектов (которые не могут работать в виртуалках) есть эквивалентная оснастка для переустановки baremetal-серверов.
Тестируются в основном куски кода (уровня плейбук). Окажись я в другой среде, я бы взял любого cloud-подобного провайдера, а принцип оставил бы тем же.
Основная проблема, с которой мы боролись - это "последовательность изменений" (проверить плейбуки на выживаемость после ребута/развала кластера и т.д.).
Я недавно затащил в молекулу поддержку нескольких сайд-эффектов (пока ещё в мастере) - это должно решить проблему.
молекулой можно тестить плэйбуки. но это не удобно. делаешь "мета-роль", в которую подсовываешь вместо converge.yml свой плэйбук. шатко, хлипко… я если честно таким образом плэйбуки не тестирую.
Но тут стоит прокомментировать, у меня плэйбуки обычно максимально простые: состоят из нескольких плэев, в которых нет тасков, только инклюд ролей. как итог достаточно тестить отдельные роли, а плэйбуки линтить. но подозреваю
- это далеко не каждому сможет подойти
- не отменяет проблем с systemd, reboot итд
Разработка и тестирование Ansible-ролей с использованием Molecule и Podman