Ansible Molecule#

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

Ключевые особенности и достоинства#

Ansible Molecule имеет следующие ключевые особенности и достоинства:

  • Позволяет создавать тестовые среды в различных виртуальных окружениях.

    Ansible Molecule позволяет тестировать роли Ansible в различных средах, включая множество поставщиков виртуализации и контейнеризации, операционные системы и дистрибутивы. Эта универсальность позволяет тестировать роли в разнообразных условиях.

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

  • Ansible Molecule позволяет создавать несколько сценариев тестирования. Основу каждого из них составляет набор сценариев Ansible в виде файлов playbook. Тестирование в пределах одного сценария основано на выполнении определенной последовательности функциональных тестов в виде сценариев из Ansible playbooks.

    Разработчику тестов необходимо определить каждый сценарий (Ansible play) в виде набора задач (Ansible tasks), используя знакомые ему возможности Ansible. Можно запускать полную последовательность тестов или часть ее.

  • Обеспечивает объявленную политику поддержки версий Ansible – поддерживает две последние основные версии Ansible. Эта политика гарантирует, что тестовая среда остается актуальной с учетом последних функций Ansible, сохраняя при этом обратную совместимость с предыдущей основной версией.

  • Обеспечивает понятный синтаксис командной строки на базе утилиты molecule, которую можно также запускать как модуль Python python3 -m molecule.

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

Применение#

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

  • Разработка новых ролей Ansible – предоставляет стандартизированную среду для разработки ролей с нуля, обеспечивая их соответствие стандартам качества.

  • Тестирование существующих ролей Ansible – может помочь выявить проблемы совместимости с новыми версиями Ansible или в различных средах, которые не были предусмотрены изначально.

  • Интеграция в CI/CD конвейеры – можно интегрировать в процессы непрерывной интеграции и развертывания для автоматизации тестирования ролей Ansible, делая процесс более надежным и эффективным.

Принцип работы#

Ansible Molecule построена на основе модульной архитектуры, которая позволяет ей быть гибкой и расширяемой. Основными компонентами Ansible Molecule являются:

  • Сценарии (Scenarios).

    Являются основными строительными блоками данного функционального тестирования. Они выстроены в определенную последовательность, описываемую далее.

  • Драйверы (Drivers или Providers).

    Отвечают за создание, управление и удаление тестовых сред. Примеры драйверов: Docker, Podman, Vagrant, Libvirt, LXC, EC2.

  • Исполнитель сценариев (Provisioners).

    Используются для исполнения сценариев в созданных тестовых средах. По умолчанию Ansible Molecule использует Ansible в качестве исполнителя.

  • Средства проверки (Verifiers).

    Инструменты для контроля успешности выполнения сценариев. Позволяет использовать Testinfra, Goss и Ansible.

Схема работы Ansible Molecule#

Ansible Molecule выполняет тестирование ролей с помощью последовательности этапов. На каждом этапе выполняется определенный сценарий. Название этапа и файла сценария (playbook) соответствуют друг другу. Например, на этапе destroy выполняется сценарий из файла destroy.yml.

  1. destroy удаляет предыдущую тестовую среду, если она существует, чтобы обеспечить отсутствие изменений, сделанных на предыдущих запусках тестирования.

  2. dependency устанавливает зависимости роли, например, указанные в файле requirements.yml.

  3. syntax проверяет синтаксис сценариев и файлов роли.

  4. create создает тестовую среду с использованием выбранного драйвера.

  5. prepare выполняет дополнительные подготовительные задачи, если они определены.

  6. converge применяет роль к тестовой среде с помощью Ansible.

  7. idempotence проверяет идемпотентность роли, применяя ее повторно и ожидая отсутствия изменений.

  8. verify выполняет тесты для проверки корректности работы роли.

  9. cleanup выполняет задачи очистки, если они определены.

  10. destroy удаляет тестовую среду после завершения тестирования.

Этапы осуществляются в строгой последовательности, после выполнения запрошенного этапа работа утилиты завершается.

Процесс тестирования показан на схеме:

