Тестирование инфраструктурного кода так же критично, как и тестирование кода приложений, однако это часто упускается из виду. Когда ваши playbook’и Ansible разворачиваются в продакшн, насколько вы уверены, что они будут работать корректно? Здесь на помощь приходит Molecule—мощный фреймворк тестирования, разработанный специально для ролей Ansible. В этом комплексном руководстве вы узнаете, как реализовать надежные стратегии тестирования для вашей автоматизации Ansible, от базового тестирования ролей до сложных валидаций множественных сценариев. Независимо от того, управляете ли вы несколькими серверами или оркестрируете тысячи узлов, Molecule трансформирует то, как вы разрабатываете и поддерживаете вашу инфраструктуру как код.

Предварительные Требования

Перед погружением в Molecule убедитесь, что у вас настроено следующее:

Необходимые Инструменты:

  • Python 3.8 или выше
  • Ansible 2.10 или выше
  • Docker (для тестирования на основе контейнеров)
  • pip (менеджер пакетов Python)

Требования к Знаниям:

  • Базовый опыт с Ansible (роли, задачи, handlers)
  • Знакомство с синтаксисом YAML
  • Понимание концепций Docker
  • Владение командной строкой

Настройка Окружения: Я рекомендую создать выделенное виртуальное окружение Python, чтобы избежать конфликтов зависимостей:

python3 -m venv molecule-env
source molecule-env/bin/activate  # На Windows: molecule-env\Scripts\activate

Шаг 1: Установка Molecule

Установка Molecule проста с помощью pip. Вам нужно установить Molecule вместе с драйвером Docker, который мы будем использовать для наших сценариев тестирования.

# Установить Molecule с поддержкой Docker
pip install "molecule[docker,lint]"

# Проверить установку
molecule --version

Ожидаемый Вывод:

molecule 5.0.1 using python 3.11
    ansible:2.15.4
    default:5.0.1 from molecule
    docker:2.1.0 from molecule_plugins.docker

Установка включает несколько компонентов:

  • Ядро Molecule: Сам фреймворк тестирования
  • Драйвер Docker: Обеспечивает тестирование на основе контейнеров
  • Инструменты линтинга: Ansible-lint и yamllint для качества кода

Контрольная Точка: Выполните molecule --version и подтвердите, что все компоненты установлены. Если драйвер Docker отсутствует, переустановите с дополнением [docker].

Шаг 2: Инициализация Новой Роли

Давайте создадим практический пример: роль веб-сервера Nginx. Molecule бесшовно интегрируется со структурой ролей Ansible Galaxy.

# Создать новую роль со встроенным тестированием Molecule
molecule init role nginx --driver-name docker

# Перейти в каталог роли
cd nginx

Эта команда генерирует полную структуру роли:

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

Ключевые Каталоги:

  • molecule/default/: Содержит конфигурацию вашего сценария тестирования
  • tasks/main.yml: Здесь размещаются ваши задачи Ansible
  • handlers/main.yml: Для перезапуска сервисов и уведомлений

Шаг 3: Понимание Структуры Molecule

Каталог molecule/default/ содержит три критических файла:

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: Управляет зависимостями ролей из Ansible Galaxy
  • driver: Указывает Docker для создания тестовых экземпляров
  • platforms: Определяет тестовые окружения (ОС, образ, ресурсы)
  • provisioner: Использует Ansible для применения вашей роли
  • verifier: Запускает проверочные тесты после конвергенции

converge.yml - Применяет вашу роль к тестовым экземплярам:

---
- name: Converge
  hosts: all
  become: true
  tasks:
    - name: "Include nginx"
      include_role:
        name: "nginx"

verify.yml - Содержит утверждения для валидации поведения роли:

---
- name: Verify
  hosts: all
  gather_facts: false
  tasks:
    - name: Example assertion
      ansible.builtin.assert:
        that: true

Шаг 4: Написание Первого Теста

Давайте построим функциональную роль Nginx с правильными тестами. Начните с определения задач роли.

tasks/main.yml:

---
# Установить веб-сервер Nginx
- name: Install Nginx package
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: yes
  notify: Start nginx

- name: Ensure Nginx is started and enabled
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

