Molecule — тестирование Ansible-ролей

Продолжительность: 17 уроков · Уровень: средний

Molecule — это фреймворк для разработки и тестирования Ansible-ролей. Он поднимает временное окружение (контейнер или виртуальную машину), прогоняет на нём роль и проверяет результат. Так ошибки ловятся локально, до попадания в продакшн.

1. Что такое Molecule

Molecule автоматизирует стандартный цикл разработки роли:

  1. создать каркас роли с тестами;
  2. поднять тестовое окружение (Docker, Vagrant, podman);
  3. применить роль (converge);
  4. проверить результат (verify);
  5. проверить идемпотентность — повторный запуск не должен менять систему;
  6. удалить окружение (destroy).
Идемпотентность — ключевое свойство хорошей роли: сколько раз ни запускай её, состояние системы не меняется сверх одного раза.

2. Установка

Molecule — это Python-пакет. Устанавливается вместе с драйвером Docker:

python3 -m venv .venv
source .venv/bin/activate
pip install molecule molecule-docker ansible-core ansible-lint yamllint

Проверка установки

molecule --version

3. Создание роли и сценария

molecule init role myapp --driver docker

Команда создаёт стандартную структуру:

myapp/
├── tasks/
│   └── main.yml
├── handlers/
├── templates/
├── vars/
├── defaults/
│   └── main.yml
├── meta/
└── molecule/
    └── default/
        ├── molecule.yml
        ├── converge.yml
        └── verify.yml

4. Сценарий и molecule.yml

Каждый сценарий (scenario) описывает окружение и шаги тестирования. Основной файл — molecule.yml:

---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: instance
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: ansible

Поля

ПолеЧто делает
dependencyподтягивает зависимости роли (galaxy)
driverпровайдер окружения: docker, podman, vagrant
platformsсписок «машин» для теста
provisionerисполнитель, обычно ansible
verifierинструмент проверки: ansible, testinfra, goss

5. Команды сценария

molecule converge   # применить роль к окружению
molecule verify     # запустить проверки
molecule idempotence # прогнать и убедиться, что ничего не меняется
molecule test       # полный цикл: dependency -> create -> converge -> verify -> destroy
molecule destroy    # удалить окружение
molecule list       # показать текущие инстансы
В повседневной разработке удобен цикл molecule converge + molecule verify: окружение остаётся запущенным, пока ты правишь роль и перепроверяешь её.

6. Проверки на Testinfra

Для тестов удобно использовать testinfra — Python-библиотеку, которая проверяет состояние машины:

# molecule/default/tests/test_default.py
import testinfra.utils.ansible_runner as ansible_runner

testinfra_hosts = ansible_runner.AnsibleRunner(
    ansible_inventory_path='inventory'
).get_hosts('all')

def test_service(host):
    service = host.service('nginx')
    assert service.is_enabled
    assert service.is_running

def test_port(host):
    assert host.socket('tcp://0.0.0.0:80').is_listening

В molecule.yml переключи проверку на testinfra:

verifier:
  name: testinfra
  pip:
    - pytest

7. Проверка идемпотентности и линтинг

molecule idempotence прогоняет роль дважды. Если второй запуск вносит изменения — команда падает. Это сигнал, что роль написана не идемпотентно: она не описывает желаемое состояние (например, через state=present), а каждый раз вносит изменения.

Линтеры следят за качеством кода:

ansible-lint tasks/main.yml   # проверка стиля и ошибок
yamllint molecule/default/molecule.yml  # проверка YAML
molecule lint # линт внутри сценария

8. Конфигурация снаружи

Variable-интерполяцию и environment можно задать в блоке env:

scenario:
  name: default
driver:
  name: docker
env:
  ANSIBLE_ROLES_PATH: ../../..

Для разных окружений создаются отдельные сценарии:

molecule init scenario --scenario-name ubuntu22
molecule test --scenario-name ubuntu22

9. Molecule в CI

Сценарий легко встроить в пайплайн GitLab CI:

test-role:
  stage: test
  image: python:3.11
  services:
    - docker:dind
  before_script:
    - pip install molecule molecule-docker ansible-core
  script:
    - molecule test
В CI рекомендуется сразу использовать полный molecule test, а не отдельные команды — так окружение гарантированно удаляется даже при падении.

10. Драйверы и платформы

