Тестирование автоматизации Ansible с помощью Molecule Часть 1

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В статье много информации об Ansible. Давайте посмотрим, как тестировать роли с помощью Molecule, Docker и Testinfra.

Molecule – это проект Red Hat, призванный помочь в тестировании ролей Ansible. Он обеспечивает поддержку тестирования с различными операционными системами и дистрибуями. Molecule также является весьма разноплановым проектом, позволяющим использовать множество провайдеров виртуализации, тестовых фреймворков и тестовых сценариев. Такой подход обеспечивает последовательность в разработке и обслуживании ролей.

Приступаем к работе

Настройка вашей среды

Python3 и pip – это необходимые условия для Ansible и Molecule. Установка и настройка этих инструментов выходят за рамки данного руководства.

Следующие команды установят Ansible и Molecule с помощью pip. Для получения информации о других вариантах установки посетите соответствующие страницы документации Ansible и Molecule.

# install ansible
python3 -m pip install --user ansible
# Install the latest version of molecule from source
python3 -m pip install -U git+https://github.com/ansible-community/molecule
#install testinfra
python3 -m pip install --user pytest-testinfra
#install the molecule docker driver
python3 -m pip install -U "molecule[docker]"

Вам также потребуется установить docker-ce вместе с плагином Docker для Molecule. Последняя команда в приведенном выше скрипте устанавливает плагин docker. Этот метод применим к установке любых плагинов molecule, которые вы планируете использовать. После этого Docker сможет выступать в качестве драйвера в Molecule.

Инициализация новой роли с помощью Molecule

Теперь, когда предустановки готовы, начнем с некоторых основ. Начните с запуска molecule init role sample.demo_role --driver-name docker --verifier-name testinfra. Вуаля, Молекула создаёт новую роль, уже настроенную в тестовом каталоге. Давайте посмотрим на каталог, а затем более подробно рассмотрим эту команду.

demo_role/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── molecule
│   └── default
│       ├── converge.yml
│       ├── molecule.yml
│       └── tests
│           ├── conftest.py
│           ├── __pycache__
│           │   ├── conftest.cpython-38.pyc
│           │   └── test_default.cpython-38.pyc
│           └── test_default.py
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

Правда впечатляет? Molecule создал все необходимое для создания роли и одновременного ее тестирования.

Изучение команды и результатов её применения

Ниже описание команды и опций, которые мы использовали:

Molecule инициирует sample.demo_role

init role задействует ansible-galaxy  для создания каталога шаблонов <NAME_SPACE>.<ROLE_NAME>. Команда также подготавливает каталог Molecule, чтобы помочь начать работу. В качестве альтернативы, если у вас уже есть роль, вы можете инициировать Molecule как сценарий с molecule init scenario -r <ROLE_NAME>.

--driver-name Docker

Указывает на то, какой драйвер следует использовать для вашей тестовой среды. Драйвер определяет, какую платформу или инфраструктуру развернуть для тестов. Несколько доступных драйверов включают podman, libvirt, Azure и многие другие. Независимо от вашего драйвера, необходимо установить модуль с помощью pip. Здесь мы сосредоточимся на использовании Docker.

--verifier-name testinfra

Указывает, какой верификатор вы хотите использовать для вашего сценария по умолчанию. Верификатор – это механизм, используемый для тестирования ваших ролей. Некоторые доступные опции включают Ansible, test infra и inspect. Хотя Ansible является верификатором по умолчанию, мы будем использовать testinfra для этой демонстрации.

Вот описание созданных файлов Molecule:

./molecule/default/molecule.yml

Это основной файл для Molecule. Используется для определения шагов тестирования, сценариев, зависимостей и других параметров конфигурации. Сгенерированный файл должен выглядеть следующим образом:

---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: instance
    image: quay.io/centos/centos:stream8
    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: testinfra

./molecule/default/converge.yml

Это плейбук, который Molecule запустит, чтобы обеспечить цели для тестирования. Ниже приведен файл, который создает Molecule. Если вы можете использовать этот файл в сборнике воспроизведения, вы можете использовать его здесь.

---
- name: Converge
  hosts: all
  tasks:
    - name: "Include sample.demo_role"
      include_role:
        name: "sample.demo_role"

./molecule/default/tests/test_default.py

Это исходный тестовый файл, созданный для test infra. Именно здесь мы будем проводить наши тесты для этой демо-версии. Однако вы не ограничены этим файлом или даже этим каталогом для ваших тестов. Тест по умолчанию показан ниже.

"""Role testing files using testinfra."""
def test_hosts_file(host):
    """Validate etc/hosts file"""
    f = host.file("etc/hosts")
assert f.exists
    assert f.user == "root"
    assert f.group == "root"

Приступаем к практике

Каждая роль должна что-то выполнять. У нас есть роль, которая в настоящее время ничего не делает, давайте исправим это, добавив некоторые задачи в ./tasks/main.yml. В этой статье мы будем придерживаться основ, добавив лишь несколько вещей, для которых мы можем писать тесты. В данном случае несколько пакетов yum, пользователь и конфигурационный файл предусмотрены в приведенном ниже коде.