- name: Deploy custom index.html
  ansible.builtin.copy:
    content: |
      <html>
      <head><title>Ansible Managed</title></head>
      <body><h1>Deployed with Ansible</h1></body>
      </html>
    dest: /var/www/html/index.html
    owner: www-data
    group: www-data
    mode: '0644'

handlers/main.yml:

---
- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started

Теперь создайте осмысленные проверочные тесты в molecule/default/verify.yml:

---
- name: Verify
  hosts: all
  gather_facts: true
  tasks:
    - name: Check if Nginx is installed
      ansible.builtin.package_facts:
        manager: auto

    - name: Assert Nginx package is present
      ansible.builtin.assert:
        that:
          - "'nginx' in ansible_facts.packages"
        fail_msg: "Nginx package is not installed"
        success_msg: "Nginx package is correctly installed"

    - name: Check if Nginx service is running
      ansible.builtin.service_facts:

    - name: Assert Nginx service is active
      ansible.builtin.assert:
        that:
          - "ansible_facts.services['nginx.service'].state == 'running'"
          - "ansible_facts.services['nginx.service'].status == 'enabled'"
        fail_msg: "Nginx service is not running or not enabled"
        success_msg: "Nginx service is active and enabled"

    - name: Check if Nginx is listening on port 80
      ansible.builtin.wait_for:
        port: 80
        timeout: 5

    - name: Verify custom index.html content
      ansible.builtin.uri:
        url: http://localhost
        return_content: yes
      register: webpage

    - name: Assert webpage contains expected content
      ansible.builtin.assert:
        that:
          - "'Deployed with Ansible' in webpage.content"
        fail_msg: "Custom index.html was not deployed correctly"
        success_msg: "Custom index.html is correctly deployed"

Шаг 5: Запуск Тестов

Molecule предоставляет полный жизненный цикл тестирования. Вот как выполнить тесты:

# Запустить полную последовательность тестирования
molecule test

# Или запустить отдельные шаги:
molecule create    # Создать тестовые экземпляры
molecule converge  # Применить вашу роль
molecule verify    # Запустить проверочные тесты
molecule destroy   # Очистить экземпляры

Полная Последовательность Тестирования:

Когда вы запускаете molecule test, Molecule выполняет эти фазы:

  1. Dependency: Установка зависимостей ролей из Ansible Galaxy
  2. Lint: Проверка синтаксиса и лучших практик
  3. Cleanup: Удаление предыдущих тестовых экземпляров
  4. Destroy: Обеспечение чистого состояния
  5. Create: Создание тестовых контейнеров
  6. Prepare: Опциональные шаги предварительной настройки
  7. Converge: Применение вашей роли
  8. Idempotence: Повторный запуск для обеспечения отсутствия изменений
  9. Verify: Запуск проверочных тестов
  10. Destroy: Очистка ресурсов

Ожидаемый Вывод (сокращенно):

--> Test matrix

└── default
    ├── dependency
    ├── cleanup
    ├── destroy
    ├── create
    ├── prepare
    ├── converge
    ├── idempotence
    ├── verify
    └── destroy

--> Scenario: 'default'
--> Action: 'converge'

    PLAY [Converge] ********************************************************

    TASK [Include nginx] ***************************************************
    included: /Users/user/nginx/tasks/main.yml

    TASK [Install Nginx package] *******************************************
    changed: [instance]

    TASK [Ensure Nginx is started and enabled] *****************************
    changed: [instance]

    PLAY RECAP *************************************************************
    instance: ok=3 changed=2 unreachable=0 failed=0

--> Scenario: 'default'
--> Action: 'verify'

    TASK [Assert Nginx service is active] **********************************
    ok: [instance] => {
        "msg": "Nginx service is active and enabled"
    }

Совет по Рабочему Процессу Разработки: Во время разработки используйте molecule converge повторно для применения изменений без уничтожения экземпляров. Запускайте полный molecule test только когда готовы валидировать всё.

Шаг 6: Тестирование с Различными Сценариями

Реальная инфраструктура редко работает на одной ОС. Сценарии Molecule позволяют тестировать на нескольких платформах одновременно.

Создайте мультиплатформенный сценарий, изменив molecule/default/molecule.yml:

---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: ubuntu-20-04
    image: geerlingguy/docker-ubuntu2004-ansible:latest
    pre_build_image: true
  - name: ubuntu-22-04
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    pre_build_image: true
  - name: debian-11
    image: geerlingguy/docker-debian11-ansible:latest
    pre_build_image: true
