[DevOps] Тестирование ansible роли для RabbitMQ кластера с помощью molecule
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Molecule — это фреймворк, предназначенный для тестирования ролей в Ansible. На хабре довольно много статей про тестирование с помощью molecule и почти во всех статьях говорится о неких "сложных сценариях тестирования для ansible", и далее в примерах обычно идут какие-то простенькие роли и тесты. Мне стало интересно протестировать более сложную роль, например роль для создания RabbitMQ кластера.Используемые версии программ на момент написания статьи. Не гарантируется корректная работа для molecule версии ниже 3.3debian 10 Busteransible-3.4.0molecule-3.3.0docker-ce-20.10.6yamllint-1.26.1ansible-lint-5.0.8Устанавливаем ansible и molecule.pip3 install --user ansible (как именно устанавливать не столь важно, в приведенном примере установка идет в хоумдир пользователя). pip3 install --user molecule[docker] (мы будем использовать драйвер докера)Устанавливаем линтерыpip3 install --user ansible-lint yamllintУстановка докера выходит за рамки этой статьи, стоит отметить только что докер вы можете установить на эту же машину, где будете запускать molecule или же установить докер на любую другую машину в сети (например если мощности локальной машины не хватает) или же использовать уже существующий докер сервер.Во втором случае на локальную машину нужно установить только докер клиент и выставить переменную DOCKER_HOST="ssh://ansible@адрес_вашего_докер_сервера", где ansible - аккаунт, который имеет ssh доступ на сервер и под которым будут создаваться докер контейнеры. Аккаунт также должен состоять в группе docker на докер сервере.Описание ансибл роли тоже выходит за рамки статьи, можно взять любую похожую роль, где есть логика создания кластера.Переходим в нашу условную роль
cd roles/role_rabbitmq
Создаем конфиги для линтеров в текущей директории (дефолтные конфиги будут генерить много лишних алертов) или же создаем линки на общие конфиги..ansible-lint
---
exclude_paths:
- .cache/
- .git/
- molecule/
skip_list:
- command-instead-of-module
- git-latest
- no-handler
- package-latest
- empty-string-compare
- command-instead-of-shell
- meta-no-info
- no-changed-when
- no-relative-paths
- risky-shell-pipe
- role-name
- unnamed-task
.yamllint
---
extends: default
ignore: |
templates/
sites/
files/
old/
README.md
LICENSE
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 1
brackets:
min-spaces-inside: 0
max-spaces-inside: 1
comments:
require-starting-space: false
level: error
indentation:
spaces: 2
indent-sequences: consistent
line-length: disable
truthy: disable
Создаем директорию molecule/cluster для нашего сценария.
mkdir molecule/cluster
Открываем в редакторе файл molecule/cluster/Dockerfile.j2. Данный конфиг будет использоваться при создании докер контейнеров. Опять же ничто не ограничивает вашу фантазию - можно использовать уже готовый имидж с ансибл на борту или создать свой.
FROM registry.company.net/debian/buster:latest
ENV DEBIAN_FRONTEND noninteractive
ENV pip_packages "ansible"
ENV http_proxy "http://10.10.0.1:8888"
ENV https_proxy "http://10.0.0.1:8888"
ENV no_proxy "127.0.0.1,localhost,*.company.net,10.0.0.0/8,192.168.0.0/16,172.0.0.0/8"
# Install dependencies.
RUN apt update \
&& apt-get install -y --no-install-recommends \
sudo systemd systemd-sysv \
build-essential wget libffi-dev libssl-dev \
python3-apt python3-cryptography python3-pip python3-dev python3-setuptools python3-wheel \
procps passwd curl lsof netcat gnupg ca-certificates openssh-client less vim iputils-ping iproute2 \
debian-archive-keyring dnsutils \
&& rm -rf /var/lib/apt/lists/* \
&& rm -Rf /usr/share/doc && rm -Rf /usr/share/man \
&& apt-get clean
# Create ansible user
RUN groupadd --system ansible \
&& useradd --system --comment "Ansible remote management" --home-dir /home/ansible --create-home --gid ansible --shell /bin/bash --password "*" an
sible && echo "%ansible ALL = (ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible
# Add company repo
RUN curl -k "https://certs.company.net/ca.pem" > /usr/local/share/ca-certificates/ca.crt && update-ca-certificates \
&& curl -k "https://company.net/repos/keys/company_repo_key.gpg" | apt-key add \
&& echo "deb https://company.net/repos/buster buster-local main > /etc/apt/sources.list.d/company.list && apt-get update && pip3 install $pip_packages
# Install Ansible inventory file.
RUN mkdir -p /etc/ansible && echo "[local]\nlocalhost ansible_connection=local" > /etc/ansible/hosts
# Exclude /usr/share/doc
# Если программа использует файлы из /usr/share/doc, то следует добавить диру в игнор для dpkg, иначе файлы будут удалены
RUN sed -i 's/path-exclude \/usr\/share\/doc/#path-exclude \/usr\/share\/doc/' /etc/dpkg/dpkg.cfg.d/docker
# Make sure systemd doesn't start agettys on tty[1-6].
RUN rm -f /lib/systemd/system/multi-user.target.wants/getty.target
VOLUME ["/sys/fs/cgroup"]
CMD ["/lib/systemd/systemd"]
Создаем файл molecule/cluster/prepare.yml. Данный файл используется молекулой также как и в ансибле - для различных pre-tasks. В данном случаем мы обновляем дебиан пакеты и устанавливаем питон модуль pika для RabbitMQ.
---
- name: prepare
hosts: all
gather_facts: no # не используем сбор фактов для ускорения выполнения
tasks:
- name: update apt cache
block:
- name: update apt cache
apt:
update_cache: yes
- name: perform upgrade of all packages to the latest version
apt:
upgrade: dist
force_apt_get: yes
- name: install python pika
pip:
name:
- pika
executable: pip3
Создаем файл molecule/cluster/converge.yml. В данном файле мы непосредственно указываем ансибл роль для тестирования. Обратите внимание на hosts, имя должно совпадать с именем группы в molecule.yml
---
- name: Converge
hosts: rabbitmq_cluster
roles:
- role: role_rabbitmq
Создаем файл molecule/cluster/molecule.yml. По сути это главный файл, где мы описываем все необходимые параметры для запуска наших тестов. В данном случае мы создаем докер сеть cluster 192.168.0.0/24 и создаем три докер контейнера в этой сети - node01, node01, node03 с заранее заданными айпи адресами 192.168.0.1/2/3. Это нужно для создания RabbitMQ кластера из трех нод, где ноды должны видеть друг друга.Инвентори мы определяем как
inventory:
links:
group_vars: ../../../../files/molecule/group_vars/
и
groups:
- rabbitmq_cluster
Поэтому создаем в структуре ансибл файл files/molecule/group_vars/rabbitmq_cluster.yml где описываем все необходимые параметры нашей ансибл роли role_rabbitmq
---
rabbitmq_cluster: yes
certs_dir: /etc/rabbitmq/ssl
rabbitmq_ssl: yes
rabbitmq_ssl_certs:
- "_.company.net"
rabbitmq_cookie: NJWHJPAOPYKSGTRGDLTN
# обратите внимание, здесь мы указываем короткие имена нод, заданные в нашем molecule.yml
# все ноды из списка должны узнавать друг друга по этим коротким именам
rabbitmq_nodes:
- node01
- node02
- node03
rabbitmq_master: rabbit@node01
rabbitmq_master_node: node01
rabbitmq_vhosts:
- name: /test
rabbitmq_users:
- user: test
password: test
vhost: /test
rabbitmq_exchanges:
- name: test
type: direct
durable: yes
vhost: /test
rabbitmq_queues:
- name: test
durable: yes
vhost: /test
rabbitmq_bindings:
- name: test
destination: test
destination_type: queue
vhost: /test
rabbitmq_policies:
- name: ha-replica
vhost: /test
tags:
ha-mode: exactly
ha-params: 2
ha-sync-mode: automatic
molecule.yml
---
dependency:
name: galaxy
options:
ignore-certs: True
driver:
name: docker
platforms:
- name: node01
image: registry.company.net/debian/buster:latest
# pre_build_image: true
privileged: True
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro
capabilities:
- SYS_ADMIN
command: "/lib/systemd/systemd"
dns_servers:
- 10.0.0.1
groups:
- rabbitmq_cluster
docker_networks:
- name: cluster
ipam_config:
- subnet: "192.168.0.0/24"
gateway: "192.168.0.254"
networks:
- name: cluster
ipv4_address: "192.168.0.1"
network_mode: default
- name: node02
image: registry.company.net/debian/buster:latest
privileged: True
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro
capabilities:
- SYS_ADMIN
command: "/lib/systemd/systemd"
dns_servers:
- 10.0.0.1
groups:
- rabbitmq_cluster
networks:
- name: cluster
ipv4_address: "192.168.0.2"
network_mode: default
- name: node03
image: registry.company.net/debian/buster:latest
privileged: True
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro
capabilities:
- SYS_ADMIN
command: "/lib/systemd/systemd"
dns_servers:
- 10.0.0.1
groups:
- rabbitmq_cluster
networks:
- name: cluster
ipv4_address: "192.168.0.3"
network_mode: default
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
host_key_checking: False
gathering: smart
callback_whitelist: profile_tasks, timer, yaml
ssh_connection:
pipelining: True
inventory:
links:
group_vars: ../../../../files/molecule/group_vars/
ansible_args:
- -e molecule_run=True
- -e use_proxy=False
env:
MOLECULE_NO_LOG: 0
ANSIBLE_VERBOSITY: 1
verifier:
name: ansible
lint: |
set -e
ansible-lint .
scenario:
name: cluster
test_sequence:
- dependency
- lint
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy
Через ansible_args можно добавлять различные переменные для ансибл роли
ansible_args:
- -e molecule_run=True
- -e use_proxy=False
Через env можно устанавливать различные переменные environment. В данном случае мы увеличиваем дебаг для ансибла (аналогично опции -v) через ANSIBLE_VERBOSITY.MOLECULE_NO_LOG незадокументированная опция молекулы, позволяет ставить no_log=no для удобства отладки (по дефолту no_log в молекуле всегда yes). При этом в роли можно использовать такую конструкцию no_log: "{{ molecule_no_log|d(False)|ternary(False, True) }}". Если molecule_no_log=0, то выставить no_log: no, иначе no_log: yes. Так как используются тестовые аккаунты и пароли, то запись этих данных в лог некритична.
env:
MOLECULE_NO_LOG: 0
ANSIBLE_VERBOSITY: 1
В последних версиях ansible-lint сам вызывает yamllint, поэтому можно указать линтер только ansible-lint
lint: |
set -e
ansible-lint .
В scenario мы определяем наш сценарий cluster и все шаги, необходимые для тестирования. Просмотреть все шаги можно через команду molecule matrix test.Обратите внимание на сценарии side_effect и verify, если их непосредственно не указать, то у меня они почему-то не вызывались, хотя показаны в выводе molecule matrix.
scenario:
name: cluster
test_sequence:
- dependency
- lint
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy
Попробуем запустить сценарий cluster, если не указать -s то молекула запустит сценарий defaultmolecule test -s cluster > /tmp/log 2>&1Молекула начинает прогонять указанные в test_sequence шаги, причем делает это дважды для соблюдения idempotence. Если во втором тесте будут отличия от первого теста, то молекула завершит работу с ошибкой. Не всегда это работает как нужно (например если конфиг меняется динамически самим сервисом, как в случает с редис), хотя это всегда можно обойти директивой ансибла changed_when: noВ конце в логе /tmp/log должен появиться отчет с финальным сообщением "Idempotence completed successfully", то есть ошибок не найдено и роль можно смело использовать в продакшн ;). При возникновении ошибки на любом шаге, молекула прекращает работу и останавливает свои докер-контейнеры.Если нужно посмотреть что же вызывает ошибку или проверить состояние конфига, то можно вызывать молекулу с опцией converge, molecule converge -s cluster. В этом случае молекула прогоняет все таски, указанные в converge.yml и не запускает destroy. Можно зайти в контейнер через "docker exec -it container_id /bin/bash" и просмотреть логи или проверить конфиги.Самое интересное у молекулы на мой взгляд это side-effect и verify. Через side-effect таски можно задавать различные деструктивные действия (что-то вроде chaos monkey). А через verify таски можно проверять финальное состояние системы.Например скажем молекуле сделать рестарт сервису rabbitmq на каждой ноде после создания кластера (но ничто не ограничивает вас в фантазии).Создаем файл molecule/cluster/side_effect.yml
---
- name: Side Effect
serial: 1
hosts: all
gather_facts: no # факты нам не нужны
tasks:
- name: restart rabbitmq service
block:
- name: stop rabbitmq service
systemd:
name: rabbitmq-server
state: stopped
failed_when: no
- name: pause
pause:
seconds: 15
- name: start rabbitmq service
systemd:
name: rabbitmq-server
state: started
failed_when: no
Создаем файл molecule/cluster/verify.yml и добавим различные базовые проверки для нашего кластера (опять же ничто не ограничивает вашу фантазию).
---
- name: Verify
hosts: all
gather_facts: no
tasks:
- name: cluster status
block:
- name: get cluster status
command: "rabbitmqctl cluster_status --formatter json"
register: output
- name: set facts
set_fact:
cluster_output: "{{ output.stdout|from_json }}"
- name: print nodes
debug:
var: cluster_output.disk_nodes
- name: verify fail
fail:
msg: "FAIL: number of nodes is less than 3"
when:
- cluster_output.disk_nodes | length < 3
run_once: yes
- name: check vhosts
block:
- name: get vhosts
command: "rabbitmqctl list_vhosts --formatter json"
register: output
- name: set facts
set_fact:
vhost_output: "{{ output.stdout|from_json }}.name"
- name: print vhosts
debug:
var: vhost_output
- name: verify fail
fail:
msg: "FAIL: vhost is missing"
when:
- "'/test' not in vhost_output"
run_once: yes
- name: check users
block:
- name: get users
command: "rabbitmqctl list_users --formatter json"
register: output
- name: set facts
set_fact:
user_output: "{{ output.stdout|from_json }}.user"
- name: print users
debug:
var: user_output
- name: verify fail
fail:
msg: "FAIL: user is missing"
when:
- "'test' not in user_output"
run_once: yes
- name: check queues
block:
- name: get queues
command: "rabbitmqctl -p /test list_queues --formatter json"
register: output
- name: set facts
set_fact:
queue_output: "{{ output.stdout|from_json }}.name"
- name: print queues
debug:
var: queue_output
- name: verify fail
fail:
msg: "FAIL: queue is missing"
when:
- "'test' not in queue_output"
run_once: yes
- name: check exchanges
block:
- name: get exchanges
command: "rabbitmqctl -p /test list_exchanges --formatter json"
register: output
- name: set facts
set_fact:
exchange_output: "{{ output.stdout|from_json }}.name"
- name: print exchanges
debug:
var: exchange_output
- name: verify fail
fail:
msg: "FAIL: exchange is missing"
when:
- "'test' not in exchange_output"
run_once: yes
- name: check bindings
block:
- name: get bindings
command: "rabbitmqctl -p /test list_bindings --formatter json"
register: output
- name: set facts
set_fact:
binding_output: "{{ output.stdout|from_json }}.source_name"
- name: print bindings
debug:
var: binding_output
- name: verify fail
fail:
msg: "FAIL: binding is missing"
when:
- "'test' not in binding_output"
run_once: yes
- name: check policies
block:
- name: get policies
command: "rabbitmqctl -p /test list_policies --formatter json"
register: output
- name: set facts
set_fact:
policy_output: "{{ output.stdout|from_json }}.name"
- name: print policies
debug:
var: policy_output
- name: verify fail
fail:
msg: "FAIL: policy is missing"
when:
- "'ha-replica' not in policy_output"
run_once: yes
- name: check publish
block:
- name: install consumer script
copy:
src: ../../../../files/molecule/scripts/consumer.py
dest: /usr/local/bin/consumer.py
owner: root
mode: 0755
- name: publish a message to a queue
rabbitmq_publish:
url: "amqp://test:test@localhost:5672/%2Ftest"
queue: test
body: "Test message"
content_type: "text/plain"
durable: yes
- name: receive a message from the queue
command: /usr/local/bin/consumer.py
run_once: yes
Так как ansible lookup не очень хорошо работает в докер-контейнере, создаем files/molecule/scripts/consumer.py, небольшой скрипт на питоне, который печатает сообщения из очереди test.
#!/usr/bin/python3
import pika, sys
url = 'amqp://test:test@localhost/%2ftest'
params = pika.URLParameters(url)
params.socket_timeout = 1
connection = pika.BlockingConnection(params)
channel = connection.channel()
channel.queue_declare(queue='test', durable=True)
method_frame, header_frame, body = channel.basic_get(queue = 'test')
if method_frame is None:
connection.close()
sys.exit('Queue is empty!')
else:
channel.basic_ack(delivery_tag=method_frame.delivery_tag)
connection.close()
print(body)
Проверяем side-effect
molecule converge -s cluster
molecule side-effect -s cluster
Проверяем verify
molecule verify -s cluster
Если все хорошо, запускаем полный тест и проверяем лог.
molecule test -s cluster >/tmp/log 2>&1
tail -f /tmp/log
===========
Источник:
habr.com
===========
Похожие новости:
- [Системное администрирование, MySQL, Серверное администрирование, Администрирование баз данных] Создаем базу данных MySQL с Ansible (перевод)
- [C++, Unreal Engine, DevOps] IncrediBuild: Как ускорить сборку и анализ вашего проекта
- [C++, Unreal Engine, DevOps] IncrediBuild: How to Speed up Your Project's Build and Analysis
- [Oracle, Программирование, SQL, DevOps] Настройка CI/CD скриптов миграции БД с нуля с использованием GitLab и Liquibase
- [Облачные вычисления, DevOps] Как ускорить работу микросервиса с помощью многопоточности, асинхронности и кэша: пошаговая инструкция
- [Amazon Web Services, DevOps, Google Cloud Platform, Kubernetes] Как готовить Helm правильно: несколько полезных рецептов
- [Git, Системы управления версиями, Системы сборки, DevOps] Вышел релиз GitLab 13.11 с агентом для Kubernetes и настройкой конвейера для проверки соответствия требованиям
- [Системное администрирование, Карьера в IT-индустрии, DevOps, Kubernetes] Как проходит DevOps-стажировка в Southbridge
- [Информационная безопасность, DevOps] Введение Open Policy Agent (OPA) (перевод)
- [Системное администрирование, Серверное администрирование, DevOps, Kubernetes] Как Asana использует Kubernetes (перевод)
Теги для поиска: #_devops, #_ansible, #_molecule, #_devops
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:20
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Molecule — это фреймворк, предназначенный для тестирования ролей в Ansible. На хабре довольно много статей про тестирование с помощью molecule и почти во всех статьях говорится о неких "сложных сценариях тестирования для ansible", и далее в примерах обычно идут какие-то простенькие роли и тесты. Мне стало интересно протестировать более сложную роль, например роль для создания RabbitMQ кластера.Используемые версии программ на момент написания статьи. Не гарантируется корректная работа для molecule версии ниже 3.3debian 10 Busteransible-3.4.0molecule-3.3.0docker-ce-20.10.6yamllint-1.26.1ansible-lint-5.0.8Устанавливаем ansible и molecule.pip3 install --user ansible (как именно устанавливать не столь важно, в приведенном примере установка идет в хоумдир пользователя). pip3 install --user molecule[docker] (мы будем использовать драйвер докера)Устанавливаем линтерыpip3 install --user ansible-lint yamllintУстановка докера выходит за рамки этой статьи, стоит отметить только что докер вы можете установить на эту же машину, где будете запускать molecule или же установить докер на любую другую машину в сети (например если мощности локальной машины не хватает) или же использовать уже существующий докер сервер.Во втором случае на локальную машину нужно установить только докер клиент и выставить переменную DOCKER_HOST="ssh://ansible@адрес_вашего_докер_сервера", где ansible - аккаунт, который имеет ssh доступ на сервер и под которым будут создаваться докер контейнеры. Аккаунт также должен состоять в группе docker на докер сервере.Описание ансибл роли тоже выходит за рамки статьи, можно взять любую похожую роль, где есть логика создания кластера.Переходим в нашу условную роль cd roles/role_rabbitmq
---
exclude_paths: - .cache/ - .git/ - molecule/ skip_list: - command-instead-of-module - git-latest - no-handler - package-latest - empty-string-compare - command-instead-of-shell - meta-no-info - no-changed-when - no-relative-paths - risky-shell-pipe - role-name - unnamed-task ---
extends: default ignore: | templates/ sites/ files/ old/ README.md LICENSE rules: braces: min-spaces-inside: 0 max-spaces-inside: 1 brackets: min-spaces-inside: 0 max-spaces-inside: 1 comments: require-starting-space: false level: error indentation: spaces: 2 indent-sequences: consistent line-length: disable truthy: disable mkdir molecule/cluster
FROM registry.company.net/debian/buster:latest
ENV DEBIAN_FRONTEND noninteractive ENV pip_packages "ansible" ENV http_proxy "http://10.10.0.1:8888" ENV https_proxy "http://10.0.0.1:8888" ENV no_proxy "127.0.0.1,localhost,*.company.net,10.0.0.0/8,192.168.0.0/16,172.0.0.0/8" # Install dependencies. RUN apt update \ && apt-get install -y --no-install-recommends \ sudo systemd systemd-sysv \ build-essential wget libffi-dev libssl-dev \ python3-apt python3-cryptography python3-pip python3-dev python3-setuptools python3-wheel \ procps passwd curl lsof netcat gnupg ca-certificates openssh-client less vim iputils-ping iproute2 \ debian-archive-keyring dnsutils \ && rm -rf /var/lib/apt/lists/* \ && rm -Rf /usr/share/doc && rm -Rf /usr/share/man \ && apt-get clean # Create ansible user RUN groupadd --system ansible \ && useradd --system --comment "Ansible remote management" --home-dir /home/ansible --create-home --gid ansible --shell /bin/bash --password "*" an sible && echo "%ansible ALL = (ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible # Add company repo RUN curl -k "https://certs.company.net/ca.pem" > /usr/local/share/ca-certificates/ca.crt && update-ca-certificates \ && curl -k "https://company.net/repos/keys/company_repo_key.gpg" | apt-key add \ && echo "deb https://company.net/repos/buster buster-local main > /etc/apt/sources.list.d/company.list && apt-get update && pip3 install $pip_packages # Install Ansible inventory file. RUN mkdir -p /etc/ansible && echo "[local]\nlocalhost ansible_connection=local" > /etc/ansible/hosts # Exclude /usr/share/doc # Если программа использует файлы из /usr/share/doc, то следует добавить диру в игнор для dpkg, иначе файлы будут удалены RUN sed -i 's/path-exclude \/usr\/share\/doc/#path-exclude \/usr\/share\/doc/' /etc/dpkg/dpkg.cfg.d/docker # Make sure systemd doesn't start agettys on tty[1-6]. RUN rm -f /lib/systemd/system/multi-user.target.wants/getty.target VOLUME ["/sys/fs/cgroup"] CMD ["/lib/systemd/systemd"] ---
- name: prepare hosts: all gather_facts: no # не используем сбор фактов для ускорения выполнения tasks: - name: update apt cache block: - name: update apt cache apt: update_cache: yes - name: perform upgrade of all packages to the latest version apt: upgrade: dist force_apt_get: yes - name: install python pika pip: name: - pika executable: pip3 ---
- name: Converge hosts: rabbitmq_cluster roles: - role: role_rabbitmq inventory:
links: group_vars: ../../../../files/molecule/group_vars/ groups:
- rabbitmq_cluster ---
rabbitmq_cluster: yes certs_dir: /etc/rabbitmq/ssl rabbitmq_ssl: yes rabbitmq_ssl_certs: - "_.company.net" rabbitmq_cookie: NJWHJPAOPYKSGTRGDLTN # обратите внимание, здесь мы указываем короткие имена нод, заданные в нашем molecule.yml # все ноды из списка должны узнавать друг друга по этим коротким именам rabbitmq_nodes: - node01 - node02 - node03 rabbitmq_master: rabbit@node01 rabbitmq_master_node: node01 rabbitmq_vhosts: - name: /test rabbitmq_users: - user: test password: test vhost: /test rabbitmq_exchanges: - name: test type: direct durable: yes vhost: /test rabbitmq_queues: - name: test durable: yes vhost: /test rabbitmq_bindings: - name: test destination: test destination_type: queue vhost: /test rabbitmq_policies: - name: ha-replica vhost: /test tags: ha-mode: exactly ha-params: 2 ha-sync-mode: automatic ---
dependency: name: galaxy options: ignore-certs: True driver: name: docker platforms: - name: node01 image: registry.company.net/debian/buster:latest # pre_build_image: true privileged: True tmpfs: - /run - /tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro capabilities: - SYS_ADMIN command: "/lib/systemd/systemd" dns_servers: - 10.0.0.1 groups: - rabbitmq_cluster docker_networks: - name: cluster ipam_config: - subnet: "192.168.0.0/24" gateway: "192.168.0.254" networks: - name: cluster ipv4_address: "192.168.0.1" network_mode: default - name: node02 image: registry.company.net/debian/buster:latest privileged: True tmpfs: - /run - /tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro capabilities: - SYS_ADMIN command: "/lib/systemd/systemd" dns_servers: - 10.0.0.1 groups: - rabbitmq_cluster networks: - name: cluster ipv4_address: "192.168.0.2" network_mode: default - name: node03 image: registry.company.net/debian/buster:latest privileged: True tmpfs: - /run - /tmp volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro capabilities: - SYS_ADMIN command: "/lib/systemd/systemd" dns_servers: - 10.0.0.1 groups: - rabbitmq_cluster networks: - name: cluster ipv4_address: "192.168.0.3" network_mode: default provisioner: name: ansible config_options: defaults: interpreter_python: auto_silent host_key_checking: False gathering: smart callback_whitelist: profile_tasks, timer, yaml ssh_connection: pipelining: True inventory: links: group_vars: ../../../../files/molecule/group_vars/ ansible_args: - -e molecule_run=True - -e use_proxy=False env: MOLECULE_NO_LOG: 0 ANSIBLE_VERBOSITY: 1 verifier: name: ansible lint: | set -e ansible-lint . scenario: name: cluster test_sequence: - dependency - lint - cleanup - destroy - syntax - create - prepare - converge - idempotence - side_effect - verify - cleanup - destroy ansible_args:
- -e molecule_run=True - -e use_proxy=False env:
MOLECULE_NO_LOG: 0 ANSIBLE_VERBOSITY: 1 lint: |
set -e ansible-lint . scenario:
name: cluster test_sequence: - dependency - lint - cleanup - destroy - syntax - create - prepare - converge - idempotence - side_effect - verify - cleanup - destroy ---
- name: Side Effect serial: 1 hosts: all gather_facts: no # факты нам не нужны tasks: - name: restart rabbitmq service block: - name: stop rabbitmq service systemd: name: rabbitmq-server state: stopped failed_when: no - name: pause pause: seconds: 15 - name: start rabbitmq service systemd: name: rabbitmq-server state: started failed_when: no ---
- name: Verify hosts: all gather_facts: no tasks: - name: cluster status block: - name: get cluster status command: "rabbitmqctl cluster_status --formatter json" register: output - name: set facts set_fact: cluster_output: "{{ output.stdout|from_json }}" - name: print nodes debug: var: cluster_output.disk_nodes - name: verify fail fail: msg: "FAIL: number of nodes is less than 3" when: - cluster_output.disk_nodes | length < 3 run_once: yes - name: check vhosts block: - name: get vhosts command: "rabbitmqctl list_vhosts --formatter json" register: output - name: set facts set_fact: vhost_output: "{{ output.stdout|from_json }}.name" - name: print vhosts debug: var: vhost_output - name: verify fail fail: msg: "FAIL: vhost is missing" when: - "'/test' not in vhost_output" run_once: yes - name: check users block: - name: get users command: "rabbitmqctl list_users --formatter json" register: output - name: set facts set_fact: user_output: "{{ output.stdout|from_json }}.user" - name: print users debug: var: user_output - name: verify fail fail: msg: "FAIL: user is missing" when: - "'test' not in user_output" run_once: yes - name: check queues block: - name: get queues command: "rabbitmqctl -p /test list_queues --formatter json" register: output - name: set facts set_fact: queue_output: "{{ output.stdout|from_json }}.name" - name: print queues debug: var: queue_output - name: verify fail fail: msg: "FAIL: queue is missing" when: - "'test' not in queue_output" run_once: yes - name: check exchanges block: - name: get exchanges command: "rabbitmqctl -p /test list_exchanges --formatter json" register: output - name: set facts set_fact: exchange_output: "{{ output.stdout|from_json }}.name" - name: print exchanges debug: var: exchange_output - name: verify fail fail: msg: "FAIL: exchange is missing" when: - "'test' not in exchange_output" run_once: yes - name: check bindings block: - name: get bindings command: "rabbitmqctl -p /test list_bindings --formatter json" register: output - name: set facts set_fact: binding_output: "{{ output.stdout|from_json }}.source_name" - name: print bindings debug: var: binding_output - name: verify fail fail: msg: "FAIL: binding is missing" when: - "'test' not in binding_output" run_once: yes - name: check policies block: - name: get policies command: "rabbitmqctl -p /test list_policies --formatter json" register: output - name: set facts set_fact: policy_output: "{{ output.stdout|from_json }}.name" - name: print policies debug: var: policy_output - name: verify fail fail: msg: "FAIL: policy is missing" when: - "'ha-replica' not in policy_output" run_once: yes - name: check publish block: - name: install consumer script copy: src: ../../../../files/molecule/scripts/consumer.py dest: /usr/local/bin/consumer.py owner: root mode: 0755 - name: publish a message to a queue rabbitmq_publish: url: "amqp://test:test@localhost:5672/%2Ftest" queue: test body: "Test message" content_type: "text/plain" durable: yes - name: receive a message from the queue command: /usr/local/bin/consumer.py run_once: yes #!/usr/bin/python3
import pika, sys url = 'amqp://test:test@localhost/%2ftest' params = pika.URLParameters(url) params.socket_timeout = 1 connection = pika.BlockingConnection(params) channel = connection.channel() channel.queue_declare(queue='test', durable=True) method_frame, header_frame, body = channel.basic_get(queue = 'test') if method_frame is None: connection.close() sys.exit('Queue is empty!') else: channel.basic_ack(delivery_tag=method_frame.delivery_tag) connection.close() print(body) molecule converge -s cluster
molecule side-effect -s cluster molecule verify -s cluster
molecule test -s cluster >/tmp/log 2>&1
tail -f /tmp/log =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:20
Часовой пояс: UTC + 5