---
# tasks file for demo_role
- name: install some packages
  yum:
    name: "{{ item.name }}-{{item.version}}.{{ item.arch }}"
    state: installed
  with_items:
    - { name: 'epel-release', version: '8-11.el8', arch: 'noarch' }
    - { name: 'htop', version: '3.0.5-1.el8', arch: 'x86_64' }
    - { name: 'nginx', version: '1.14.1-9.module_el8.0.0+1060+3ab382d3', arch: 'x86_64' }
    - { name: 'git', version: '2.31.1-2.el8', arch: 'x86_64' }
- name: add webapp user
  ansible.builtin.user:
    name: webapp
    system: true
- name: create an app directory owned by webapp
  ansible.builtin.file:
    path: /opt/webapp
    state: directory
    owner: webapp
    group: webapp
- name: create app.conf owned by webapp
  ansible.builtin.file:
    path: /opt/webapp/app.conf
    state: touch
    owner: webapp
    group: webapp
    mode: '0755'
    access_time: preserve
    modification_time: preserve

Create и Converge

У нас есть роль, которая будет обрабатывать некоторые задачи, что же дальше? Во-первых, мы можем запустить команду molecule create в директории  ./demo_role. Create использует настройки, определенные в конфигурации molecule.yml, чтобы определить драйвер и платформу. Для этого примера Molecule будет использовать следующие строки в molecule.yml.

driver:
  name: docker
platforms:
  - name: instance
    image: quay.io/centos/centos:stream8
    pre_build_image: true

Он будет использовать Ansible для запуска контейнера Docker на основе образа quay.io/centos/centos:stream8, при необходимости извлекая его из реестра контейнеров.

Теперь, когда у нас есть цель и роль, давайте объединим их с molecule converge. Команда converge запускает плейбук converge.yml по отношению к целевой платформе. 

INFO     default scenario test matrix: dependency, create, prepare, converge
INFO     Performing prerun with role_name_check=0...
INFO     Set ANSIBLE_LIBRARY=/home/pcritchfield/.cache/ansible-compat/54dfe2/modules:/home/pcritchfield/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/pcritchfield/.cache/ansible-compat/54dfe2/collections:/home/pcritchfield/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/pcritchfield/.cache/ansible-compat/54dfe2/roles:/home/pcritchfield/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Using /home/pcritchfield/.cache/ansible-compat/54dfe2/roles/sample.demo_role symlink to current repository in order to enable Ansible to find the role using its expected full name.
INFO     Running default > dependency
WARNING  Skipping, missing the requirements file.
WARNING  Skipping, missing the requirements file.
INFO     Running default > create
WARNING  Skipping, instances already created.
INFO     Running default > prepare
WARNING  Skipping, prepare playbook not configured.
INFO     Running default > converge
INFO     Sanity checks: 'docker'
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [Include sample.demo_role] ************************************************
TASK [sample.demo_role : install some packages] ********************************
changed: [instance] => (item=epel-release)
changed: [instance] => (item=htop)
changed: [instance] => (item=nginx)
changed: [instance] => (item=git)
TASK [sample.demo_role : add webapp user] **************************************
changed: [instance]
TASK [sample.demo_role : create an app directory owned by webapp] **************
changed: [instance]
TASK [sample.demo_role : create an app directory owned by webapp] **************
changed: [instance]
PLAY RECAP *********************************************************************
instance                   : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Глядя на этот результат, мы можем видеть, как выполняются шаги Molecule. На линии, показывающей INFO default scenario test matrix: dependency, create, prepare, converge. Это означает, что запуск molecule create  не всегда является необходимым. Часто можно просто запустить команду converge, поскольку она уже включает create.

Написание тестов и Verify

Теперь, когда мы запустили converge и развернули контейнеры, давайте проведем несколько тестов. Используйте команду molecule verify, чтобы запустить тест по умолчанию test_default.py. Вы должны увидеть вывод, похожий на:

INFO     default scenario test matrix: verify
INFO     Performing prerun with role_name_check=0...
INFO     Set ANSIBLE_LIBRARY=/home/pcritchfield/.cache/ansible-compat/54dfe2/modules:/home/pcritchfield/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/pcritchfield/.cache/ansible-compat/54dfe2/collections:/home/pcritchfield/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/pcritchfield/.cache/ansible-compat/54dfe2/roles:/home/pcritchfield/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Using /home/pcritchfield/.cache/ansible-compat/54dfe2/roles/sample.demo_role symlink to current repository in order to enable Ansible to find the role using its expected full name.
INFO     Running default > verify
INFO     Executing Testinfra tests found in /home/pcritchfield/Projects/ansible_molecule/roles/demo_role/molecule/default/tests/...
============================= test session starts ==============================
platform linux -- Python 3.8.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/pcritchfield
plugins: testinfra-6.8.0
collected 1 item
molecule/default/tests/test_default.py .                                 [100%]
============================== 1 passed in 1.50s ===============================
INFO     Verifier completed successfully.