provisioner:
  name: ansible
  playbooks:
    converge: converge.yml
    verify: verify.yml
verifier:
  name: ansible

Создание Именованных Сценариев:

Вы также можете создать полностью отдельные тестовые сценарии для различных случаев использования:

# Создать сценарий типа production
molecule init scenario production

# Создать сценарий для тестирования обновлений
molecule init scenario upgrade

Это создаёт:

molecule/
├── default/
│   ├── converge.yml
│   ├── molecule.yml
│   └── verify.yml
├── production/
│   ├── converge.yml
│   ├── molecule.yml
│   └── verify.yml
└── upgrade/
    ├── converge.yml
    ├── molecule.yml
    └── verify.yml

Запуск Конкретных Сценариев:

# Тестировать только сценарий production
molecule test -s production

# Конвергировать множественные сценарии
molecule converge --all

Шаг 7: Интеграция CI/CD

Molecule бесшовно интегрируется с пайплайнами непрерывной интеграции. Вот как настроить его с GitHub Actions.

.github/workflows/molecule.yml:

---
name: Molecule Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        scenario:
          - default
          - production

    steps:
      - name: Check out code
        uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install "molecule[docker,lint]"
          pip install ansible

      - name: Run Molecule tests
        run: molecule test -s ${{ matrix.scenario }}

Конфигурация GitLab CI (.gitlab-ci.yml):

---
stages:
  - test

molecule:
  stage: test
  image: geerlingguy/docker-ubuntu2204-ansible:latest
  services:
    - docker:dind
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  before_script:
    - pip install "molecule[docker,lint]"
  script:
    - molecule test --all
  only:
    - merge_requests
    - main

Контрольная Точка: Отправьте вашу роль в Git репозиторий и проверьте, что CI пайплайн выполняется успешно. Убедитесь, что все сценарии проходят и пайплайн падает при ошибках тестов.

Примеры из Реального Мира

Пример 1: Тестирование Роли Веб-Сервера

Давайте расширим нашу роль Nginx с конфигурацией SSL и виртуальными хостами.

tasks/main.yml (расширенный):

---
- name: Install Nginx and SSL dependencies
  ansible.builtin.apt:
    name:
      - nginx
      - openssl
    state: present
    update_cache: yes

- name: Create SSL directory
  ansible.builtin.file:
    path: /etc/nginx/ssl
    state: directory
    mode: '0755'

- name: Generate self-signed SSL certificate
  ansible.builtin.command:
    cmd: >
      openssl req -x509 -nodes -days 365 -newkey rsa:2048
      -keyout /etc/nginx/ssl/nginx.key
      -out /etc/nginx/ssl/nginx.crt
      -subj "/C=US/ST=State/L=City/O=Org/CN=localhost"
    creates: /etc/nginx/ssl/nginx.crt

- name: Deploy SSL virtual host configuration
  ansible.builtin.template:
    src: vhost-ssl.conf.j2
    dest: /etc/nginx/sites-available/default
    mode: '0644'
  notify: Reload nginx

- name: Ensure Nginx is started
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

templates/vhost-ssl.conf.j2:

