Ansible Molecule — тестирование Ansible-ролей в Docker
Molecule позволяет запускать Ansible-роль в изолированном тестовом окружении.
В этом примере Molecule создаёт Docker-контейнер с Ubuntu, подготавливает его и применяет к нему тестируемую Ansible-роль.
Схема работы:
Molecule
│
├── create
│ └── создаёт Docker-контейнер
│
├── prepare
│ └── подготавливает контейнер для Ansible
│
├── converge
│ └── применяет тестируемую Ansible-роль
│
├── verify
│ └── проверяет результат
│
└── destroy
└── удаляет тестовое окружение
Требования
На управляющей машине должны быть установлены:
- Docker
- Python
- Ansible
- Molecule
- Molecule Docker plugin
Проверить Docker:
Проверить Python:
Для нового окружения лучше использовать актуальную поддерживаемую версию Python.
Создание Python virtual environment
Создадим каталог проекта:
Создадим виртуальное окружение:
Активируем:
После активации проверить:
Обновить pip:
Установить Ansible, Molecule и Docker plugin:
Проверить:
Создание Ansible-роли
Создадим каталог ролей:
Создадим роль:
Получим примерно такую структуру:
test_docker_role/
├── venv/
└── roles/
└── docker/
├── defaults/
├── files/
├── handlers/
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
├── tests/
└── vars/
Перейти в роль:
Настройка metadata роли
Molecule использует метаданные Ansible Galaxy для определения имени роли.
Открыть:
Минимальный пример:
---
galaxy_info:
role_name: docker
namespace: devopslearning
author: Andrey
description: Install and configure Docker
license: MIT
min_ansible_version: "2.15"
dependencies: []
Полное имя роли в данном случае:
Не путать:
Создание Molecule scenario
Находясь внутри:
создать scenario:
Появится:
roles/docker/
└── molecule/
└── default/
├── molecule.yml
├── create.yml
├── destroy.yml
├── converge.yml
├── prepare.yml
└── ...
Warning
В новых версиях Molecule команда из старых руководств:
может не работать.
Например:
Использовать:
Настройка molecule.yml
Открыть:
Минимальная конфигурация:
---
driver:
name: docker
platforms:
- name: instance
image: ubuntu:24.04
pre_build_image: true
provisioner:
name: ansible
Здесь:
| Параметр | Назначение |
|---|---|
driver |
тип тестового окружения |
docker |
использовать Docker |
platforms |
список тестовых машин |
instance |
имя тестового экземпляра |
image |
Docker image |
provisioner |
чем конфигурировать instance |
Создание Docker-контейнера
В некоторых версиях/сценариях Molecule create.yml создаётся как generic-заготовка.
Например, можно увидеть:
Сам по себе такой файл контейнер не создаёт.
Для минимального локального сценария можно создать контейнер через Ansible.
molecule/default/create.yml:
---
- name: Create
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Create Molecule container
community.docker.docker_container:
name: instance
image: ubuntu:24.04
state: started
command: sleep infinity
После этого:
Проверить:
Должен существовать контейнер:
Подготовка контейнера
Обычный образ:
минимальный и может не содержать Python.
Это проблема для Ansible, потому что большинство Ansible-модулей выполняются на target через Python.
Без Python можно получить:
или ошибку на:
Получается bootstrap-проблема:
Ansible
│
├── хочет использовать apt module
│
└── apt module требует Python
│
└── Python ещё не установлен
Для первоначальной установки Python используется raw, поскольку raw не требует Python на удалённой системе.
Создать:
---
- name: Prepare
hosts: all
gather_facts: false
tasks:
- name: Install Python
ansible.builtin.raw: apt-get update && apt-get install -y python3
changed_when: false
Важно:
Пока Python не установлен, Ansible не сможет нормально выполнить сбор facts.
Запустить:
Подключение тестируемой роли
Настроить:
---
- name: Converge
hosts: all
gather_facts: true
become: true
tasks:
- name: Apply Docker role
ansible.builtin.include_role:
name: devopslearning.docker
Важно использовать имя роли:
а не:
default — это имя Molecule scenario, а не namespace Ansible-роли.
Первый полный запуск
Для чистого теста:
Последовательность:
molecule destroy
│
▼
удалить старое окружение
molecule create
│
▼
создать Ubuntu container
molecule prepare
│
▼
установить Python
molecule converge
│
▼
применить devopslearning.docker
Успешный converge выглядит примерно так:
TASK [Gathering Facts]
ok: [instance]
TASK [Apply Docker role]
included: devopslearning.docker for instance
TASK [devopslearning.docker : ...]
changed: [instance]
PLAY RECAP
instance : ok=3 changed=1 failed=0
Главное:
и:
Повторный запуск
После первого успешного запуска:
Molecule не обязан пересоздавать контейнер.
Если instance уже существует, можно увидеть:
А если prepare уже выполнялся:
После чего выполняется непосредственно:
Проверка идемпотентности
Ansible-роль должна по возможности быть идемпотентной.
Первый запуск:
может быть нормальным — система конфигурируется.
При повторном запуске желательно получить:
То есть:
Первый запуск
Ubuntu
↓
роль
↓
Docker установлен
↓
changed > 0
Второй запуск
Ubuntu + Docker
↓
та же роль
↓
система уже в нужном состоянии
↓
changed = 0
Для ручной проверки:
Проверка состояния контейнера
Посмотреть контейнер:
Все контейнеры, включая остановленные:
Зайти внутрь:
Также при корректно настроенном scenario можно использовать:
Удаление тестового окружения
После тестирования:
Проверить:
Тестовый instance должен быть удалён.
Полный lifecycle
В итоге Molecule используется примерно так:
Назначение этапов:
| Этап | Назначение |
|---|---|
dependency |
установить зависимости роли |
create |
создать тестовое окружение |
prepare |
подготовить окружение |
converge |
применить тестируемую роль |
idempotence |
проверить повторное применение |
verify |
проверить результат |
destroy |
удалить окружение |
Полезные команды
Создать окружение:
Подготовить:
Применить роль:
Войти в instance:
Посмотреть состояние:
Удалить:
Полный тестовый цикл:
Типовые ошибки
No such option '-d'
Старые руководства могут использовать:
В используемой версии Molecule такой параметр отсутствует.
Использовать:
а driver определить в molecule.yml.
docker ps пуст после molecule create
Проверить:
Если там находится:
то это generic create.yml, который фактически не создаёт Docker-контейнер.
Проверить вывод:
Важно: успешный return code create.yml ещё не гарантирует, что Docker-контейнер действительно был создан.
/usr/bin/python3 was not found
Пример:
Причина:
Решение — установить Python на этапе prepare через:
The role 'default.docker' was not found
Причина — перепутано имя scenario и имя роли.
Использовать:
Molecule использует старые версии
Проверить:
Также:
Старый Python может ограничивать версии устанавливаемых Python-пакетов.
Посмотреть доступные версии:
Если virtual environment был создан старым Python, простого:
может быть недостаточно.
Нужно пересоздать venv современным Python:
deactivate
rm -rf venv
python3 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
python -m pip install ansible-core molecule "molecule-plugins[docker]"
После этого проверить:
Итоговая структура
После настройки:
test_docker_role/
├── venv/
└── roles/
└── docker/
├── defaults/
├── handlers/
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
├── vars/
└── molecule/
└── default/
├── molecule.yml
├── create.yml
├── prepare.yml
├── converge.yml
├── verify.yml
└── destroy.yml
Главная идея:
Molecule позволяет уничтожать и пересоздавать тестовую систему сколько угодно раз, не затрагивая рабочие серверы.
Это позволяет разрабатывать роль по циклу: