# Тестирование через Molecule Molecule — стандартный инструмент для тестирования Ansible ролей. Каждая роль запускается в Docker-контейнерах, проходит набор автоматических проверок и удаляется. Реальные серверы не нужны. ## Требования Только **Docker** — Molecule, Python и зависимости уже внутри образа `k3s-ansible`. ```bash make build # собрать образ (один раз) make molecule-k3s # запустить тест ``` Как это работает: `make molecule-*` запускает контейнер `k3s-ansible` с примонтированным Docker socket. Внутри этого контейнера Molecule создаёт тестовые контейнеры — Docker внутри Docker без демона (только socket от хоста). ## Доступные тесты ```bash make molecule-k3s # Роль k3s — 3 ноды: master01, worker01, rpi01 (~8-12 мин) make molecule-prometheus # Роль prometheus-stack (~2-3 мин) make molecule-istio # Роль istio (~2-3 мин) make molecule-all # Все тесты последовательно (~15-20 мин) make molecule-lint # Линтинг YAML + ansible-lint (~30 сек) ``` ## Жизненный цикл теста ``` dependency → зависимые роли lint → yamllint + ansible-lint syntax → ansible-playbook --syntax-check create → запустить Docker-контейнер prepare → подготовить контейнер (Python, collections) converge → выполнить тестируемые задачи idempotency → повторный converge (проверка изменений = 0) verify → assertions (проверить результаты) destroy → удалить контейнер ``` При ошибке на любой фазе тест падает, контейнер удаляется автоматически. ## Что тестирует каждая роль ### Роль `k3s` (3 контейнера, ~8-12 мин) | Контейнер | Образ | Соответствует | |---|---|---| | `master01` | `geerlingguy/docker-ubuntu2204-ansible` | Ubuntu 22.04 x86_64 | | `worker01` | `geerlingguy/docker-ubuntu2204-ansible` | Ubuntu 22.04 x86_64 | | `rpi01` | `geerlingguy/docker-debian12-ansible` | Debian 12 (Raspberry Pi OS) | Что проверяет `verify.yml`: | Проверка | Нода | Что именно | |---|---|---| | `/etc/kubernetes/k3s` существует | все | Директория создана | | `config.yaml` существует, права `0600` | все | Файл конфига | | `cluster-init: true` | master01 | Первый мастер инициализирует | | `server: https://...:6443` | worker01, rpi01 | Присоединяются к master01 | | `cluster-cidr: 10.42.0.0/16` | все | Правильная подсеть | | `disable: [traefik]` | все | Traefik выключен | | `net.ipv4.ip_forward = 1` | все | sysctl применён | ### Роль `prometheus-stack` (~2-3 мин) Тестирует рендеринг Jinja2-шаблона без privileged режима. | Проверка | Что именно | |---|---| | `grafana.adminUser` | Значение переменной | | `grafana.persistence.enabled` | `true` | | `prometheus.retention` | `7d` | | `alertmanager.enabled` | `true` | | `nodeExporter.enabled` | `true` | ### Роль `istio` (~2-3 мин) Тестирует рендеринг всех четырёх шаблонов роли. | Файл | Проверка | |---|---| | `istiod-values.yaml` | Ресурсы pilot, `meshConfig`, `enablePrometheusMerge: true` | | `kiali-values.yaml` | `auth.strategy: token`, Prometheus URL | | `peer-authentication.yaml` | `kind: PeerAuthentication`, `spec.mtls.mode: STRICT` | | `kiali-token-secret.yaml` | `type: kubernetes.io/service-account-token` | ## Запуск тестов пошагово ### Линтинг (~30 сек) ```bash make molecule-lint ``` Запускает `yamllint .` и `ansible-lint` на всём проекте. Используй перед каждым коммитом. ### Тест одной роли ```bash make molecule-k3s ``` Ожидаемый вывод (успешный): ``` INFO Running default > create TASK [Create instance(s)] **** changed: [localhost] => (item=master01) changed: [localhost] => (item=worker01) changed: [localhost] => (item=rpi01) INFO Running default > converge TASK [Test server config template rendering] *** changed: [master01] INFO Running default > idempotency PLAY RECAP master01 : ok=12 changed=0 unreachable=0 failed=0 worker01 : ok=12 changed=0 unreachable=0 failed=0 rpi01 : ok=12 changed=0 unreachable=0 failed=0 INFO Idempotency completed successfully. INFO Running default > verify TASK [Assert cluster-init is set (только master01)] *** ok: [master01] => {"msg": "All assertions passed"} INFO Running default > destroy ✓ k3s role: OK ``` ## Отладка упавших тестов ```bash # Войти в runner-контейнер с Docker socket: docker run --rm -it \ -v $(pwd):/ansible \ -v /var/run/docker.sock:/var/run/docker.sock \ --entrypoint bash \ k3s-ansible # Внутри — перейти к нужной роли: cd /ansible/roles/k3s # или roles/prometheus-stack / addons/jenkins/role # Запускать фазы вручную: molecule converge # создать контейнер и запустить задачи molecule login # войти в тестовый контейнер molecule login --host master01 # конкретная нода molecule verify # только assertions molecule converge -- -vvv # подробный вывод molecule destroy # удалить тестовые контейнеры # Отдельные фазы: molecule lint molecule syntax molecule create molecule prepare molecule idempotency ``` ## Написание новых тестов ### molecule.yml ```yaml driver: name: docker platforms: - name: my-test-instance image: geerlingguy/docker-ubuntu2204-ansible:latest pre_build_image: true privileged: true # нужно для sysctl, модулей ядра groups: - k3s_master provisioner: name: ansible verifier: name: ansible ``` ### converge.yml ```yaml - name: Converge hosts: all become: true vars: kube_vip_address: "192.168.1.100" # все нужные переменные здесь k3s_version: "v1.29.3+k3s1" tasks: - name: Render template ansible.builtin.template: src: "{{ playbook_dir }}/../../templates/my-template.j2" dest: /tmp/result.yaml ``` ### verify.yml ```yaml - name: Verify hosts: all tasks: - name: Read result ansible.builtin.slurp: src: /tmp/result.yaml register: raw - name: Parse YAML ansible.builtin.set_fact: result: "{{ raw.content | b64decode | from_yaml }}" - name: Assert key exists ansible.builtin.assert: that: - result.myKey == 'expected-value' - result.enabled == true fail_msg: "Ожидалось 'expected-value', получено: {{ result.myKey }}" ``` ## Типичные ошибки | Ошибка | Причина | Решение | |---|---|---| | `Unable to pull image` | Нет интернета | `docker pull geerlingguy/docker-ubuntu2204-ansible:latest` | | `FAILED: assert ... is defined` | Переменная не задана | Добавь в секцию `vars:` converge.yml | | `Idempotency: CHANGED` | Таск не идемпотентен | Добавь `changed_when: false` или исправь задачу | | `yamllint: wrong indentation` | Ошибка отступа | Исправь файл, `make molecule-lint` | | `ansible-lint: no-changed-when` | shell/command без changed_when | Добавь `changed_when: <условие>` | | `sysctl: Operation not permitted` | Нет privileged | Добавь `privileged: true` в molecule.yml |