server {
    listen 80;
    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

molecule/default/verify.yml (расширенный):

---
- name: Verify
  hosts: all
  gather_facts: true
  tasks:
    - name: Check SSL certificate exists
      ansible.builtin.stat:
        path: /etc/nginx/ssl/nginx.crt
      register: ssl_cert

    - name: Assert SSL certificate is present
      ansible.builtin.assert:
        that:
          - ssl_cert.stat.exists
          - ssl_cert.stat.mode == '0644'

    - name: Verify Nginx is listening on HTTPS
      ansible.builtin.wait_for:
        port: 443
        timeout: 5

    - name: Test HTTPS connection
      ansible.builtin.uri:
        url: https://localhost
        validate_certs: no
        return_content: yes
      register: https_response

    - name: Assert HTTPS is working
      ansible.builtin.assert:
        that:
          - https_response.status == 200

Пример 2: Тестирование Конфигурации Базы Данных

Вот как протестировать роль PostgreSQL с Molecule.

molecule/default/molecule.yml:

---
platforms:
  - name: postgres-instance
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    pre_build_image: true
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    privileged: true
    command: /lib/systemd/systemd

tasks/main.yml (роль PostgreSQL):

---
- name: Install PostgreSQL
  ansible.builtin.apt:
    name:
      - postgresql
      - postgresql-contrib
      - python3-psycopg2
    state: present
    update_cache: yes

- name: Ensure PostgreSQL is started
  ansible.builtin.service:
    name: postgresql
    state: started
    enabled: yes

- name: Create application database
  become_user: postgres
  community.postgresql.postgresql_db:
    name: appdb
    state: present

- name: Create database user
  become_user: postgres
  community.postgresql.postgresql_user:
    name: appuser
    password: "{{ db_password | default('changeme') }}"
    db: appdb
    priv: ALL
    state: present

molecule/default/verify.yml:

---
- name: Verify
  hosts: all
  become: true
  tasks:
    - name: Check PostgreSQL service status
      ansible.builtin.service_facts:

    - name: Assert PostgreSQL is running
      ansible.builtin.assert:
        that:
          - "ansible_facts.services['postgresql.service'].state == 'running'"

    - name: Verify database exists
      become_user: postgres
      community.postgresql.postgresql_query:
        db: appdb
        query: SELECT 1
      register: db_check

    - name: Assert database is accessible
      ansible.builtin.assert:
        that:
          - db_check is succeeded

    - name: Test database connection with user
      become_user: postgres
      community.postgresql.postgresql_query:
        db: appdb
        login_user: appuser
        query: CREATE TABLE test (id serial PRIMARY KEY, name varchar(50))
      register: table_creation

    - name: Assert user has correct privileges
      ansible.builtin.assert:
        that:
          - table_creation is succeeded

Пример 3: Тестирование Усиления Безопасности

Роли безопасности требуют тщательного тестирования для обеспечения того, что они не нарушают функциональность.

molecule/default/verify.yml (усиление безопасности):

---
- name: Verify Security Hardening
  hosts: all
  gather_facts: true
  tasks:
    - name: Check if SSH password authentication is disabled
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PasswordAuthentication'
        line: 'PasswordAuthentication no'
        state: present
      check_mode: yes
      register: ssh_config

    - name: Assert SSH is properly configured
      ansible.builtin.assert:
        that:
          - not ssh_config.changed
        fail_msg: "SSH password authentication is not disabled"

    - name: Verify firewall is active
      ansible.builtin.command: ufw status
      register: ufw_status
      changed_when: false

    - name: Assert firewall is enabled
      ansible.builtin.assert:
        that:
          - "'Status: active' in ufw_status.stdout"

    - name: Check for unattended upgrades
      ansible.builtin.stat:
        path: /etc/apt/apt.conf.d/50unattended-upgrades
      register: unattended_upgrades

    - name: Assert automatic updates are configured
      ansible.builtin.assert:
        that:
          - unattended_upgrades.stat.exists

    - name: Verify root login is disabled
      ansible.builtin.command: passwd -S root
      register: root_status
      changed_when: false

    - name: Assert root account is locked
      ansible.builtin.assert:
        that:
          - "'L' in root_status.stdout"
        fail_msg: "Root account is not locked"

Лучшие Практики

Организация Тестов

Держите тесты сфокусированными и модульными:

# Плохо: Один гигантский файл верификации
verify.yml  # 500 строк тестов

# Хорошо: Отдельные задачи верификации
molecule/default/
├── molecule.yml
├── converge.yml
├── verify.yml
└── verify/
    ├── test_installation.yml
    ├── test_configuration.yml
    ├── test_security.yml
    └── test_networking.yml

Основной verify.yml включает конкретные тесты:

---
- name: Verify
  hosts: all
  tasks:
    - name: Run installation tests
      include_tasks: verify/test_installation.yml

    - name: Run configuration tests
      include_tasks: verify/test_configuration.yml

    - name: Run security tests
      include_tasks: verify/test_security.yml

Управление Сценариями

Используйте сценарии стратегически:

  • default: Базовое тестирование функциональности
  • production: Окружение типа production со всеми функциями
  • upgrade: Тестирование путей обновления с предыдущих версий
  • multi-node: Тестирование распределенных систем

Не создавайте сценарии для незначительных вариаций. Вместо этого используйте переменные:

# molecule/default/converge.yml
- name: Converge
  hosts: all
  vars:
    # Переопределите их в конкретных сценариях
    enable_ssl: "{{ scenario_ssl | default(true) }}"
    enable_monitoring: "{{ scenario_monitoring | default(false) }}"
  roles:
    - nginx

Тестирование Идемпотентности

Идемпотентность критична—запуск вашей роли несколько раз не должен вызывать изменений после первого запуска.

Molecule автоматически тестирует это. Убедитесь, что ваши задачи идемпотентны:

# Плохо: Всегда сообщает об изменениях
- name: Configure application
  ansible.builtin.shell: echo "config=true" >> /etc/app.conf

# Хорошо: Идемпотентная конфигурация
- name: Configure application
  ansible.builtin.lineinfile:
    path: /etc/app.conf
    line: "config=true"
    create: yes

Отслеживайте вывод теста идемпотентности:

PLAY RECAP *****************************************************************
instance: ok=10 changed=0 unreachable=0 failed=0

Если changed больше 0 при втором запуске, у вас проблемы с идемпотентностью.

Docker vs Vagrant

Docker (Рекомендуется для большинства случаев):

  • Быстро: Контейнеры запускаются за секунды
  • Эффективен по ресурсам: Запускайте много экземпляров одновременно
  • Дружественен к CI: Работает в большинстве CI окружений
  • Ограничения: Не может тестировать модули ядра, особенности systemd, или что-либо, требующее полной VM

Vagrant (Для сложных сценариев):

  • Полные VM: Полная операционная система
  • Systemd: Полная поддержка init системы
  • Тестирование ядра: Может тестировать параметры и модули ядра
  • Компромиссы: Медленнее (минуты для запуска), ресурсоемкий, сложнее в CI

Когда использовать Vagrant:

# molecule/vagrant/molecule.yml
---
driver:
  name: vagrant
platforms:
  - name: ubuntu-vm
    box: ubuntu/jammy64
    memory: 2048
    cpus: 2
provisioner:
  name: ansible

Используйте Vagrant при тестировании ролей, которые:

  • Изменяют параметры ядра (sysctl)
  • Требуют специфических функций systemd
  • Устанавливают модули ядра
  • Нуждаются в полном стеке сети

Распространенные Ошибки

Ограничения Контейнеров

Проблема: Systemd не работает должным образом в стандартных контейнерах.

Решение: Используйте предварительно собранные образы с поддержкой systemd:

platforms:
  - name: instance
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    privileged: true
    command: /lib/systemd/systemd

Docker образы Джеффа Герлинга специально собраны для тестирования Ansible с работающим systemd.

Проблемы с Привилегиями

Проблема: Задачи падают с ошибками разрешений.

Решение: Используйте become должным образом в вашем playbook конвергенции:

# molecule/default/converge.yml
---
- name: Converge
  hosts: all
  become: true  # Запускать задачи с sudo
  tasks:
    - name: Include role
      include_role:
        name: nginx

Избегайте требования become: yes в самой роли когда это возможно. Позвольте пользователю решать вопрос повышения привилегий.

Управление Зависимостями

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

Решение: Определите зависимости в meta/main.yml:

# meta/main.yml
---
dependencies:
  - role: geerlingguy.security
  - role: geerlingguy.firewall

Molecule автоматически устанавливает их перед тестированием, если у вас включен менеджер зависимостей Galaxy:

# molecule/default/molecule.yml
dependency:
  name: galaxy
  options:
    role-file: requirements.yml

Создайте requirements.yml для внешних зависимостей:

# requirements.yml
---
roles:
  - name: geerlingguy.security
    version: 2.3.0
  - name: geerlingguy.firewall
    version: 3.1.0

Нестабильность Тестов

Проблема: Тесты иногда падают без очевидной причины.

Распространенные причины:

  • Таймауты сети
  • Состояния гонки при запуске сервисов
  • Недостаточное время ожидания

Решение: Добавьте соответствующие ожидания и повторы:

- name: Wait for service to be ready
  ansible.builtin.wait_for:
    port: 80
    delay: 2
    timeout: 30

- name: Check endpoint with retry
  ansible.builtin.uri:
    url: http://localhost/health
  register: health_check
  until: health_check.status == 200
  retries: 5
  delay: 3

Инструменты и Интеграция

Testinfra для Верификации

Хотя Molecule использует Ansible для верификации по умолчанию, вы также можете использовать Testinfra (тестирование на основе Python):

pip install testinfra

molecule/default/tests/test_default.py:

import os
import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']
).get_hosts('all')

