Contents
Шаг 1 — Подготовка среды
Если вы выполнили предварительные требования, у вас должны быть venv
установлены и правильно настроены Python 3, , и Docker. Давайте начнем с создания виртуальной среды для тестирования Ansible с помощью Molecule.
Начните с входа в систему как пользователь без полномочий root и создайте новую виртуальную среду:
Активируйте его, чтобы убедиться, что ваши действия ограничены этой средой:
Затем в вашей активированной среде установите wheel
пакет, который предоставляет bdist_wheel
setuptools
расширение, pip
используемое для установки Ansible:
Теперь вы можете установить molecule
и docker
с pip
. Ansible будет автоматически установлен как зависимость для Molecule:
Вот что будет делать каждый из этих пакетов:
molecule
: это основной пакет Molecule, который вы будете использовать для тестирования ролей. Установкаmolecule
автоматически устанавливает Ansible вместе с другими зависимостями и позволяет использовать Ansible playbooks для выполнения ролей и тестов.docker
: эта библиотека Python используется Molecule для взаимодействия с Docker. Это понадобится вам, поскольку вы используете Docker в качестве драйвера.
Далее создадим роль в Molecule.
Шаг 2 — Создание роли в молекуле
После настройки среды вы можете использовать Molecule для создания базовой роли, которую вы будете использовать для тестирования установки Apache. Эта роль создаст структуру каталогов и некоторые начальные тесты, а также укажет Docker в качестве драйвера, чтобы Molecule использовала Docker для запуска своих тестов.
Создайте новую роль с именем ansible-apache
:
Флаг -r
указывает имя роли, а -d
указывает драйвер, который предоставляет хосты для использования Molecule при тестировании.
Перейдите в каталог только что созданной роли:
Протестируйте роль по умолчанию, чтобы проверить правильность настройки Molecule:
Вы увидите выходные данные со списком всех тестовых действий по умолчанию. Перед началом теста Molecule проверяет файл конфигурации, molecule.yml
чтобы убедиться, что все в порядке. Он также печатает эту тестовую матрицу, которая определяет порядок тестовых действий:
--> Validating schema /home/sammy/ansible-apache/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix
└── default
├── lint
├── destroy
├── dependency
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
└── destroy
...
Мы подробно обсудим каждое тестовое действие после того, как вы создадите свою роль и настроите свои тесты. На данный момент обратите внимание на PLAY_RECAP
для каждого теста и убедитесь, что ни одно из действий по умолчанию не возвращает failed
статус. Например, действие PLAY_RECAP
по умолчанию 'create'
должно выглядеть так:
...
PLAY RECAP *********************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0
Перейдем к изменению роли для настройки Apache и firewalld.
Шаг 3 — Настройка Apache и Firewalld
Чтобы настроить Apache и firewalld, вы создадите файл задач для роли, указав пакеты для установки и службы для включения. Эти данные будут извлечены из файла переменных и шаблона, который вы будете использовать для замены страницы индекса Apache по умолчанию.
Находясь в ansible-apache
каталоге, создайте файл задач для роли, используя nano
или ваш любимый текстовый редактор:
Вы увидите, что файл уже существует. Удалите то, что там есть, и замените его следующим кодом, чтобы установить необходимые пакеты и включить правильные службы, настройки HTML по умолчанию и настройки брандмауэра:
В этом плейбуке 4 задания:
"Ensure required packages are present"
: эта задача установит пакеты, перечисленные в файле переменных в папкеpkg_list
. Файл переменных будет расположен по адресу~/ansible-apache/vars/main.yml
, и вы создадите его в конце этого шага."Ensure latest index.html is present"
: эта задача скопирует страницу шаблонаindex.html.j2
и вставит ее поверх индексного файла по умолчанию,/var/www/html/index.html
созданного Apache. На этом шаге вы также создадите новый шаблон."Ensure httpd service is started and enabled"
: эта задача запустит и активирует службы, перечисленныеsvc_list
в файле переменных."Whitelist http in firewalld"
: эта задача внесетhttp
службу в белый список в форматеfirewalld
. Firewalld — это комплексное решение брандмауэра, которое по умолчанию присутствует на серверах CentOS. Чтобыhttp
служба работала, вам нужно открыть необходимые порты. Указаниеfirewalld
внести службу в белый список гарантирует, что она внесет в белый список все порты, которые требуются службе.
Сохраните и закройте файл, когда закончите.
Далее создадим templates
каталог для index.html.j2
страницы шаблона:
Создайте саму страницу:
Вставьте следующий шаблонный код:
Сохраните и закройте файл.
Последним шагом в завершении роли является написание файла переменных, который предоставляет имена пакетов и сервисов для нашей основной ролевой игры:
Вставьте содержимое по умолчанию со следующим кодом, который указывает pkg_list
и svc_list
:
Эти списки содержат следующую информацию:
pkg_list
: содержит имена пакетов, которые будет устанавливать роль:httpd
иfirewalld
.svc_list
: содержит имена служб, которые будет запускать и включать роль:httpd
иfirewalld
.
Примечание. Убедитесь, что в вашем файле переменных нет пустых строк, иначе ваш тест не удастся выполнить во время линтинга.
Теперь, когда вы закончили создание своей роли, давайте настроим Molecule, чтобы проверить, работает ли она должным образом.
Шаг 4 — Изменение роли для запуска тестов
В нашем случае настройка Molecule включает в себя изменение файла конфигурации Molecule molecule.yml
для добавления спецификаций платформы. Поскольку вы тестируете роль, которая настраивает и запускает httpd
службу systemd, вам потребуется использовать образ с настроенной системой systemd и включенным привилегированным режимом. Для этого руководства вы будете использовать milcom/centos7-systemd
образ , доступный на Docker Hub . Привилегированный режим позволяет запускать контейнеры почти со всеми возможностями хост-компьютера.
Давайте отредактируем, molecule.yml
чтобы отразить эти изменения:
Добавьте выделенную информацию о платформе:
Сохраните и закройте файл, когда закончите.
Теперь, когда вы успешно настроили тестовую среду, давайте перейдем к написанию тестовых случаев, которые Molecule будет запускать для вашего контейнера после выполнения роли.
Шаг 5 — Написание тестовых случаев
В тесте на эту роль вы проверите следующие условия:
- Что пакеты и установлены
httpd
.firewalld
- Что службы
httpd
иfirewalld
запущены и включены. - Что
http
служба включена в настройках вашего брандмауэра. - Он содержит те же данные, что
index.html
и в вашем файле шаблона.
Если все эти тесты пройдены, роль работает так, как задумано.
Чтобы написать тестовые примеры для этих условий, давайте отредактируем тесты по умолчанию в ~/ansible-apache/molecule/default/tests/test_default.py
. Используя Testinfra, мы напишем тестовые примеры в виде функций Python, использующих классы Molecule.
Открыто test_default.py
:
Удалите содержимое файла, чтобы вы могли писать тесты с нуля.
Примечание. Когда вы пишете свои тесты, убедитесь, что они разделены двумя новыми строками, иначе они не пройдут.
Начните с импорта необходимых модулей Python:
Эти модули включают в себя:
os
: этот встроенный модуль Python обеспечивает функциональность, зависящую от операционной системы, что позволяет Python взаимодействовать с базовой операционной системой.pytest
:pytest
Модуль позволяет писать тесты.testinfra.utils.ansible_runner
: этот модуль Testinfra использует Ansible в качестве серверной части для выполнения команд.
Под импортом модуля добавьте следующий код, который использует серверную часть Ansible для возврата текущего экземпляра хоста:
С вашим тестовым файлом, настроенным для использования серверной части Ansible, давайте напишем модульные тесты для проверки состояния хоста.
Первый тест гарантирует, что httpd
и firewalld
установлены:
Тест начинается с pytest.mark.parametrize
декоратора , который позволяет нам параметризовать аргументы теста. Этот первый тест будет использоваться test_pkg
в качестве параметра для проверки наличия пакетов httpd
и .firewalld
Следующий тест проверяет, запущены ли httpd
и firewalld
включены ли и. В test_svc
качестве параметра принимает:
Последний тест проверяет, что файлы и содержимое переданы как parametrize()
существующие. Если файл не создан вашей ролью и содержимое не настроено должным образом, assert
будет возвращено False
:
В каждом тесте assert
будет возвращаться True
или False
в зависимости от результата теста.
Готовый файл выглядит так:
Теперь, когда вы указали свои тестовые примеры, давайте проверим роль.
Шаг 6 — Проверка роли с помощью Molecule
Как только вы начнете тест, Molecule выполнит действия, которые вы определили в своем сценарии. Теперь давайте снова запустим molecule
сценарий по умолчанию, выполнив действия в тестовой последовательности по умолчанию и внимательно изучив каждое из них.
Запустите тест для сценария по умолчанию еще раз:
Это запустит тестовый запуск. Начальный вывод печатает тестовую матрицу по умолчанию:
--> Validating schema /home/sammy/ansible-apache/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix
└── default
├── lint
├── destroy
├── dependency
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
└── destroy
Давайте рассмотрим каждое тестовое действие и ожидаемый результат, начиная с линтинга.
Действие линтинга выполняет yamllint
, flake8
и ansible-lint
:
yamllint
: этот линтер выполняется для всех файлов YAML, присутствующих в каталоге роли.flake8
: этот линтер кода Python проверяет тесты, созданные для Testinfra.ansible-lint
: этот линтер для плейбуков Ansible выполняется во всех сценариях.
...
--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in /home/sammy/ansible-apache/...
Lint completed successfully.
--> Executing Flake8 on files found in /home/sammy/ansible-apache/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on /home/sammy/ansible-apache/molecule/default/playbook.yml...
Lint completed successfully.
Следующее действие, destroy , выполняется с использованием destroy.yml
файла. Это делается для проверки нашей роли на только что созданном контейнере.
По умолчанию destroy вызывается дважды: в начале тестового прогона для удаления всех ранее существовавших контейнеров и в конце для удаления только что созданного контейнера:
...
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Delete docker network(s)] ************************************************
skipping: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
После завершения действия по уничтожению тест перейдет к зависимости . Это действие позволяет вам извлекать зависимости ansible-galaxy
, если они требуются вашей роли. В этом случае наша роль не:
...
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
Следующее тестовое действие — это проверка синтаксиса , которая выполняется в playbook.yml
плейбуке по умолчанию. Он работает аналогично --syntax-check
флагу в команде ansible-playbook --syntax-check playbook.yml
:
...
--> Scenario: 'default'
--> Action: 'syntax'
playbook: /home/sammy/ansible-apache/molecule/default/playbook.yml
Затем тест переходит к действию создания . Это использует create.yml
файл в каталоге Molecule вашей роли для создания контейнера Docker с вашими спецификациями:
...
--> Scenario: 'default'
--> Action: 'create'
PLAY [Create] ******************************************************************
TASK [Log into a Docker registry] **********************************************
skipping: [localhost] => (item=None)
skipping: [localhost]
TASK [Create Dockerfiles from image names] *************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Discover local Docker images] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Build an Ansible compatible image] ***************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Create docker network(s)] ************************************************
skipping: [localhost]
TASK [Create molecule instance(s)] *********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) creation to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0
После создания тест переходит к действию подготовки . Это действие запускает сценарий подготовки, который переводит хост в определенное состояние перед запуском конвергенции. Это полезно, если ваша роль требует предварительной настройки системы перед выполнением роли. Опять же, это не относится к нашей роли:
...
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
После подготовки действие конвергенции выполняет вашу роль в контейнере, запуская playbook.yml
плейбук. Если в файле настроено несколько платформ molecule.yml
, Molecule сойдется на всех из них:
...
--> Scenario: 'default'
--> Action: 'converge'
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [centos7]
TASK [ansible-apache : Ensure required packages are present] *******************
changed: [centos7]
TASK [ansible-apache : Ensure latest index.html is present] ********************
changed: [centos7]
TASK [ansible-apache : Ensure httpd service is started and enabled] ************
changed: [centos7] => (item=httpd)
changed: [centos7] => (item=firewalld)
TASK [ansible-apache : Whitelist http in firewalld] ****************************
changed: [centos7]
PLAY RECAP *********************************************************************
centos7 : ok=5 changed=4 unreachable=0 failed=0
После покрытия тест переходит к идемпотентности . Это действие проверяет плейбук на идемпотентность, чтобы убедиться в отсутствии неожиданных изменений при нескольких запусках:
...
--> Scenario: 'default'
--> Action: 'idempotence'
Idempotence completed successfully.
Следующее тестовое действие — это действие с побочным эффектом . Это позволяет вам создавать ситуации, в которых вы сможете протестировать больше вещей, например отказоустойчивость HA. По умолчанию Molecule не настраивает сборник побочных эффектов, и задача пропускается:
...
--> Scenario: 'default'
--> Action: 'side_effect'
Skipping, side effect playbook not configured.
Затем Molecule запустит действие верификатора , используя верификатор по умолчанию, Testinfra. Это действие выполняет тесты, которые вы написали ранее в test_default.py
. Если все тесты пройдены успешно, вы увидите сообщение об успехе, и Molecule перейдет к следующему шагу:
...
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in /home/sammy/ansible-apache/molecule/default/tests/...
============================= test session starts ==============================
platform linux -- Python 3.6.5, pytest-3.7.3, py-1.5.4, pluggy-0.7.1
rootdir: /home/sammy/ansible-apache/molecule/default, inifile:
plugins: testinfra-1.14.1
collected 6 items
tests/test_default.py ...... [100%]
========================== 6 passed in 41.05 seconds ===========================
Verifier completed successfully.
Наконец, Molecule уничтожает экземпляры, завершенные во время теста, и удаляет сеть, назначенную этим экземплярам:
...
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Delete docker network(s)] ************************************************
skipping: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
Теперь тестовые действия завершены, подтверждая, что ваша роль работает должным образом.
Вывод
В этой статье вы создали роль Ansible для установки и настройки Apache и firewalld. Затем вы написали модульные тесты с помощью Testinfra, которые Molecule использовала для проверки успешности выполнения роли.
Статья является переводом digitalocean.com