Успешно! Наш тест по умолчанию работает и подтверждает, что root является пользователем.  molecule verify также позволяет нам повторять наши тесты на существующем контейнере. Нет необходимости повторять  create и converge.

Теперь давайте напишем несколько тестов, чтобы подтвердить, что наша роль выполняет то, что должна. Мы начнем с проверки того, что установлены соответствующие пакеты и версии. Добавьте следующее к ./molecule/default/tests/test_default.py:

import pytest
# Confirm that specific packages and versions are installed
@pytest.mark.parametrize("name,version", [
    ("epel-release", "8"),
    ("htop", "3.0"),
    ("nginx", "1.14"),
    ("git", "2.31"),
])
def test_packages(host, name, version):
    pkg = host.package(name)
    assert pkg.is_installed
    assert pkg.version.startswith(version)

Для тех, кто новичок в тестировании, это может показаться многовато. К счастью, это довольно просто. Мы используем pytest для параметризации сопоставления имени и версии. Затем передаем это в test_packages и проверяем имя пакета и его версию. Использование карты позволяет нам написать один тест для всех пакетов. Продолжайте, сохраните этот файл и запустите molecule verify. Вы должны увидеть, что четыре теста были успешно выполнены.

======================= test session starts ========================
platform linux -- Python 3.8.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/pcritchfield
plugins: testinfra-6.8.0
collected 4 items
molecule/default/tests/test_default.py ....                              [100%]
======================== 4 passed in 2.77s =========================
INFO     Verifier completed successfully.

Далее мы можем протестировать для пользователя webapp и файла app.conf. Добавьте следующее к test_default.py:

# Test that the webapp user is available.
@pytest.mark.parametrize("user,group", [
    ("webapp", "webapp"),
])
def test_users(host, user, group):
    usr = host.user(user)
    assert usr.exists
    assert usr.group == group
# Test that app.conf is present and has expected permissions
@pytest.mark.parametrize("filename,owner,group,mode", [
    ("/opt/webapp/app.conf", "webapp", "webapp", 0o755),
])
def test_file(host, filename, owner, group, mode):
    target = host.file(filename)
    assert target.exists
    assert target.user == owner
    assert target.group == group
    assert target.mode == mode

Запустите molecule verify еще раз, и теперь вы увидите шесть проходящих тестов:

======================= test session starts ========================
platform linux -- Python 3.8.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/pcritchfield
plugins: testinfra-6.8.0
collected 6 items
molecule/default/tests/test_default.py ......                            [100%]
======================== 6 passed in 4.09s =========================

Наконец, чтобы всё очистить, мы можем запустить molecule destroy. Это удаляет контейнеры, которые мы развернули и подготовили с помощью create или converge. Это дает нам прекрасную возможность начать все сначала. Обеспечивая уверенность в том, что мы получим последовательные развертывания при каждом использовании нашей demo_role.

Одна команда, чтобы управлять ими всеми

Одна последняя команда Molecule, которую мы рассмотрим, это molecule test. Команда test запустит весь сценарий: создание, конвергенцию, проверку и многое другое. Давайте посмотрим, что делает тест в качестве сценария по умолчанию. Запустите команду molecule matrix test, чтобы вывести списком все этапы, которые будет проходить test:

INFO     Test matrix
---                                                                                       
default:                                                                                  
  - dependency                                                                            
  - lint                                                                                  
  - cleanup                                                                               
  - destroy                                                                               
  - syntax                                                                                
  - create                                                                                
  - prepare                                                                               
  - converge                                                                              
  - idempotence                                                                           
  - side_effect                                                                           
  - verify                                                                                
  - cleanup                                                                               
  - destroy

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

Вы можете найти демонстрационный код в этом посте на GitHub (https://github.com/PCritchfield/ansible/tree/master/ansible_molecule_pt1)

В следующий раз

В следующей статье мы углубимся в конфигурацию molecule.yml. Мы рассмотрим тестирование нескольких операционных систем, линтинг и идемпотентность.

Видеокурс Ansible: Infrastructure as Code с практикой на стендах.

Источник: https://habr.com/ru/company/southbridge/blog/711432/


Интересные статьи

Интересные статьи

Авторитет института NIST (National Institute of Standards and Technology, Национальный Институт Стандартов и Технологии) в среде специалистов по информационной безопасности фактически непререкаем. На ...
Друзья, это первая статья по фреймворку LeoECS из предстоящей серии, которая позволит вам быстрее понять, как работать с LeoECS в Unity и решить некоторые виды проблем, возникающих на практике. Все со...
Векторная графика очень удобна для иллюстраций. Молекулы состоят из атомов соединённых связями. Хочется, чтобы операции редактирования рисунка химической структуры осущес...
30  октября мы провели встречу с СТО и техническими руководителями Райффайзенбанка, Mindbox и ЦИАН, где за два часа постарались максимально охватить непривычную для ...
Привет, Хабр! Представляю вашему вниманию перевод статьи "Land Cover Classification with eo-learn: Part 1" автора Matic Lubej. Часть 2 Предисловие Примерно полгода назад был сделан первый комм...