def test_nginx_is_installed(host):
    nginx = host.package("nginx")
    assert nginx.is_installed

def test_nginx_running_and_enabled(host):
    nginx = host.service("nginx")
    assert nginx.is_running
    assert nginx.is_enabled

def test_nginx_listening(host):
    assert host.socket("tcp://0.0.0.0:80").is_listening

def test_index_html_content(host):
    content = host.file("/var/www/html/index.html").content_string
    assert "Deployed with Ansible" in content

Настроить Testinfra в molecule.yml:

verifier:
  name: testinfra
  options:
    v: 1

Интеграция GitLab/GitHub CI

Продвинутые GitHub Actions с матричным тестированием:

---
name: Ansible Role Testing

on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '0 0 * * 0'  # Еженедельно

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies
        run: pip install ansible-lint yamllint
      - name: Lint Ansible role
        run: ansible-lint .
      - name: Lint YAML files
        run: yamllint .

  test:
    needs: lint
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        distro:
          - ubuntu2004
          - ubuntu2204
          - debian11
        scenario:
          - default
          - production
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install Molecule
        run: pip install "molecule[docker,lint]" ansible
      - name: Run Molecule test
        run: molecule test -s ${{ matrix.scenario }}
        env:
          PY_COLORS: '1'
          ANSIBLE_FORCE_COLOR: '1'
          MOLECULE_DISTRO: ${{ matrix.distro }}