../../../_images/molecule-command.svg ../../../_images/molecule-command.svg

На локальном узле выполняются следующие этапы:

После создания тестовой среды в ней выполняются следующие этапы:

Если пользователь запрашивает выполнение определенного этапа, например, prepare, утилита выполнит также все предшествующие ему этапы.

Например, процесс выполнения этапа prepare показан на схеме:

../../../_images/molecule-prepare.svg ../../../_images/molecule-prepare.svg

Тестовые среды#

В Ansible Molecule тестовые среды определяются драйвером. Их можно разделить на несколько типов в зависимости от того, какие инструменты используются:

  • Контейнеры.

    При использовании драйверов типа Docker или Podman Ansible Molecule создает отдельные контейнеры для каждой тестовой платформы, определенной в molecule.yml. Если необходимо протестировать роль на нескольких операционных системах, Molecule создаст по одному контейнеру для каждой из них. Один контейнер используется для всех этапов (create, converge, verify) в рамках одного сценария. Это означает, что контейнер создается на этапе create и уничтожается на этапе destroy, а все остальные действия выполняются внутри этого контейнера.

  • Виртуальные машины.

    При использовании драйверов типа Vagrant или Libvirt, Ansible Molecule создает виртуальные машины для каждой платформы.

  • Виртуальные окружения.

    Ansible Molecule по умолчанию не использует виртуальные окружения Python (venv) внутри тестовых сред. Однако, если роль требует использования пакетов Python или виртуальных окружений на целевых узлах, вы можете настроить это в своих задачах Ansible.

Установка#

Для установки Ansible Molecule выполните следующие действия:

  1. Подключите репозиторий Astra Automation.

    Инструкция по подключению репозитория
    1. В каталоге /etc/apt/sources.list.d/ создайте файл astra-automation.list со ссылкой на репозиторий Astra Automation:

      deb https://dl.astralinux.ru/aa/aa-debs-for-alse-1.7 <version> main
      

      Вместо <version> необходимо подставить версию устанавливаемой платформы, например, 1.1-upd1.

      Доступные версии продукта опубликованы в таблице История обновлений.

    2. Обновите список доступных пакетов:

      sudo apt update
      
  2. Установите пакет molecule:

    sudo apt install molecule --yes
    

Настройка#

Ansible Molecule можно настроить с помощью следующих компонентов:

При вычислении действующих значений аргументов используется следующий порядок (значения, указанные на более поздних этапах, заменяют значения, указанные ранее):

  1. Файл настроек.

  2. Команды.

По умолчанию Ansible Molecule начинает поиск файла настроек с текущего каталога. Если в каталоге несколько сценариев, утилита проверяет структуру подкаталогов. Если указан аргумент --scenario-name, утилита ищет файл molecule.yml в соответствующем каталоге сценария.

Параметры в файле настроек задаются следующим образом:

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

platforms:
  - name: molecule-astra
    image: hub.astra-automation.ru/aa/aa-base-ee
    privileged: true
    groups:
      - all

driver:
  options:
    managed: false
    login_cmd_template: "podman exec -ti {instance} bash"
    ansible_connection_options:
      ansible_connection: podman

Подробное описание параметров см. в справочнике.

Пример#

В этом примере рассматривается создание роли Ansible, которая получает текущую версию Ansible и записывает ее в файл /tmp/ansible_version_output.txt. В качестве тестовой среды используется контейнер, запускаемый с помощью Podman. Подробное описание команд и возможных аргументов утилиты см. в справочнике.

Создание структуры роли#

Для создания структуры роли выполните следующие действия:

  1. Создайте каталог для роли и перейдите в него:

    mkdir ansible_version_role && cd ansible_version_role
    
  2. Создайте сценарий:

    molecule init scenario
    

    Эта команда создаст структуру файлов и каталогов для сценария с поддержкой драйвера по умолчанию (default) в каталоге текущей роли.

  3. Создайте каталог tasks для хранения задач роли:

    mkdir tasks
    
  4. В каталоге tasks создайте файл main.yml.

