Одно из основных преимуществ Red Hat Ansible Automation Platform заключается в том, что ее язык описания автоматизаций читабелен не только для пары-тройки гуру, но и почти для всех, кто имеет отношение к ИТ. Поэтому вносить свой вклад в автоматизацию могут любые специалисты, что сильно облегчает организацию межкомандного взаимодействия и внедрение автоматизации на уровне корпоративной культуры.
Однако, когда делом занимается такая масса народа, очень важно все тщательно тестировать. При разработке Ansible-контента, вроде плейбуков, ролей или коллекций, мы очень рекомендуем предварительно проверять все в тестовой среде, прежде чем выкатывать в продакшн. Цель такого тестирования – удостовериться, что все работает как надо, чтобы избежать неприятных сюрпризов на «боевых» системах.
Тестирование автоматизационного контента – штука довольно сложная, поскольку для этого надо развертывать специальную инфраструктуру тестирования и настраивать условия тестирования, чтобы обеспечить релевантность самих тестов. Molecule – это комплексная инфраструктура тестирования, которая помогает разрабатывать и тестировать роли Ansible, чтобы вы могли сосредоточиться на разработке автоматизаций и не отвлекаться на управление инфраструктурой тестирования.
Вот как это декларируется в документации проекта:
Molecule позволяет протестировать роль на множестве целевых инстансов, чтобы проверить ее в различных комбинациях операционных систем и сред виртуализации. Без него для каждой из таких комбинаций пришлось бы создавать и поддерживать отдельную среду тестирования, настраивать подключение к тестовым инстансам и откатывать их в исходное состояние перед каждым тестированием. Molecule же делает все это за вас, причем автоматизированным и воспроизводимым образом.
В этой серии из двух частей мы покажем, как применять Molecule при разработке и тестировании ролей Ansible. В первой части рассмотрим установку и настройку Molecule, во второй – разработку ролей с его помощью.
Если роль является частью коллекции, используйте этот подход для разработки и юнит-тестирования роли. В следующей статье мы покажем, как применять Molecule для выполнения интегрированных тестов в коллекции.
Molecule использует драйверы для предоставления целевых инстансов на базе различных технологий, включая Linux-контейнеры, виртуальные машины и облачных провайдеров. По умолчанию он идет с тремя предустановленными драйверами: Docker и Podman для контейнеров, а также драйвером Delegated для создания кастомных интеграций. Драйверы для других провайдеров предоставляются сообществом разработки проекта.
В этом посте мы будем использовать драйвер Podman для разработки и тестирования новой роли с использованием Linux-контейнеров. Podman – это легковесный контейнерный движок для Linux, ему не нужен работающий демон и он обеспечивает запуск rootless-контейнеров, что хорошо для безопасности.
Используя Molecule с драйвером Podman, мы с нуля разработаем и протестируем новую роль Ansible, которая развертывает веб-приложение на базе веб-сервера Apache и должна работать на Red Hat Enterprise Linux (RHEL) 8 или Ubuntu 20.04.
Мы разбираем типовой сценарий, когда роль должна работать на различных версиях операционной системы. Используя Podman и Linux-контейнеры, мы можем создать несколько инстансов, чтобы протестировать роль на разных версиях ОС. Благодаря своей легковесности, контейнеры позволяют быстро итерировать функциональность роли прямо по ходу разработки. Использование контейнеров для тестирования ролей применимо в данной ситуации, поскольку роль конфигурирует только запущенные инстансы Linux. Для тестирования на других целевых системах или облачных инфраструктурах можно использовать драйвер delegated или другие драйверы, предоставляемые сообществом.
Для примеров из этой статьи нужна физическая или виртуальная машина Linux с установленными Python 3 и Podman (мы используем RHEL 8.2). Также Podman должен был сконфигурирован для запуска rootless-контейнеров. Установка Podman выходит за рамки этой статьи, для получения соответствующей информации см. официальную документацию. Установка Podman на RHEL 8 также описывается в документации по контейнерам RHEL 8.
Molecule выполнен в виде Python-пакета и, соответственно, устанавливается через pip. Первым шагом мы создаем выделенное Python-окружение и устанавливаем в него наш Molecule:
Обратите внимание, что мы устанавливаем Molecule с опцией «lint», чтобы pip также поставил инструменты «yamllint» и «ansible-lint», которые позволят нам использовать Molecule для статического анализа кода роли на предмет соответствия стандартам кодирования Ansible.
Установка скачивает все необходимые зависимости из интернета, включая Ansible. Теперь смотрим что мы установили:
Что ж, пора использовать команду «molecule», чтобы инициализировать новую роль Ansible.
Вообще говоря, при разработке новой роли Ansible, она инициализируется командой «ansible-galaxy role init», но мы будем использовать вместо этого команду «molecule». При этом мы получим ту же структуру роли, что и с командой «ansible-galaxy», а также базовую заготовку кода для запуска тестов Molecule.
По умолчанию Molecule использует для выполнения тестов драйвер Docker. Поскольку мы хотим использовать вместо него podman, то при инициализации роли командой «molecule» надо указать соответствующий драйвер с помощью опции «--driver-name=podman».
Переключаемся обратно в каталог «molecule-blog» и инициализируем новую роль «mywebapp» следующей командой:
Molecule создает структуру нашей роли в папке «mywebapp». Переключаемся в эту папку и смотрим, что там:
Molecule складывает свои конфигурационные файлы в подкаталог «molecule». При инициализации новой роли здесь появляется всего один сценарий, который называется «default». Позднее сюда можно добавить свои сценарии для тестирования различных условий. В этой статье мы будем использовать только сценарий «default».
Проверим базовую конфигурацию в файле «molecule/default/molecule.yml»:
Как мы и просили, в этом файле указано, что для тестов применяется драйвер Podman. Здесь же задается платформа по умолчанию для тестового инстанса, через контейнерный образ «docker.io/pycontribs/centos:7», который мы потом поменяем.
В отличие Molecule v2, Molecule v3 не задает линтер по умолчанию. Поэтому откроем конфигурационный файл «molecule/default/molecule.yml» и допишем в конце конфигурацию lint:
Сохраним и закроем файл, и запустим команду «molecule lint» из корневой папки нашего проекта, чтобы прогнать линтер по всему проекту:
На выходе получаем несколько ошибок, поскольку в файле «meta/main.yml» нет ряда требуемых значений. Исправим это: отредактируем файл «meta/main.yml», добавив «author», «company», «license», «platforms» и удалив пустую строку в конце. Для краткости обойдемся без комментариев, и тогда наш «meta/main.yaml» будет выглядеть так:
Еще раз прогоним по проекту линтер и убедимся, что ошибок больше нет.
Итак, наша роль инициализирована и базовая конфигурация molecule тоже на месте. Теперь создадим тестовый инстанс.
По умолчанию Molecule задает только один инстанс, которые называется «instance» и создается из образа «Centos:7». Наша роль, если помните, должна работать на RHEL 8 и Ubuntu 20.04. Кроме того, поскольку она запускает веб-сервер Apache в качестве системной службы, нам нужен контейнерный образ с включенным «systemd».
У Red Hat есть официальный Universal Base Image для RHEL 8 с включенным «systemd»:
• registry.access.redhat.com/ubi8/ubi-init
Для Ubuntu нет официального образа с «systemd», поэтому мы воспользуемся образом, который поддерживается силами Джефа Джирлинга (Jeff Geerling) из сообщества Ansible:
• geerlingguy/docker-ubuntu2004-ansible
Чтобы получить инстансы с «systemd», подправим конфигурационный файл «molecule/default/molecule.yml», убрав из него инстанс «centos:7» и добавив два новых инстанса:
С помощью этих параметров мы монтируем для каждого инстанса временную файловую систему «/run» и «/tmp», а также том «cgroup». Кроме того, мы включаем функцию «SYS_ADMIN», необходимую для запуска контейнеров с Systemd.
Если делать все по уму и выполнять этот пример на машине RHEL 8 с включенным SELinux, то еще надо установить в true логический параметр «container_manage_cgroup», чтобы контейнеры могли запускать Systemd, (подробнее см. документацию RHEL 8):
Для инициализации этих инстансов Molecule использует Ansible Playbook. Изменим и добавим параметры инициализации, модифицировав словарь «provisioner» в конфигурационном файле «molecule/default/molecule.yml».
Он принимает те же самые опции конфигурации, что прописаны в конфигурационном файле «ansible.cfg». Например, обновим конфигурацию провайдера (provisioner), добавив секцию «defaults». Установим интерпретатор Python в «auto_silent», чтобы деактивировать предупреждения. Включим callback-плагины «profile_tasks», «timer» и «yaml», чтобы профайлерская информация включалась в вывод Playbook. И наконец, добавим секцию «ssh_connection» и отключим SSH pipelining, поскольку он не работает с Podman:
Сохраним этот файл и создадим инстанс командой «molecule create» из корневого каталога нашей роли:
Molecule выполнит инициализационный плейбук и создаст оба наших инстанса. Проверим их командой «molecule list»:
Также проверим, что оба контейнера запущены в Podman:
При разработке роли Molecule использует запущенные инстансы для ее тестирования. Если тест проваливается или какая-то ошибка приводит к необратимым изменениям, из-за которых все надо начинать сначала, вы можете в любое время убить эти инстансы командой «molecule destroy» и создать их заново командной «molecule create».
Если вам не терпится и хочется поглубже копнуть тему разработки и тестирования ролей, или тему Ansible-автоматизации, то рекомендуем следующие ресурсы:
Однако, когда делом занимается такая масса народа, очень важно все тщательно тестировать. При разработке Ansible-контента, вроде плейбуков, ролей или коллекций, мы очень рекомендуем предварительно проверять все в тестовой среде, прежде чем выкатывать в продакшн. Цель такого тестирования – удостовериться, что все работает как надо, чтобы избежать неприятных сюрпризов на «боевых» системах.
Тестирование автоматизационного контента – штука довольно сложная, поскольку для этого надо развертывать специальную инфраструктуру тестирования и настраивать условия тестирования, чтобы обеспечить релевантность самих тестов. Molecule – это комплексная инфраструктура тестирования, которая помогает разрабатывать и тестировать роли Ansible, чтобы вы могли сосредоточиться на разработке автоматизаций и не отвлекаться на управление инфраструктурой тестирования.
Вот как это декларируется в документации проекта:
«Molecule призван помочь в разработке и тестировании ролей Ansible, и способствует внедрению подхода, результатом которого являются комплексно проработанные роли, которые хорошо написаны, просты в понимании и поддержке».
Molecule позволяет протестировать роль на множестве целевых инстансов, чтобы проверить ее в различных комбинациях операционных систем и сред виртуализации. Без него для каждой из таких комбинаций пришлось бы создавать и поддерживать отдельную среду тестирования, настраивать подключение к тестовым инстансам и откатывать их в исходное состояние перед каждым тестированием. Molecule же делает все это за вас, причем автоматизированным и воспроизводимым образом.
В этой серии из двух частей мы покажем, как применять Molecule при разработке и тестировании ролей Ansible. В первой части рассмотрим установку и настройку Molecule, во второй – разработку ролей с его помощью.
Если роль является частью коллекции, используйте этот подход для разработки и юнит-тестирования роли. В следующей статье мы покажем, как применять Molecule для выполнения интегрированных тестов в коллекции.
Molecule использует драйверы для предоставления целевых инстансов на базе различных технологий, включая Linux-контейнеры, виртуальные машины и облачных провайдеров. По умолчанию он идет с тремя предустановленными драйверами: Docker и Podman для контейнеров, а также драйвером Delegated для создания кастомных интеграций. Драйверы для других провайдеров предоставляются сообществом разработки проекта.
В этом посте мы будем использовать драйвер Podman для разработки и тестирования новой роли с использованием Linux-контейнеров. Podman – это легковесный контейнерный движок для Linux, ему не нужен работающий демон и он обеспечивает запуск rootless-контейнеров, что хорошо для безопасности.
Используя Molecule с драйвером Podman, мы с нуля разработаем и протестируем новую роль Ansible, которая развертывает веб-приложение на базе веб-сервера Apache и должна работать на Red Hat Enterprise Linux (RHEL) 8 или Ubuntu 20.04.
Мы разбираем типовой сценарий, когда роль должна работать на различных версиях операционной системы. Используя Podman и Linux-контейнеры, мы можем создать несколько инстансов, чтобы протестировать роль на разных версиях ОС. Благодаря своей легковесности, контейнеры позволяют быстро итерировать функциональность роли прямо по ходу разработки. Использование контейнеров для тестирования ролей применимо в данной ситуации, поскольку роль конфигурирует только запущенные инстансы Linux. Для тестирования на других целевых системах или облачных инфраструктурах можно использовать драйвер delegated или другие драйверы, предоставляемые сообществом.
Что нам понадобится
Для примеров из этой статьи нужна физическая или виртуальная машина Linux с установленными Python 3 и Podman (мы используем RHEL 8.2). Также Podman должен был сконфигурирован для запуска rootless-контейнеров. Установка Podman выходит за рамки этой статьи, для получения соответствующей информации см. официальную документацию. Установка Podman на RHEL 8 также описывается в документации по контейнерам RHEL 8.
Приступаем
Molecule выполнен в виде Python-пакета и, соответственно, устанавливается через pip. Первым шагом мы создаем выделенное Python-окружение и устанавливаем в него наш Molecule:
$ mkdir molecule-blog
$ cd molecule-blog
$ python3 -m venv molecule-venv
$ source molecule-venv/bin/activate
(molecule-venv) $ pip install "molecule[lint]"
Обратите внимание, что мы устанавливаем Molecule с опцией «lint», чтобы pip также поставил инструменты «yamllint» и «ansible-lint», которые позволят нам использовать Molecule для статического анализа кода роли на предмет соответствия стандартам кодирования Ansible.
Установка скачивает все необходимые зависимости из интернета, включая Ansible. Теперь смотрим что мы установили:
$ molecule --version
molecule 3.0.4
ansible==2.9.10 python==3.6
Что ж, пора использовать команду «molecule», чтобы инициализировать новую роль Ansible.
Инициализируем новую роль Ansible
Вообще говоря, при разработке новой роли Ansible, она инициализируется командой «ansible-galaxy role init», но мы будем использовать вместо этого команду «molecule». При этом мы получим ту же структуру роли, что и с командой «ansible-galaxy», а также базовую заготовку кода для запуска тестов Molecule.
По умолчанию Molecule использует для выполнения тестов драйвер Docker. Поскольку мы хотим использовать вместо него podman, то при инициализации роли командой «molecule» надо указать соответствующий драйвер с помощью опции «--driver-name=podman».
Переключаемся обратно в каталог «molecule-blog» и инициализируем новую роль «mywebapp» следующей командой:
$ molecule init role mywebapp --driver-name=podman
--> Initializing new role mywebapp...
Initialized role in /home/ricardo/molecule-blog/mywebapp successfully.
Molecule создает структуру нашей роли в папке «mywebapp». Переключаемся в эту папку и смотрим, что там:
$ cd mywebapp
$ tree
.
+-- defaults
¦ L-- main.yml
+-- files
+-- handlers
¦ L-- main.yml
+-- meta
¦ L-- main.yml
+-- molecule
¦ L-- default
¦ +-- converge.yml
¦ +-- INSTALL.rst
¦ +-- molecule.yml
¦ L-- verify.yml
+-- README.md
+-- tasks
¦ L-- main.yml
+-- templates
+-- tests
¦ +-- inventory
¦ L-- test.yml
L-- vars
L-- main.yml
10 directories, 12 files
Molecule складывает свои конфигурационные файлы в подкаталог «molecule». При инициализации новой роли здесь появляется всего один сценарий, который называется «default». Позднее сюда можно добавить свои сценарии для тестирования различных условий. В этой статье мы будем использовать только сценарий «default».
Проверим базовую конфигурацию в файле «molecule/default/molecule.yml»:
$ cat molecule/default/molecule.yml
---
dependency:
name: galaxy
driver:
name: podman
platforms:
- name: instance
image: docker.io/pycontribs/centos:7
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
Как мы и просили, в этом файле указано, что для тестов применяется драйвер Podman. Здесь же задается платформа по умолчанию для тестового инстанса, через контейнерный образ «docker.io/pycontribs/centos:7», который мы потом поменяем.
В отличие Molecule v2, Molecule v3 не задает линтер по умолчанию. Поэтому откроем конфигурационный файл «molecule/default/molecule.yml» и допишем в конце конфигурацию lint:
$ vi molecule/default/molecule.yml
...
verifier:
name: ansible
lint: |
set -e
yamllint .
ansible-lint .
Сохраним и закроем файл, и запустим команду «molecule lint» из корневой папки нашего проекта, чтобы прогнать линтер по всему проекту:
$ molecule lint
На выходе получаем несколько ошибок, поскольку в файле «meta/main.yml» нет ряда требуемых значений. Исправим это: отредактируем файл «meta/main.yml», добавив «author», «company», «license», «platforms» и удалив пустую строку в конце. Для краткости обойдемся без комментариев, и тогда наш «meta/main.yaml» будет выглядеть так:
$ vi meta/main.yml
galaxy_info:
author: Ricardo Gerardi
description: Mywebapp role deploys a sample web app
company: Red Hat
license: MIT
min_ansible_version: 2.9
platforms:
- name: rhel
versions:
- 8
- name: ubuntu
versions:
- 20.04
galaxy_tags: []
dependencies: []
Еще раз прогоним по проекту линтер и убедимся, что ошибок больше нет.
$ molecule lint
--> Test matrix
L-- default
+-- dependency
L-- lint
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'lint'
--> Executing: set -e
yamllint .
ansible-lint .
Итак, наша роль инициализирована и базовая конфигурация molecule тоже на месте. Теперь создадим тестовый инстанс.
Создаем тестовый инстанс
По умолчанию Molecule задает только один инстанс, которые называется «instance» и создается из образа «Centos:7». Наша роль, если помните, должна работать на RHEL 8 и Ubuntu 20.04. Кроме того, поскольку она запускает веб-сервер Apache в качестве системной службы, нам нужен контейнерный образ с включенным «systemd».
У Red Hat есть официальный Universal Base Image для RHEL 8 с включенным «systemd»:
• registry.access.redhat.com/ubi8/ubi-init
Для Ubuntu нет официального образа с «systemd», поэтому мы воспользуемся образом, который поддерживается силами Джефа Джирлинга (Jeff Geerling) из сообщества Ansible:
• geerlingguy/docker-ubuntu2004-ansible
Чтобы получить инстансы с «systemd», подправим конфигурационный файл «molecule/default/molecule.yml», убрав из него инстанс «centos:7» и добавив два новых инстанса:
$ vi molecule/default/molecule.yml
---
dependency:
name: galaxy
driver:
name: podman
platforms:
- name: rhel8
image: registry.access.redhat.com/ubi8/ubi-init
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
capabilities:
- SYS_ADMIN
command: "/usr/sbin/init"
pre_build_image: true
- name: ubuntu
image: geerlingguy/docker-ubuntu2004-ansible
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
capabilities:
- SYS_ADMIN
command: "/lib/systemd/systemd"
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
lint: |
set -e
yamllint .
ansible-lint .
С помощью этих параметров мы монтируем для каждого инстанса временную файловую систему «/run» и «/tmp», а также том «cgroup». Кроме того, мы включаем функцию «SYS_ADMIN», необходимую для запуска контейнеров с Systemd.
Если делать все по уму и выполнять этот пример на машине RHEL 8 с включенным SELinux, то еще надо установить в true логический параметр «container_manage_cgroup», чтобы контейнеры могли запускать Systemd, (подробнее см. документацию RHEL 8):
sudo setsebool -P container_manage_cgroup 1
Для инициализации этих инстансов Molecule использует Ansible Playbook. Изменим и добавим параметры инициализации, модифицировав словарь «provisioner» в конфигурационном файле «molecule/default/molecule.yml».
Он принимает те же самые опции конфигурации, что прописаны в конфигурационном файле «ansible.cfg». Например, обновим конфигурацию провайдера (provisioner), добавив секцию «defaults». Установим интерпретатор Python в «auto_silent», чтобы деактивировать предупреждения. Включим callback-плагины «profile_tasks», «timer» и «yaml», чтобы профайлерская информация включалась в вывод Playbook. И наконец, добавим секцию «ssh_connection» и отключим SSH pipelining, поскольку он не работает с Podman:
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
callback_whitelist: profile_tasks, timer, yaml
ssh_connection:
pipelining: false
Сохраним этот файл и создадим инстанс командой «molecule create» из корневого каталога нашей роли:
$ molecule create
Molecule выполнит инициализационный плейбук и создаст оба наших инстанса. Проверим их командой «molecule list»:
$ molecule list
Instance Name Driver Name Provisioner Name Scenario Name Created Converged
--------------- ------------- ------------------ --------------- --------- -----------
rhel8 podman ansible default true false
ubuntu podman ansible default true false
Также проверим, что оба контейнера запущены в Podman:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2e2f14eaa37b docker.io/geerlingguy/docker-ubuntu2004-ansible:latest /lib/systemd/syst... About a minute ago Up About a minute ago ubuntu
2ce0a0ea8692 registry.access.redhat.com/ubi8/ubi-init:latest /usr/sbin/init About a minute ago Up About a minute ago rhel8
При разработке роли Molecule использует запущенные инстансы для ее тестирования. Если тест проваливается или какая-то ошибка приводит к необратимым изменениям, из-за которых все надо начинать сначала, вы можете в любое время убить эти инстансы командой «molecule destroy» и создать их заново командной «molecule create».
Заключение
Если вам не терпится и хочется поглубже копнуть тему разработки и тестирования ролей, или тему Ansible-автоматизации, то рекомендуем следующие ресурсы:
- Ansible Whitepaper — Achieving Rolling Updates & Continuous Deployment
- Ansible Whitepaper — Ansible in Depth
- Getting Started Guide — Molecule documentation
- ansible-community/molecule: Molecule aids in the development and testing of Ansible roles
- Roles in the official Ansible documentation
- Galaxy Developer Guide
amarao
Молекула мертва, потому что её highly opinionated не работает IRL.
1) Большинство людей хочет проверять плейбуки, а не роли.
2) Тесты для тривиальных ролей писать особо не надо, а для нетривиальных у молекулы нет никаких возможностей правильно описать нетривиальность (например, внешние зависимости).
3) Драйвера ужасны. Любая роль, выходящая за рамки "ой мы тут сделали
file: state=directory
и нам надо написать ТЕСТЫ ДЛЯ ЭТОЙ РОЛИ" тут же утыкается в то, что докер на сервера похож, мягко говоря, не совсем — привет systemd, привет reboot, привет ntp, привет /etc/hosts, и т.д. А попытка поменять драйвер с контейнерного на (хотя бы виртуалки) открывает бездны нового порядка. Например, плейбука для подъёма драйвера пишется в /tmp и используется оттуда, даже если драйвер поменяли. (Перезагрузите компьютер, чтобы всё начало работать).Для модулей ansible-test куда более годный инструмент, хоть он и тащит много лишнего по полиси (например, требование специальных путей откуда можно запускать).
Для плейбук же ничего годного нет, приходится всё самому изобретать.
MMik
Amarao, тесты инфраструктуры на Goss не пробовали писать? Как оцените инструмент?
amarao
Я мельком её (его?) смотрел. Их подход работает для простых случаев, а в них и так всё хорошо. В сложных случаях же выкрутасы с ещё одним template language — ой, не надо.
Мы используем testinfra, у которой помимо мощи pytest'а под капотом ещё какая-никакая интеграция с ansible'ом (можно использовать инвентори и дёргать модули в checkmode'е, а если очень хочется, то можно и транспорт ансибла использовать).
dominigato
Одно другое не заменяет.
Во-первых надо, может вам не надо — так не пишите. Во-вторых у молекулы есть requirements management, prepare стадия и т.д. Что именно не хватает?
Вы понимаете что молекула и впрочем ансибл тут совершенно ни при чем? Это технические сложности с докером, к ним и обращайтесь, а лучше используйте podman как в статье рекомендуется. Хотя бы /etc/hosts и systemd вас перестанут волновать. Ну или используйте delegated.
Опять же, с виртуальным, или еще лучше — delegated драйвер, это почти все равно как гонять это на обычном сервере. Молекула тут вообще ни при чем, это проблема с вашими ролями и вашим окружением. Она то свое дело делает.
Скорее всего вы ожидаете от этого проекта много того, чего он никогда в жизни не обещал и не был предназначен. Все ваши проблемы из-за ваших специфических технических сложностей и из-за непонимания ансибл и его принципа построения ролей в частности.
amarao
Если бы в ансибле роли были аналогом функций, жизнь была бы сильно проще. Но это не так. Функции принимают значение, имеют локальные перменные и могут вернуть значение. Как мне вернуть значение из функции без сайд-эффектов в глобальных перменных? Я бы очень не отказался от такого синтакиса:
И внутри роли
- return: somevalue
к сожалению, ничего этого нет. Вместо этого у нас глобальные переменные с несовместимыми lifetimes.
Насчёт моего окружения вы правы. Взял молекулу, взял ансибл, сказал запускать на libvirt'е, а потом поменял драйвер на openstack, а libvirt всё ещё используется, потому что записано в /tmp (и имеет больший приоритет, чем то, что в плейбуке). Я один день на это "моё окружение" потратил и полностью для себя молекулу закопал.
Основная же проблема в том, что reusable roles в отсутствии изоляции — необоснованная фантазия. Это легко заметить по, например, даже rhel'овому коду для ансибла — openshift, ceph-ansible — у обоих всё, мягко говоря, не в рамках мечтаний о "reusable roles". Роль обычно пишется под задачу и в отсутствии задачи смысла не имеет. А тогда уже надо плейбуки тестировать.
Насчёт непонимания анисбла — да, спасибо, это вы точно заметили. Каждый раз, когда я в ansible bingo дописываю пример, я глубоко не понимаю как это можно понимать.
dominigato
Я лет 7 наверное слушаю постоянное нытье что роли в ансибле это плохо, они плохо работают, это никогда не работает и т.д. и т.п. И каждый раз когда дело доходит до деталей, оказывается что человек просто не следует никаким вообще good practices, guidelines, нет никакого нормального дизайна, а иногда просто творит необъяснимые странные вещи. Но виноват ансибл и роли.
Вот у вас все плохо, а у меня все прекрасно с reusable roles, кому лучше?
Это поправимо, читайте больше документации, делайте хороший продуманный дизайн перед тем как запускать хаос написанный на коленках, наймите девопса наконец-то вместо сисадмина, и будет вам счастье. :)
amarao
Скажите, сколько живёт переменная, заданная в task/vars? А переменная, заданная в play/vars? А set_fact? А если переменная set_fact из include? А если переменная из role/defaults, которая была include?
Вы знаете, мы очень много пишем на ансибле, и у нас сложилась очень сильная практическая школа. Один из принципов этой школы состоит в том, что чем проще, тем лучше (даже если решение будет неуниверсальным). Это значает, что никаких include_vars в зависимости от переменных, никогда не используется include_role, а include_tasks в loop — это code smell (который иногда нужен, но которого надо избежать). И один из принципов говорит, что нельзя бороться за универсализацию ролей. Чем более универсальна роль, тем более волшебным образом она взрывается.
Вообще, максима написания кода на Ансибле — чем меньше решений принимается на Ансибле, тем лучше. Анисбл — отличный транспорт и механизм для сайд-эффектов, но совершеннейший кошмар для программирования (принятия решений). Каждый when — это плохо. Каждый and или вложенное условие — это плохо.
Когда же вы следуете практике максимальной специализации роли, оказывается, что в отрыве от плейбуки она не особо и нужна. Так что тестировать надо плейбуки.
(Вот вам контр-пример того, как писать не надо — роль пытается принимать стопятьсот решений https://github.com/AlexeySetevoi/ansible-clickhouse/blob/master/tasks/main.yml… и взрывается, если процесс решений не совсем такой, как ожидали. Например, case sensitive file system. Баг до сих пор не заслали, но он там есть).
dominigato
Это конечно очень оригинальная идея, предлагаю запатентовать, украдут же.
Я рад что вы на своем опыте открываете good practices ансибла, но лучше все-таки учиться на чужих ошибках. Все правильно, ансибл — не для программирования, у ансибл девов это уже мантра. Но есть люди, при виде микроскопа у которых, руки сразу тянутся к гвоздям.
Вот как вы к этом выводу пришли, для меня загадка. Нужно тестировать отдельную фунциональность ролей, каждая из которых «хорошо умеет делать что-то одно».
amarao
Ну вот видите, вроде, согласились, а потом строго наоборот перевернули. Вы говорите расхожую unix-истину "хорошо умеет делать что-то одно". Не хорошо, а минимально необходимо. Роль для postgress не умеет "хорошо настраивать постгресс", а настраивает только то, что нужно в проекте. Это снижает сложность ролей на несколько порядков и именно в этом месте попытка писать роли как программы или функции (которые делают одно, но делают хорошо), натыкается на полное отсутствие изоляции. Одна ошибка в именновании приватной перменной (ой, у нас же нет приватных перменных) и роль взрывает проект из-за того, что еёйный set_fact с database_ip оверрайдит roles/vars/database_ip в другой роли. Разумеется, существует техника defensive programming по именованию приватных переменных в роли (что увеличивает нагрузку на пишущего в несколько раз); но лучший выход из ситуации — не пытаться делать "хорошо", а делать минимально необходимое без запаса на расширение. Нужно расширение — перепиши простой предыдущий код. Это легче, чем сопровождать универсальный код.
dominigato
Так что если писать сначала нормально, то никакой нагрузки на пишущего нет. А если и линтер настроить чтобы проверял это, то вообще можно спать спокойно.
Ну если она делает все что нужно для постгрес в проекте, то не вижу проблемы. Если же она пытается прописать IP везде где можно, вмешиваясь там где другие роли работают и т.д. — то это уже дизайн проблема.
Для таких вещей можно, кстати, использовать коллекции, где можно хостить много ролей, которые делают что-то одно, и плейбуки, которые их комбинируют чтобы сделать что-то большое и сложное.
amarao
То есть проблемы с изоляцией имён не существует. В питоне есть локальные переменные, в Ансибле нет, "но в ведь в питоне приватные перменные тоже underscore обозначают".
Насчёт "прописать IP" — этот вопрос мы ещё даже близко не затронули, потому что всё что касается хождения по чужим перменным — боль и постоянная балансировка между кривым решением, code smell и лапшой.
В целом я вашу позицию понял — вы проблем не видите, а всё остальное — моя некомпетентность. Ваша позиция мне ясна, менять её у меня стимула нет.
dominigato
Вы сами это признаете, а потом требуете от него быть языком программирования.
Или может в терраформе есть какие-то приватные переменные?
Я их не вижу потому что использую для каждого дела свою утилиту. Если хочется попрограммировать — ansible-runner вам в помощь.
ultral
молекулой можно тестить плэйбуки. но это не удобно. делаешь "мета-роль", в которую подсовываешь вместо converge.yml свой плэйбук. шатко, хлипко… я если честно таким образом плэйбуки не тестирую.
Но тут стоит прокомментировать, у меня плэйбуки обычно максимально простые: состоят из нескольких плэев, в которых нет тасков, только инклюд ролей. как итог достаточно тестить отдельные роли, а плэйбуки линтить. но подозреваю