Интеграция с Ansible Galaxy

При публикации ролей в Ansible Galaxy включите тесты Molecule для повышения доверия:

# .github/workflows/release.yml
---
name: Release to Galaxy

on:
  push:
    tags:
      - 'v*'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Test with Molecule
        run: |
          pip install "molecule[docker,lint]"
          molecule test

  release:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Release to Galaxy
        uses: robertdebock/galaxy-action@1.2.0
        with:
          galaxy_api_key: ${{ secrets.GALAXY_API_KEY }}

Добавьте ссылку на ваш CI badge в README.md:

# Ansible Role: Nginx

[![CI](https://github.com/username/ansible-role-nginx/workflows/CI/badge.svg)](https://github.com/username/ansible-role-nginx/actions)
[![Ansible Galaxy](https://img.shields.io/badge/galaxy-username.nginx-blue.svg)](https://galaxy.ansible.com/username/nginx)

Протестировано с Molecule на:
- Ubuntu 20.04
- Ubuntu 22.04
- Debian 11

Заключение

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

Ключевые Выводы:

  • Всегда тестируйте свои роли на нескольких операционных системах и сценариях
  • Используйте тестирование идемпотентности для предотвращения дрейфа конфигурации
  • Интегрируйте Molecule в ваш CI/CD пайплайн для непрерывной валидации
  • Используйте Docker для скорости во время разработки, Vagrant для сложного тестирования на системном уровне
  • Пишите четкие, сфокусированные тесты верификации, которые действуют как живая документация

Следующие Шаги:

  1. Исследуйте продвинутые сценарии: Внедрите мультиузловое тестирование для распределенных систем (узнайте больше в нашем руководстве по Лучшим Практикам Управления Docker Контейнерами)
  2. Интегрируйте с вашим CI/CD пайплайном: Добавьте тесты Molecule в ваши существующие пайплайны (посмотрите Стратегии Оптимизации CI/CD Пайплайна)
  3. Вносите вклад в сообщество: Делитесь вашими протестированными ролями на Ansible Galaxy
  4. Изучайте дополнительные инструменты тестирования: Исследуйте Testinfra, InSpec и ServerSpec для более глубокой валидации инфраструктуры

Для большего об автоматизации инфраструктуры и лучших практиках DevOps, изучите наше комплексное руководство по Инфраструктуре как Код с Terraform или погрузитесь в Стратегии Развертывания Kubernetes для тестирования облачной инфраструктуры.

Дополнительные Ресурсы:

Начните тестировать ваш инфраструктурный код сегодня—ваше будущее “я” (и ваша команда) будут благодарны вам, когда развертывания станут предсказуемыми, надежными и свободными от стресса.