В результате выполнения действий получится следующая структура:

ansible_version_role/
├── molecule
│   └── default
│       ├── converge.yml
│       ├── create.yml
│       ├── destroy.yml
│       ├── molecule.yml
│       ├── requirements.yml
│       └── verify.yml
└── tasks
    └── main.yml

Заполнение файлов роли#

molecule.yml – файл настроек утилиты. Пример заполнения файла:

---
dependency:
  name: galaxy
  options:
    requirements-file: requirements.yml

platforms:
  - name: molecule-astra
    image: hub.astra-automation.ru/aa/aa-base-ee
    privileged: true
    groups:
      - all

driver:
  options:
    managed: false
    login_cmd_template: "podman exec -ti {instance} bash"
    ansible_connection_options:
      ansible_connection: podman

provisioner:
  name: ansible
  config_options:
    defaults:
      remote_tmp: '/tmp/.ansible-${USER}/tmp'
  playbooks:
    create: create.yml
    converge: converge.yml
    destroy: destroy.yml
    verify: verify.yml
  inventory:
    group_vars:
      all:
        ansible_python_interpreter: /usr/bin/python3.9  # Версия Python контейнера
        ansible_user: '1000'  # Пользователь в контейнере

Файл converge.yml используется для запуска роли, которая выполняет задачу получения версии Ansible. Пример заполнения файла:

- name: Converge
  hosts: all
  become: false
  gather_facts: false
  roles:
    - ansible_version_role

Файл create.yml отвечает за создание контейнера. В этом примере для создания контейнера используется модуль containers.podman.podman_container:

- name: Create
  hosts: localhost
  gather_facts: false

  tasks:
    - name: Create a container
      containers.podman.podman_container:
        name: "{{ item.name }}"
        image: "{{ item.image }}"
        privileged: "{{ item.privileged | default(omit) }}"
        volumes: "{{ item.volumes | default(omit) }}"
        capabilities: "{{ item.capabilities | default(omit) }}"
        systemd: "{{ item.systemd | default(omit) }}"
        state: started
        command: "{{ item.command | default('sleep 1d') }}"
        log_driver: json-file
      register: result
      loop: "{{ molecule_yml.platforms }}"

    - name: Create remote_tmp directory
      ansible.builtin.file:
        path: '/tmp/.ansible-{{ ansible_user }}/tmp'
        state: directory
        mode: '0755'

Файл destroy.yml отвечает за удаление контейнера по окончании тестов. Пример заполнения:

- name: Destroy molecule containers
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Stop and remove container
      containers.podman.podman_container:
        name: molecule-astra
        state: absent
        rm: true

В файле verify.yml содержится задача проверки существования файла с версией Ansible в тестовом окружении. Пример заполнения:

- name: Verify Ansible version output
  hosts: all
  tasks:
    - name: Check if ansible version output contains 'ansible'
      ansible.builtin.command: "cat /tmp/ansible_version_output.txt"
      register: ansible_version_check
      failed_when: "'ansible' not in ansible_version_check.stdout"
      changed_when: false

В файле requirements.yml указываются зависимости Ansible. В данном примере файл указывает на необходимость использования коллекции containers.podman:

collections:
  - containers.podman

В файле main.yml указываются задачи, которые выполняет роль. В данном примере роль выполняет команду ansible --version и сохраняет результат в файл /tmp/ansible_version_output.txt.

- name: Get Ansible version
  ansible.builtin.command: ansible --version
  register: ansible_version_output
  changed_when: false

- name: Save Ansible version output to file in /tmp directory
  ansible.builtin.copy:
    content: "{{ ansible_version_output.stdout }}"
    dest: /tmp/ansible_version_output.txt

Запуск тестов#

Чтобы запустить полный цикл тестирования, выполните команду:

molecule test

Запуск этой команды приведет к выполнению следующих этапов тестирования:

  1. create;

  2. converge;

  3. verify;

  4. destroy.

Для подключения к контейнеру и ручной проверки выполните команду:

molecule login