Molecule работает поверх разных драйверов: docker (по умолчанию), podman, vagrant (полные виртуальные машины), delegated и облачные платформы. Выбор описывается в molecule.yml:

driver:
  name: docker
platforms:
  - name: ubuntu-22.04
    image: ubuntu:22.04
    pre_build_image: true
  - name: debian-12
    image: debian:12
    pre_build_image: true
С pre_build_image: true образ обязан уже содержать Python и нужный интерпретатор Ansible — иначе проверка упадёт на старте.

11. Переменные, группы и факты

Реальные роли зависят от инвентаря: группами хостов и host_vars управляет раздел inventory в конфигурации:

platforms:
  - name: app-1
    image: ubuntu:22.04
    groups:
      - app_servers
provisioner:
  name: ansible
  inventory:
    host_vars:
      app-1:
        app_port: 8080

Так тестируется поведение роли, которое зависит от групповых переменных: например, разные версии пакета для серверов приложений и баз данных.

Дополнительные факты передаются ключом ansible.extra_vars, а зависимости роли подтягиваются через dependencies в сценарии.

12. Сценарий как инструмент

Команды сценария дают точечный контроль без уничтожения окружения:

molecule create      # поднять платформы
molecule converge    # применить роль
molecule verify      # прогнать тесты
molecule destroy     # удалить окружения

molecule converge полезен для отладки: можно повторно применить роль, посмотреть вывод и исправить роль без пересоздания контейнеров.

Пока роль разрабатывается, запускай только molecule converge: тесты добавляем, когда поведение уже устоит. Это экономит минуты на каждой итерации.

13. Molecule в зрелом пайплайне

Проверка роли не ограничивается одним прогоном — производственный подход состоит из нескольких слоёв:

Что проверяетсяИнструмент
Стиль и синтаксис ролиansible-lint, yamllint
Поведение роли в окруженииmolecule test
Идемпотентностьдвойной converge + verify
Чистота окружений в CIdocker image prune

Храни сценарии под разные дистрибутивы и собирай матрицу в CI, а сами шаги раскатывай параллельно — так регрессии ловятся до мержа роли.

Если ролей много, объединяй проверки: один pipeline тянет несколько каталогов ролей через molecule test --all и отчитывается одной сборкой.

14. Docker-окружение: сети и тома

Роль редко живёт в изоляции: ей нужны базы, кэши и внешние сервисы в той же сети. Molecule отдаёт управление окружением Docker — сети, тома и лимиты настраиваются в molecule.yml:

platforms:
  - name: app
    image: debian:12
    networks:
      - name: molecule-net
    volumes:
      - ./shared:/shared
Порты публикуются только явно: 8080:80. Случайный проброс всего порта — дыра в изолированном сценарии.

15. Интеграция с реальными зависимостями

Роли часто требуют внешние ресурсы: базу данных, брокер, внешние API. Molecule объединяется с Docker-композицией и другими сервисами, чтобы проверить взаимосвязь:

platforms:
  - name: app
    image: centos:stream8
    networks:
      - name: shared-net
Будь осторожен с коллизиями портов и файловых путей между контейнерами: одинаковые volume-монтирования легко ломают прогон, который вчера работал.

16. Pre-commit и линтеры до прогона

Быстрая проверка до «тяжёлого» прогона экономит циклы CI: синтаксис и стиль ловятся за секунды, а не минуты контейнера. Pre-commit запускает хуки локально в момент коммита:

pre-commit run --all-files  # прогнать все хуки
pre-commit autoupdate        # обновить версии хуков
Настрой pre-commit так, чтобы он не «молча» чинил всё подряд: правила должны быть консистентны с вашим кодстайлом, иначе автокоррект исказит смысл дифов.

17. Отладка неудачных прогонов

Сломанная роль не всегда видна по первому логу. Отладка — это последовательная изоляция слоёв: сначала провайдер, затем роли, затем проверки:

molecule login -s default   # войти в контейнер
molecule converge            # повторить приложение (без конвергенции)
Прокачивай диагностику: ANSIBLE_VERBOSITY=3 и лог-файлы дают контекст, а не просто конечную ошибку. Слова «no hosts matched» почти всегда означают несовпадение групп в inventory.

Что дальше

Углубляйся в Ansible, научись писать роли, затем добавь Terraform для инфраструктуры и Docker для окружений. Обзор всех курсов — на главной странице.

← Вернуться к курсам