From 696e08aa3559228b7b60aed23286f2b2b7d05fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=90=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BF=D0=BE=D0=B2?= Date: Sat, 25 Oct 2025 11:29:37 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=A0=D0=B5=D0=BE=D1=80=D0=B3=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20Makefile=20=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20Docker=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Реорганизован Makefile: * Переменные вынесены наверх * Справка перенесена в конец * Удалены секции molecule и container * Объединены presets и preset в одну секцию * Переименована секция docker в docker-cmd - Добавлены Docker образы: * ansible-controller - основной контроллер * alt-linux, astra-linux, redos - российские дистрибутивы * rhel, centos, alma, rocky - RHEL-совместимые образы - Обновлены preset'ы: * Добавлены описания #description: во все preset'ы * Переименован docker.yml в docker-test.yml * Добавлены новые preset'ы: etcd-patroni, multi-os - Добавлена документация: * docs/examples.md - примеры использования * docs/universal-testing.md - универсальное тестирование * dockerfiles/README.md - описание Docker образов - Улучшена функциональность: * Единообразный стиль команд make [категория] [действие] * Улучшенный вывод информации о preset'ах * Добавлены пустые цели для совместимости --- Makefile | 440 +++++++++++------- dockerfiles/README.md | 160 +++++++ dockerfiles/alma/Dockerfile | 48 ++ dockerfiles/alt-linux/Dockerfile | 50 ++ dockerfiles/ansible-controller/Dockerfile | 89 ++++ .../ansible-controller/docker-compose.yml | 23 + .../ansible-controller/requirements.yml | 9 + dockerfiles/astra-linux/Dockerfile | 50 ++ dockerfiles/centos/Dockerfile | 48 ++ dockerfiles/redos/Dockerfile | 50 ++ dockerfiles/rhel/Dockerfile | 48 ++ dockerfiles/rocky/Dockerfile | 48 ++ docs/examples.md | 424 +++++++++++++++++ docs/universal-testing.md | 281 +++++++++++ molecule/default/converge.yml | 53 ++- molecule/default/create.yml | 118 +++-- molecule/default/destroy.yml | 23 +- molecule/default/verify.yml | 122 +++++ molecule/presets/default.yml | 2 +- .../presets/{docker.yml => docker-test.yml} | 2 +- molecule/presets/etcd-patroni.yml | 62 +++ molecule/presets/minimal.yml | 2 +- molecule/presets/multi-os.yml | 70 +++ molecule/presets/performance.yml | 63 ++- molecule/presets/security.yml | 62 ++- molecule/presets/standart.yml | 2 +- molecule/presets/test.yml | 2 +- 27 files changed, 2101 insertions(+), 250 deletions(-) create mode 100644 dockerfiles/README.md create mode 100644 dockerfiles/alma/Dockerfile create mode 100644 dockerfiles/alt-linux/Dockerfile create mode 100644 dockerfiles/ansible-controller/Dockerfile create mode 100644 dockerfiles/ansible-controller/docker-compose.yml create mode 100644 dockerfiles/ansible-controller/requirements.yml create mode 100644 dockerfiles/astra-linux/Dockerfile create mode 100644 dockerfiles/centos/Dockerfile create mode 100644 dockerfiles/redos/Dockerfile create mode 100644 dockerfiles/rhel/Dockerfile create mode 100644 dockerfiles/rocky/Dockerfile create mode 100644 docs/examples.md create mode 100644 docs/universal-testing.md create mode 100644 molecule/default/verify.yml rename molecule/presets/{docker.yml => docker-test.yml} (88%) create mode 100644 molecule/presets/etcd-patroni.yml create mode 100644 molecule/presets/multi-os.yml diff --git a/Makefile b/Makefile index 59c2b58..c3dddfe 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,9 @@ SHELL := /bin/bash # ============================================================================= -# ЦВЕТА ДЛЯ ВЫВОДА +# ПЕРЕМЕННЫЕ # ============================================================================= +# Цвета для вывода RED := \033[0;31m GREEN := \033[0;32m YELLOW := \033[0;33m @@ -18,19 +19,25 @@ CYAN := \033[0;36m WHITE := \033[0;37m RESET := \033[0m -# ============================================================================= -# ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ -# ============================================================================= +# Глобальные переменные PROJECT_NAME ?= ansible-template VERSION ?= 0.1.0 AUTHOR ?= "Сергей Антропов" SITE ?= "https://devops.org.ru" -DOCKER_IMAGE ?= quay.io/ansible/creator-ee:latest +DOCKER_IMAGE ?= inecs/ansible-controller:latest DOCKER_DIND_IMAGE ?= docker:27-dind CONTAINER_NAME ?= ansible-controller -.PHONY: role molecule vault git docker help +# Переменные для Docker Hub +DOCKER_REGISTRY ?= inecs +DOCKER_VERSION ?= latest +DOCKER_IMAGES := ansible-controller alt-linux astra-linux redos rhel centos alma rocky +.PHONY: role vault git docker-cmd presets controller help + +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С РОЛЯМИ +# ============================================================================= role: @case "$(word 2, $(MAKECMDGOALS))" in \ lint) \ @@ -62,34 +69,6 @@ role: $(DOCKER_IMAGE) \ bash -c "cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml && ansible-playbook -i localhost, destroy.yml --connection=local" || echo "✅ Тестирование завершено"; \ fi;; \ - presets) \ - echo "📋 Доступные пресеты:"; \ - echo ""; \ - preset_count=0; \ - for preset in molecule/presets/*.yml; do \ - if [ -f "$$preset" ]; then \ - preset_name=$$(basename "$$preset" .yml); \ - preset_desc=$$(grep -E "^#.*пресет|^#.*preset" "$$preset" | head -1 | sed 's/^# *//' || echo "Описание отсутствует"); \ - host_count=$$(grep -c "^- name:" "$$preset" 2>/dev/null || echo "?"); \ - printf " 📄 %s - %s (%s хостов)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \ - preset_count=$$((preset_count + 1)); \ - fi; \ - done; \ - if [ $$preset_count -eq 0 ]; then \ - echo " ⚠️ Пресеты не найдены"; \ - fi; \ - echo ""; \ - echo "💡 Использование:"; \ - echo " make role test - с default preset"; \ - echo " make role test [preset_name] - с любым preset"; \ - echo " make role test minimal - с minimal preset"; \ - echo " make role test standard - со standard preset"; \ - echo " make role test docker - с docker preset"; \ - echo ""; \ - echo "💡 Примеры:"; \ - echo " make role test # default preset"; \ - echo " make role test minimal # minimal preset"; \ - echo " make role test my-custom-preset # любой preset";; \ deploy) \ echo "🚀 Развертывание ролей на реальные серверы..."; \ echo ""; \ @@ -113,177 +92,319 @@ role: fi;; \ *) \ echo "🎯 Доступные команды:"; \ - echo ""; \ - echo " 🔧 make role install - установить зависимости"; \ - echo " 🔍 make role lint - проверить синтаксис ролей"; \ - echo " 🚀 make role test - протестировать роли (default preset)"; \ - echo " 🚀 make role test [preset] - протестировать с любым preset"; \ - echo " 🚀 make role test minimal - протестировать с minimal preset"; \ - echo " 🚀 make role test standard - протестировать со standard preset"; \ - echo " 🚀 make role test docker - протестировать с docker preset"; \ - echo " 📋 make role presets - показать список preset'ов"; \ - echo " 🚀 make role deploy - развернуть роли";; \ + echo " make role test [preset] - протестировать роли"; \ + echo " make role deploy - развернуть роли"; \ + echo " make role lint - проверить синтаксис";; \ esac -#################################################################################################### -# Работа с Molecule Universal -#################################################################################################### -molecule: +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С PRESET'АМИ +# ============================================================================= +presets: @case "$(word 2, $(MAKECMDGOALS))" in \ - create) \ - echo "Создание тестового окружения ..."; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - bash -c "cd molecule/default && molecule create";; \ - converge) \ - echo "Запуск плейбуков ..."; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - bash -c "cd molecule/default && molecule converge";; \ - verify) \ - echo "Проверка результатов ..."; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - bash -c "cd molecule/default && molecule verify";; \ - destroy) \ - echo "Удаление тестового окружения ..."; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - bash -c "cd molecule/default && molecule destroy";; \ + list) \ + echo "📋 Доступные пресеты:"; \ + echo ""; \ + preset_count=0; \ + for preset in molecule/presets/*.yml; do \ + if [ -f "$$preset" ]; then \ + preset_name=$$(basename "$$preset" .yml); \ + preset_desc=$$(grep -E "^#description:" "$$preset" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"); \ + host_count=$$(grep -c "^- name:" "$$preset" 2>/dev/null || echo "?"); \ + printf " 📄 %s - %s (%s хостов)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \ + preset_count=$$((preset_count + 1)); \ + fi; \ + done; \ + if [ $$preset_count -eq 0 ]; then \ + echo " ⚠️ Пресеты не найдены"; \ + fi;; \ + info) \ + if [ -z "$(PRESET)" ]; then \ + echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \ + echo "💡 Пример: make presets info PRESET=etcd-patroni"; \ + exit 1; \ + fi; \ + if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \ + echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + make presets list; \ + exit 1; \ + fi; \ + echo "📋 Информация о пресете: $(PRESET)"; \ + echo ""; \ + echo "📄 Описание:"; \ + grep -E "^#description:" "molecule/presets/$(PRESET).yml" | head -1 | sed 's/^#description: *//' || echo "Описание отсутствует"; \ + echo ""; \ + echo "🏠 Хосты:"; \ + grep -E "^- name:" "molecule/presets/$(PRESET).yml" | sed 's/^- name: / - /' || echo "Хосты не найдены"; \ + echo ""; \ + echo "🌐 Сеть:"; \ + grep -E "^docker_network:" "molecule/presets/$(PRESET).yml" | sed 's/^docker_network: / - /' || echo "Сеть не указана"; \ + echo ""; \ + echo "🐳 Образы:"; \ + grep -E "^- " "molecule/presets/$(PRESET).yml" | grep -E "family:" | sed 's/.*family: / - /' || echo "Образы не найдены";; \ test) \ - echo "Полный цикл тестирования ..."; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - bash -c "cd molecule/default && molecule test";; \ + if [ -z "$(PRESET)" ]; then \ + echo "❌ Ошибка: Укажите PRESET=имя_пресета"; \ + echo "💡 Пример: make presets test PRESET=etcd-patroni"; \ + exit 1; \ + fi; \ + if [ ! -f "molecule/presets/$(PRESET).yml" ]; then \ + echo "❌ Ошибка: Пресет '$(PRESET)' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + make presets list; \ + exit 1; \ + fi; \ + echo "🚀 Тестирование с пресетом: $(PRESET)"; \ + echo ""; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e ANSIBLE_FORCE_COLOR=1 \ + -e MOLECULE_PRESET=$(PRESET) \ + $(DOCKER_IMAGE) \ + bash -c "cd molecule/default && molecule test" || echo "✅ Тестирование завершено";; \ *) \ - echo "Доступные команды:"; \ - echo " make molecule create - создать окружение"; \ - echo " make molecule converge - запустить плейбуки"; \ - echo " make molecule verify - проверить результаты"; \ - echo " make molecule destroy - удалить окружение"; \ - echo " make molecule test - полный цикл тестирования"; \ - ;; \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 📋 make presets list - показать список preset'ов"; \ + echo " 📄 make presets info - информация о preset'е"; \ + echo " 🚀 make presets test - тест с preset'ом"; \ + echo ""; \ + echo "💡 Примеры:"; \ + echo " make presets list"; \ + echo " make presets info PRESET=etcd-patroni"; \ + echo " make presets test PRESET=etcd-patroni";; \ esac -#################################################################################################### -# Работа с Ansible Vault -#################################################################################################### +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С VAULT +# ============================================================================= vault: @case "$(word 2, $(MAKECMDGOALS))" in \ - show) \ - echo "Доступные файлы секретов:"; \ - ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ - echo ""; \ - read -p "Введите имя файла (без .yml): " FILE; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ - quay.io/ansible/creator-ee:latest \ - ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \ create) \ - echo "Создание файла секретов:"; \ + echo "🔐 Создание файла секретов..."; \ read -p "Введите имя файла (без .yml): " FILE; \ docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ ansible-vault create --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ edit) \ - echo "Доступные файлы секретов:"; \ + echo "🔐 Редактирование секретов..."; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \ + show) \ + echo "🔐 Просмотр секретов..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \ delete) \ - echo "Доступные файлы секретов:"; \ + echo "🔐 Удаление секретов..."; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ rm -f vault/$$FILE.yml;; \ - rekey) \ - echo "Доступные файлы секретов:"; \ - ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + encrypt) \ + echo "🔐 Шифрование файла..."; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет файлов для шифрования"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ - docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ - ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \ + ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ decrypt) \ - echo "Доступные файлы секретов:"; \ + echo "🔐 Расшифровка файла..."; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ ansible-vault decrypt --vault-password-file vault/.vault vault/$$FILE.yml;; \ - encrypt) \ - echo "Доступные файлы секретов:"; \ + rekey) \ + echo "🔐 Смена пароля..."; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ - docker run --rm -v "$(PWD):/workspace" -w /workspace \ + docker run --rm -it -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ - ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ + ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \ + check) \ + echo "🔍 Проверка vault файлов..."; \ + if [ ! -d "vault" ]; then \ + echo "❌ Директория vault не найдена"; \ + exit 1; \ + fi; \ + vault_files=$$(find vault -name "*.yml" -type f 2>/dev/null); \ + if [ -z "$$vault_files" ]; then \ + echo "⚠️ Vault файлы не найдены"; \ + exit 0; \ + fi; \ + echo "📋 Найденные vault файлы:"; \ + for file in $$vault_files; do \ + echo " 📄 $$file"; \ + done; \ + echo ""; \ + echo "🔍 Проверка структуры..."; \ + for file in $$vault_files; do \ + if grep -q "ANSIBLE_VAULT" "$$file"; then \ + echo " ✅ $$file - зашифрован"; \ + else \ + echo " ⚠️ $$file - не зашифрован"; \ + fi; \ + done;; \ + scan) \ + echo "🔍 Поиск секретов в проекте..."; \ + echo "📋 Поиск потенциальных секретов:"; \ + find . -name "*.yml" -o -name "*.yaml" | grep -v ".git" | while read file; do \ + if grep -qE "(password|secret|key|token|api_key)" "$$file" 2>/dev/null; then \ + echo " ⚠️ $$file - содержит потенциальные секреты"; \ + fi; \ + done; \ + echo ""; \ + echo "💡 Рекомендации:"; \ + echo " - Используйте ansible-vault для шифрования секретов"; \ + echo " - Не храните секреты в открытом виде"; \ + echo " - Регулярно проверяйте файлы на наличие секретов";; \ *) \ - echo "Доступные команды:"; \ + echo "🎯 Доступные команды:"; \ echo " make vault create - создать файл секретов"; \ echo " make vault edit - редактировать секреты"; \ echo " make vault show - показать секреты"; \ echo " make vault delete - удалить секреты"; \ echo " make vault encrypt - зашифровать файл"; \ echo " make vault decrypt - расшифровать файл"; \ - echo " make vault rekey - сменить пароль";; \ + echo " make vault rekey - сменить пароль"; \ + echo " make vault check - проверка vault файлов"; \ + echo " make vault scan - поиск секретов";; \ esac -#################################################################################################### -# Работа с Git -#################################################################################################### +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С GIT +# ============================================================================= git: @case "$(word 2, $(MAKECMDGOALS))" in \ push) \ - git branch; \ - read -p "Выберите ветку для пуша: " BRANCH; \ - read -p "Введите описание коммита: " COMMIT; \ - commitname=$$COMMIT; \ - git add . ; \ - git commit -m "$$commitname"; \ - git push -u origin $$BRANCH; \ - echo "Изменения внесены в Git";; \ + echo "📤 Отправка изменений в репозиторий..."; \ + git add .; \ + git commit -m "Обновление проекта"; \ + git push origin main;; \ pull) \ - git pull;; \ + echo "📥 Получение изменений из репозитория..."; \ + git pull origin main;; \ new) \ - read -p "Введите имя новой ветки: " BRANCH_NAME; \ - NEW_BRANCH="$$BRANCH_NAME"; \ - git checkout -b $$NEW_BRANCH; \ - echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ + echo "🌿 Создание новой ветки..."; \ + read -p "Введите имя ветки: " BRANCH; \ + git checkout -b "$$BRANCH"; \ + echo "✅ Ветка '$$BRANCH' создана";; \ *) \ - echo "Доступные команды:"; \ + echo "🎯 Доступные команды:"; \ echo " make git push - запушить изменения"; \ echo " make git pull - получить изменения"; \ echo " make git new - создать новую ветку";; \ esac -#################################################################################################### -# Работа с Docker (упрощенная) -#################################################################################################### -docker: +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С DOCKER +# ============================================================================= +docker-cmd: @case "$(word 2, $(MAKECMDGOALS))" in \ + prepare) \ + echo "🔧 Подготовка Docker образов для Docker Hub..."; \ + echo "📋 Registry: $(DOCKER_REGISTRY)"; \ + echo "📋 Version: $(DOCKER_VERSION)"; \ + echo "📋 Images: $(DOCKER_IMAGES)"; \ + echo ""; \ + echo "💡 Для работы с Docker Hub выполните:"; \ + echo " docker login - авторизация в Docker Hub"; \ + echo " make docker build - сборка образов"; \ + echo " make docker push - отправка в Docker Hub";; \ + build) \ + echo "🐳 Сборка Docker образов..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "🔨 Сборка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + cd dockerfiles/$$image && docker build -t $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION) .; \ + done; \ + echo "✅ Образы собраны";; \ + push) \ + echo "📤 Отправка Docker образов в Docker Hub..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "📤 Отправка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + docker push $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION); \ + done; \ + echo "✅ Образы отправлены в Docker Hub";; \ + pull) \ + echo "📥 Загрузка Docker образов из Docker Hub..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "📥 Загрузка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + docker pull $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION) || echo "⚠️ Образ $$image не найден в Docker Hub"; \ + done; \ + echo "✅ Загрузка завершена";; \ clean) \ - echo "🧹 Очистка Docker ресурсов..."; \ - docker system prune -f; \ - docker volume prune -f; \ - echo "✅ Docker ресурсы очищены";; \ + echo "🧹 Очистка Docker образов..."; \ + for image in $(DOCKER_IMAGES); do \ + echo "🗑️ Удаление $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + docker rmi $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION) 2>/dev/null || true; \ + done; \ + echo "✅ Образы очищены";; \ + info) \ + echo "📊 Информация об образах..."; \ + for image in $(DOCKER_IMAGES); do \ + if docker images | grep -q "$(DOCKER_REGISTRY)/$$image"; then \ + echo "📦 $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ + docker images | grep "$(DOCKER_REGISTRY)/$$image" | head -1; \ + fi; \ + done;; \ + update) \ + echo "🔄 Обновление всех образов..."; \ + $(MAKE) docker pull; \ + $(MAKE) docker build; \ + $(MAKE) docker push; \ + echo "✅ Все образы обновлены";; \ *) \ - echo "🐳 Docker команды:"; \ + echo "🎯 Доступные команды:"; \ echo ""; \ - echo "make docker clean - очистить Docker ресурсы"; \ - echo ""; \ - echo "💡 Основное тестирование через preset систему:"; \ - echo " make role test [preset] - универсальное тестирование"; \ - echo " make role presets - показать доступные preset'ы";; \ + echo " 🔧 make docker prepare - подготовка к работе с Docker Hub"; \ + echo " 🐳 make docker build - собрать все образы"; \ + echo " 📤 make docker push - отправить образы в Docker Hub"; \ + echo " 📥 make docker pull - загрузить образы из Docker Hub"; \ + echo " 🧹 make docker clean - удалить образы"; \ + echo " 📊 make docker info - информация об образах"; \ + echo " 🔄 make docker update - обновить все образы (pull + build + push)";; \ esac -#################################################################################################### -# Справка -#################################################################################################### +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С ANSIBLE-CONTROLLER +# ============================================================================= +controller: + @case "$(word 2, $(MAKECMDGOALS))" in \ + build) \ + echo "🔨 Сборка ansible-controller..."; \ + cd dockerfiles/ansible-controller && docker build -t $(DOCKER_REGISTRY)/ansible-controller:$(DOCKER_VERSION) .; \ + echo "✅ ansible-controller собран";; \ + run) \ + echo "🚀 Запуск ansible-controller..."; \ + cd dockerfiles/ansible-controller && docker-compose up -d; \ + echo "✅ ansible-controller запущен";; \ + stop) \ + echo "🛑 Остановка ansible-controller..."; \ + cd dockerfiles/ansible-controller && docker-compose down; \ + echo "✅ ansible-controller остановлен";; \ + *) \ + echo "🎯 Доступные команды:"; \ + echo ""; \ + echo " 🔨 make controller build - собрать ansible-controller"; \ + echo " 🚀 make controller run - запустить ansible-controller"; \ + echo " 🛑 make controller stop - остановить ansible-controller";; \ + esac + +# ============================================================================= +# СПРАВКА +# ============================================================================= help: @echo "==========================================" @echo "AnsibleTemplate - Универсальная система" @@ -297,38 +418,27 @@ help: @echo " roles/ - Ansible роли" @echo " vault/ - Зашифрованные секреты" @echo "" - @echo "🚀 Основные команды:" + @echo "🚀 ОСНОВНЫЕ КОМАНДЫ:" + @echo " make role test [preset] - протестировать роли" + @echo " make role deploy - развернуть роли" + @echo " make role lint - проверить синтаксис" @echo "" - @echo "🧪 ТЕСТИРОВАНИЕ (Docker контейнеры):" - @echo " make role test - протестировать роли (default preset)" - @echo " make role test [preset] - протестировать с любым preset" - @echo " make role test minimal - тест с minimal preset" - @echo " make role test standard - тест со standard preset" - @echo " make role test docker - тест с docker preset" + @echo "📋 PRESET'Ы:" + @echo " make presets list - показать все preset'ы" + @echo " make presets test - тест с preset'ом" @echo "" - @echo "🚀 РАЗВЕРТЫВАНИЕ (Реальные серверы):" - @echo " make role deploy - развернуть роли на серверы" + @echo "🐳 DOCKER:" + @echo " make docker-cmd build - собрать образы" + @echo " make docker-cmd push - отправить в Docker Hub" + @echo " make docker-cmd info - информация об образах" @echo "" - @echo "🔧 ВСПОМОГАТЕЛЬНЫЕ:" - @echo " make role install - установить зависимости" - @echo " make role lint - проверить синтаксис ролей" - @echo " make docker clean - очистить Docker ресурсы" + @echo "🔐 VAULT:" @echo " make vault create - создать файл секретов" - @echo " make git new - создать новую ветку" + @echo " make vault check - проверка vault файлов" @echo "" - @echo "📖 Для подробной справки:" - @echo " make role - команды для ролей" - @echo " make molecule - команды Molecule" - @echo " make docker - команды Docker" - @echo " make vault - команды Vault" - @echo " make git - команды Git" + @echo "📖 Подробная справка: make [команда]" @echo "==========================================" # Пустые цели для совместимости -view create edit show delete lint deploy new advanced presets: - @true - -# Динамические цели для всех возможных preset'ов -# Это позволяет использовать make role test [любой_preset] без ошибок -%: +view create edit show delete lint deploy new advanced list info test build push pull clean prepare update run stop: @true diff --git a/dockerfiles/README.md b/dockerfiles/README.md new file mode 100644 index 0000000..42a6ed2 --- /dev/null +++ b/dockerfiles/README.md @@ -0,0 +1,160 @@ +# Docker образы для универсальной системы тестирования + +## Обзор + +Эта директория содержит Docker образы для различных операционных систем и компонентов, используемых в универсальной системе тестирования Ansible ролей. + +## Структура + +``` +dockerfiles/ +├── ansible-controller/ # Ansible контроллер с предустановленными коллекциями +├── alt-linux/ # ALT Linux с systemd +├── astra-linux/ # Astra Linux с systemd +├── redos/ # RED OS с systemd +├── Makefile # Команды для сборки образов +└── README.md # Документация +``` + +## Доступные образы + +### ansible-controller +- **Базовый образ:** `quay.io/ansible/creator-ee:latest` +- **Описание:** Ansible контроллер с предустановленными коллекциями +- **Компоненты:** + - Ansible с коллекциями (community.docker, community.general, ansible.posix) + - Docker CLI + - kubectl + - Helm + - Kind + - Istio CLI + - Дополнительные роли (geerlingguy.docker, geerlingguy.kubernetes) + +### alt-linux +- **Базовый образ:** `altlinux/p9` +- **Описание:** ALT Linux с systemd +- **Компоненты:** + - systemd + - Docker + - Docker Compose + - Python3 + - Пользователь ansible + +### astra-linux +- **Базовый образ:** `astralinux/astra-1.7` +- **Описание:** Astra Linux с systemd +- **Компоненты:** + - systemd + - Docker + - Docker Compose + - Python3 + - Пользователь ansible + +### redos +- **Базовый образ:** `redos/redos:9` +- **Описание:** RED OS с systemd +- **Компоненты:** + - systemd + - Docker + - Docker Compose + - Python3 + - Пользователь ansible + +## Использование + +### Сборка всех образов +```bash +make docker-build +``` + +### Сборка конкретного образа +```bash +make docker-build IMAGE=ansible-controller +``` + +### Отправка образов в registry +```bash +make docker-push +``` + +### Очистка образов +```bash +make docker-clean +``` + +### Информация об образах +```bash +make docker-info +``` + +## Настройка registry + +По умолчанию образы собираются с тегом `localhost:5000/имя:latest`. Для изменения registry: + +```bash +make docker-build REGISTRY=my-registry.com +make docker-push REGISTRY=my-registry.com +``` + +## Использование в preset'ах + +После сборки образов их можно использовать в preset'ах: + +```yaml +# molecule/presets/my-preset.yml +images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + alt: "localhost:5000/alt-linux:latest" + astra: "localhost:5000/astra-linux:latest" + redos: "localhost:5000/redos:latest" + +hosts: + - name: alt-server + family: alt + groups: [servers] + - name: astra-server + family: astra + groups: [servers] + - name: redos-server + family: redos + groups: [servers] +``` + +## Лучшие практики + +### 1. Версионирование образов +```bash +make docker-build VERSION=v1.0.0 +``` + +### 2. Использование registry +```bash +make docker-push REGISTRY=my-registry.com VERSION=v1.0.0 +``` + +### 3. Очистка старых образов +```bash +make docker-clean +``` + +## Troubleshooting + +### Проблемы с сборкой +1. Проверьте доступность базовых образов +2. Убедитесь, что Docker запущен +3. Проверьте права доступа к Docker + +### Проблемы с registry +1. Убедитесь, что registry доступен +2. Проверьте аутентификацию +3. Проверьте права на push + +### Проблемы с образами +1. Проверьте размер образов +2. Убедитесь, что все зависимости установлены +3. Проверьте совместимость с базовыми образами + +## Заключение + +Эти Docker образы предоставляют готовую среду для тестирования Ansible ролей на различных операционных системах. Используйте их в своих preset'ах для создания универсальной системы тестирования. diff --git a/dockerfiles/alma/Dockerfile b/dockerfiles/alma/Dockerfile new file mode 100644 index 0000000..14000bb --- /dev/null +++ b/dockerfiles/alma/Dockerfile @@ -0,0 +1,48 @@ +# AlmaLinux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM almalinux:8 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + jq \ + python3 \ + python3-pip \ + && dnf clean all + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/alt-linux/Dockerfile b/dockerfiles/alt-linux/Dockerfile new file mode 100644 index 0000000..e04c792 --- /dev/null +++ b/dockerfiles/alt-linux/Dockerfile @@ -0,0 +1,50 @@ +# ALT Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM altlinux/p9 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + htop \ + tree \ + jq \ + python3 \ + python3-pip \ + && apt-get clean + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/ansible-controller/Dockerfile b/dockerfiles/ansible-controller/Dockerfile new file mode 100644 index 0000000..cc35de7 --- /dev/null +++ b/dockerfiles/ansible-controller/Dockerfile @@ -0,0 +1,89 @@ +# Ansible Controller с предустановленными коллекциями +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM ubuntu:22.04 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y && apt-get clean + +# Устанавливаем Python и Ansible +RUN apt-get install -y \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + build-essential \ + && apt-get clean + +# Устанавливаем Ansible +RUN pip3 install ansible ansible-core + +# Устанавливаем дополнительные пакеты +RUN apt-get install -y \ + curl \ + wget \ + git \ + vim \ + nano \ + htop \ + tree \ + jq \ + && apt-get clean + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker CLI +RUN apt-get install -y docker.io docker-compose + +# Устанавливаем kubectl +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \ + && chmod +x kubectl \ + && mv kubectl /usr/local/bin/ + +# Устанавливаем Helm +RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +# Устанавливаем Kind +RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64 \ + && chmod +x ./kind \ + && mv ./kind /usr/local/bin/ + +# Устанавливаем Istio CLI +RUN curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.1 sh - \ + && mv istio-1.22.1/bin/istioctl /usr/local/bin/ \ + && rm -rf istio-1.22.1 + +# Копируем requirements.yml +COPY requirements.yml /tmp/requirements.yml + +# Устанавливаем Ansible коллекции +RUN ansible-galaxy collection install -r /tmp/requirements.yml + +# Создаем пользователя ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Создаем рабочую директорию +WORKDIR /ansible + +# Устанавливаем права +RUN chown -R ansible:ansible /ansible + +# Переключаемся на пользователя ansible +USER ansible + +# Устанавливаем дополнительные роли +RUN ansible-galaxy install geerlingguy.docker \ + && ansible-galaxy install geerlingguy.kubernetes + +# Настройки для работы с Docker +ENV DOCKER_HOST=unix:///var/run/docker.sock +ENV ANSIBLE_FORCE_COLOR=1 +ENV ANSIBLE_STDOUT_CALLBACK=yaml +ENV ANSIBLE_CALLBACKS_ENABLED=profile_tasks + +# Команда по умолчанию +CMD ["sleep", "infinity"] diff --git a/dockerfiles/ansible-controller/docker-compose.yml b/dockerfiles/ansible-controller/docker-compose.yml new file mode 100644 index 0000000..9b6c09f --- /dev/null +++ b/dockerfiles/ansible-controller/docker-compose.yml @@ -0,0 +1,23 @@ +version: "3.9" + +services: + ansible-controller: + build: + context: . + dockerfile: Dockerfile + container_name: ansible-controller + privileged: true + command: sleep infinity + environment: + DOCKER_HOST: unix:///var/run/docker.sock + ANSIBLE_VAULT_PASSWORD_FILE: /ansible/vault-password.txt + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - .:/ansible + working_dir: /ansible + networks: + - labnet + +networks: + labnet: + external: true diff --git a/dockerfiles/ansible-controller/requirements.yml b/dockerfiles/ansible-controller/requirements.yml new file mode 100644 index 0000000..3760d1a --- /dev/null +++ b/dockerfiles/ansible-controller/requirements.yml @@ -0,0 +1,9 @@ +--- +# Ansible Collections для Molecule Universal +collections: + - name: community.docker + version: ">=3.0.0" + - name: community.general + version: ">=7.0.0" + - name: ansible.posix + version: ">=1.5.4" diff --git a/dockerfiles/astra-linux/Dockerfile b/dockerfiles/astra-linux/Dockerfile new file mode 100644 index 0000000..8a44def --- /dev/null +++ b/dockerfiles/astra-linux/Dockerfile @@ -0,0 +1,50 @@ +# Astra Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM astralinux/astra-1.7 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN apt-get install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + htop \ + tree \ + jq \ + python3 \ + python3-pip \ + && apt-get clean + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/centos/Dockerfile b/dockerfiles/centos/Dockerfile new file mode 100644 index 0000000..dac6097 --- /dev/null +++ b/dockerfiles/centos/Dockerfile @@ -0,0 +1,48 @@ +# CentOS с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM quay.io/centos/centos:stream8 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + jq \ + python3 \ + python3-pip \ + && dnf clean all + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/redos/Dockerfile b/dockerfiles/redos/Dockerfile new file mode 100644 index 0000000..99cfd09 --- /dev/null +++ b/dockerfiles/redos/Dockerfile @@ -0,0 +1,50 @@ +# RED OS с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM redos/redos:9 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + htop \ + tree \ + jq \ + python3 \ + python3-pip \ + && dnf clean all + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/rhel/Dockerfile b/dockerfiles/rhel/Dockerfile new file mode 100644 index 0000000..22cbbc5 --- /dev/null +++ b/dockerfiles/rhel/Dockerfile @@ -0,0 +1,48 @@ +# RHEL с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM registry.access.redhat.com/ubi8/ubi + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + jq \ + python3 \ + python3-pip \ + && dnf clean all + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/dockerfiles/rocky/Dockerfile b/dockerfiles/rocky/Dockerfile new file mode 100644 index 0000000..f5b8641 --- /dev/null +++ b/dockerfiles/rocky/Dockerfile @@ -0,0 +1,48 @@ +# Rocky Linux с systemd +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +FROM rockylinux:8 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + git \ + vim \ + nano \ + jq \ + python3 \ + python3-pip \ + && dnf clean all + +# Устанавливаем yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 \ + && chmod +x /usr/local/bin/yq + +# Устанавливаем Docker +RUN curl -fsSL https://get.docker.com | sh + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Переключаемся на пользователя ansible +USER ansible +WORKDIR /home/ansible + +# Команда по умолчанию +CMD ["/sbin/init"] diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..623f425 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,424 @@ +# Примеры использования универсальной системы тестирования + +## Пример 1: Тестирование кластера etcd + PostgreSQL + Patroni + +### Описание +Этот пример демонстрирует тестирование высокодоступного кластера PostgreSQL с Patroni и etcd. + +### Preset: etcd-patroni + +```yaml +# molecule/presets/etcd-patroni.yml +hosts: + # ETCD кластер (5 узлов для высокой доступности) + - name: etcd1 + family: debian + groups: [etcd, cluster] + - name: etcd2 + family: rhel + groups: [etcd, cluster] + - name: etcd3 + family: debian + groups: [etcd, cluster] + - name: etcd4 + family: rhel + groups: [etcd, cluster] + - name: etcd5 + family: debian + groups: [etcd, cluster] + + # Patroni кластер (3 узла PostgreSQL) + - name: patroni1 + family: rhel + groups: [patroni, database, cluster] + - name: patroni2 + family: debian + groups: [patroni, database, cluster] + - name: patroni3 + family: rhel + groups: [patroni, database, cluster] + + # HAProxy для балансировки + - name: haproxy + family: debian + groups: [haproxy, loadbalancer] + publish: ["5000:5000", "5001:5001"] # RW и RO порты + + # DinD узел для тестирования Docker Compose внутри + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] +``` + +### Запуск тестирования + +```bash +# Информация о preset'е +make preset-info PRESET=etcd-patroni + +# Тестирование с preset'ом +make preset-test PRESET=etcd-patroni + +# Или через role test +make role test etcd-patroni +``` + +### Проверка результатов + +```bash +# Проверить статус контейнеров +make container-info + +# Проверить vault файлы +make vault-check +``` + +## Пример 2: Нагрузочное тестирование + +### Описание +Этот пример демонстрирует тестирование под нагрузкой с множественными серверами и кэшем. + +### Preset: performance + +```yaml +# molecule/presets/performance.yml +hosts: + # Основные серверы (5 узлов) + - name: server1 + family: debian + groups: [servers, web, app] + - name: server2 + family: rhel + groups: [servers, web, app] + - name: server3 + family: debian + groups: [servers, web, app] + - name: server4 + family: rhel + groups: [servers, web, app] + - name: server5 + family: debian + groups: [servers, web, app] + + # База данных (3 узла) + - name: db1 + family: rhel + groups: [database, db] + - name: db2 + family: debian + groups: [database, db] + - name: db3 + family: rhel + groups: [database, db] + + # Кэш (3 узла Redis) + - name: cache1 + family: debian + groups: [cache, redis] + - name: cache2 + family: rhel + groups: [cache, redis] + - name: cache3 + family: debian + groups: [cache, redis] + + # Load balancer + - name: lb1 + family: rhel + groups: [loadbalancer, haproxy] + publish: ["80:80", "443:443"] + + # DinD узел для тестирования Docker Compose + - name: compose-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080", "8081:8081"] +``` + +### Запуск тестирования + +```bash +# Тестирование с performance preset'ом +make role test performance + +# Проверка статуса +make container-info +``` + +## Пример 3: Тестирование безопасности + +### Описание +Этот пример демонстрирует тестирование в безопасной среде с bastion хостами и изоляцией. + +### Preset: security + +```yaml +# molecule/presets/security.yml +hosts: + # Bastion хосты (точки входа) + - name: bastion1 + family: rhel + groups: [bastion, security, jump] + publish: ["2222:22"] + - name: bastion2 + family: debian + groups: [bastion, security, jump] + publish: ["2223:22"] + + # Внутренние серверы (без внешнего доступа) + - name: internal1 + family: rhel + groups: [internal, servers, app] + - name: internal2 + family: debian + groups: [internal, servers, app] + - name: internal3 + family: rhel + groups: [internal, servers, app] + + # База данных (изолированная сеть) + - name: db-secure1 + family: rhel + groups: [database, secure, internal] + - name: db-secure2 + family: debian + groups: [database, secure, internal] + + # Мониторинг и логирование + - name: monitor1 + family: debian + groups: [monitoring, security, logs] + - name: monitor2 + family: rhel + groups: [monitoring, security, logs] + + # Firewall и сетевые компоненты + - name: fw1 + family: rhel + groups: [firewall, network, security] + - name: fw2 + family: debian + groups: [firewall, network, security] + + # DOoD узел для тестирования Docker безопасности + - name: docker-secure + type: dood + family: debian + groups: [docker, security, apps] + publish: ["8080:8080"] + env: + DOCKER_HOST: "unix:///var/run/docker.sock" +``` + +### Запуск тестирования + +```bash +# Тестирование с security preset'ом +make role test security + +# Проверка безопасности +make vault-check +make vault-scan +``` + +## Пример 4: Тестирование на разных ОС + +### Описание +Этот пример демонстрирует тестирование на различных операционных системах. + +### Preset: multi-os + +```yaml +# molecule/presets/multi-os.yml +hosts: + # Debian/Ubuntu серверы + - name: ubuntu1 + family: ubuntu + groups: [ubuntu, servers, web] + - name: debian1 + family: debian + groups: [debian, servers, web] + - name: ubuntu2 + family: ubuntu + groups: [ubuntu, servers, app] + - name: debian2 + family: debian + groups: [debian, servers, app] + + # RHEL/CentOS серверы + - name: rhel1 + family: rhel + groups: [rhel, servers, web] + - name: centos1 + family: centos + groups: [centos, servers, web] + - name: rhel2 + family: rhel + groups: [rhel, servers, app] + - name: centos2 + family: centos + groups: [centos, servers, app] + + # База данных на разных ОС + - name: db-ubuntu + family: ubuntu + groups: [database, ubuntu, db] + - name: db-rhel + family: rhel + groups: [database, rhel, db] + + # Load balancer + - name: lb-mixed + family: debian + groups: [loadbalancer, haproxy] + publish: ["80:80", "443:443"] + + # DinD узел для тестирования Docker + - name: docker-mixed + type: dind + groups: [docker, apps] + publish: ["8080:8080"] +``` + +### Запуск тестирования + +```bash +# Тестирование с multi-os preset'ом +make role test multi-os + +# Проверка типов контейнеров +make container-types +``` + +## Пример 5: Создание собственного preset'а + +### Описание +Этот пример демонстрирует создание собственного preset'а для специфических нужд. + +### Создание preset'а + +```bash +# Создать новый preset +cat > molecule/presets/my-custom.yml << 'EOF' +--- +# Пресет для тестирования веб-приложения +# Автор: Ваше имя +# Сайт: https://your-site.com + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Описание кластера +hosts: + # Веб-серверы + - name: web1 + family: debian + groups: [web, servers] + publish: ["80:80", "443:443"] + - name: web2 + family: rhel + groups: [web, servers] + publish: ["8080:80", "8443:443"] + + # База данных + - name: db1 + family: rhel + groups: [database, db] + - name: db2 + family: debian + groups: [database, db] + + # Кэш + - name: cache1 + family: debian + groups: [cache, redis] + + # DinD узел для тестирования + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] +EOF +``` + +### Использование preset'а + +```bash +# Информация о preset'е +make preset-info PRESET=my-custom + +# Тестирование с preset'ом +make preset-test PRESET=my-custom + +# Или через role test +make role test my-custom +``` + +## Пример 6: Работа с Ansible Vault + +### Создание vault файла + +```bash +# Создать файл секретов +make vault create + +# Ввести имя файла: secrets +# Ввести содержимое: +# --- +# database_password: "super_secret_password" +# api_key: "your_api_key_here" +# ssl_cert: "your_ssl_certificate" +``` + +### Использование в ролях + +```yaml +# roles/my-role/tasks/main.yml +- name: Configure database + template: + src: database.conf.j2 + dest: /etc/database.conf + vars: + db_password: "{{ database_password }}" + api_key: "{{ api_key }}" +``` + +### Проверка безопасности + +```bash +# Проверить vault файлы +make vault-check + +# Найти потенциальные секреты +make vault-scan +``` + +## Заключение + +Эти примеры демонстрируют различные способы использования универсальной системы тестирования Ansible ролей. Вы можете: + +1. Использовать готовые preset'ы для быстрого тестирования +2. Создавать собственные preset'ы для специфических нужд +3. Комбинировать различные типы контейнеров +4. Использовать Ansible Vault для безопасности +5. Тестировать на различных операционных системах + +Для получения дополнительной информации используйте: +- `make help` - общая справка +- `make preset-list` - список preset'ов +- `make container-types` - типы контейнеров +- `make vault` - команды Vault diff --git a/docs/universal-testing.md b/docs/universal-testing.md new file mode 100644 index 0000000..ac0feb7 --- /dev/null +++ b/docs/universal-testing.md @@ -0,0 +1,281 @@ +# Универсальная система тестирования Ansible ролей + +## Обзор + +Эта система предоставляет универсальную среду для тестирования и деплоя Ansible ролей с поддержкой различных типов контейнеров, автоматической генерации инвентаря и интеграции с Ansible Vault. + +## Основные возможности + +### 🐳 Типы контейнеров + +#### Systemd контейнеры (по умолчанию) +- Полная поддержка systemd сервисов +- Работа как виртуальные машины +- Подходит для тестирования ролей + +#### DinD (Docker-in-Docker) +- Изолированный Docker daemon +- Подходит для тестирования Docker Compose +- Полная изоляция от хостового Docker + +#### DOoD (Docker-out-of-Docker) +- Доступ к хостовому Docker daemon +- Быстрое тестирование +- Подходит для CI/CD + +### 📋 Preset'ы + +#### etcd-patroni +- Кластер etcd (5 узлов) +- Кластер PostgreSQL с Patroni (3 узла) +- HAProxy для балансировки +- DinD узел для тестирования + +#### performance +- 5 серверов приложений +- 3 узла базы данных +- 3 узла кэша Redis +- Load balancer +- DinD узел для тестирования + +#### security +- Bastion хосты +- Внутренние серверы +- Изолированная база данных +- Мониторинг и логирование +- Firewall компоненты +- DOoD узел для тестирования + +#### multi-os +- Тестирование на разных ОС +- Ubuntu, Debian, RHEL, CentOS +- Смешанные конфигурации +- DinD узел для тестирования + +### 🔐 Ansible Vault интеграция + +- Автоматическая расшифровка перед тестированием +- Безопасное хранение секретов +- Автоматическая повторная шифровка после тестирования +- Поддержка множественных vault'ов + +## Использование + +### Базовые команды + +```bash +# Показать все preset'ы +make preset-list + +# Информация о preset'е +make preset-info PRESET=etcd-patroni + +# Тестирование с preset'ом +make preset-test PRESET=etcd-patroni + +# Типы контейнеров +make container-types + +# Информация о контейнерах +make container-info + +# Проверка vault файлов +make vault-check + +# Поиск секретов +make vault-scan +``` + +### Тестирование ролей + +```bash +# С default preset +make role test + +# С конкретным preset'ом +make role test etcd-patroni +make role test performance +make role test security +make role test multi-os +``` + +### Работа с Ansible Vault + +```bash +# Создать файл секретов +make vault create + +# Редактировать секреты +make vault edit + +# Показать секреты +make vault show + +# Зашифровать файл +make vault encrypt + +# Расшифровать файл +make vault decrypt +``` + +## Структура проекта + +``` +. +├── molecule/ +│ ├── default/ +│ │ ├── create.yml # Создание контейнеров +│ │ ├── destroy.yml # Удаление контейнеров +│ │ ├── converge.yml # Запуск плейбуков +│ │ └── verify.yml # Проверка результатов +│ └── presets/ +│ ├── etcd-patroni.yml +│ ├── performance.yml +│ ├── security.yml +│ └── multi-os.yml +├── files/ +│ ├── requirements.yml +│ └── playbooks/ +│ └── site.yml +├── vault/ +│ └── secrets.yml +└── Makefile +``` + +## Создание собственных preset'ов + +### Пример preset'а + +```yaml +--- +# Пресет для тестирования кластера etcd + PostgreSQL + Patroni +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Описание кластера +hosts: + # Systemd узлы + - name: server1 + family: debian + groups: [servers, web] + publish: ["80:80"] + + # DinD узел + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] + + # DOoD узел + - name: docker-secure + type: dood + family: debian + groups: [docker, security] + publish: ["8081:8081"] + env: + DOCKER_HOST: "unix:///var/run/docker.sock" +``` + +### Параметры хостов + +- `name` - имя хоста +- `family` - семейство ОС (debian, rhel, ubuntu, centos) +- `type` - тип контейнера (dind, dood) +- `groups` - группы для инвентаря +- `publish` - порты для публикации +- `env` - переменные окружения +- `volumes` - дополнительные тома +- `capabilities` - дополнительные возможности + +## Лучшие практики + +### 1. Использование групп + +```yaml +hosts: + - name: web1 + groups: [web, servers, production] + - name: db1 + groups: [database, servers, production] +``` + +### 2. Безопасность + +```yaml +# Используйте Ansible Vault для секретов +vault_targets: + - /ansible/vault/secrets.yml + - /ansible/files/playbooks/group_vars/*/vault.yml + - /ansible/files/playbooks/host_vars/*/vault.yml +``` + +### 3. Тестирование + +```yaml +# Проверяйте различные сценарии +- name: Test web servers + hosts: web + tasks: + - name: Check nginx status + systemd: + name: nginx + state: started +``` + +## Troubleshooting + +### Проблемы с контейнерами + +```bash +# Проверить статус контейнеров +make container-info + +# Очистить Docker ресурсы +make docker clean +``` + +### Проблемы с Vault + +```bash +# Проверить vault файлы +make vault-check + +# Найти потенциальные секреты +make vault-scan +``` + +### Проблемы с preset'ами + +```bash +# Показать все preset'ы +make preset-list + +# Информация о preset'е +make preset-info PRESET=имя_пресета +``` + +## Заключение + +Универсальная система тестирования Ansible ролей предоставляет мощные инструменты для тестирования ролей в различных сценариях. Используйте preset'ы для быстрого создания тестовых сред, различные типы контейнеров для изоляции и Ansible Vault для безопасности. + +Для получения дополнительной информации используйте: +- `make help` - общая справка +- `make role` - команды для ролей +- `make molecule` - команды Molecule +- `make vault` - команды Vault diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index a8fc941..3f7baee 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -2,51 +2,74 @@ - hosts: localhost gather_facts: false vars: + # Получаем preset из переменной окружения или используем default + preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" + preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" + # перечисли файлы/глобы, которые нужно временно расшифровать vault_targets: - /ansible/vault/secrets.yml - # добавляй сюда свои пути (host_vars/*/vault.yml, group_vars/*/vault.yml, и т.п.) + - /ansible/files/playbooks/group_vars/*/vault.yml + - /ansible/files/playbooks/host_vars/*/vault.yml + - /ansible/roles/**/vars/vault.yml tasks: + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true + - name: Install collections community.docker.docker_container_exec: container: ansible-controller command: bash -lc "ansible-galaxy collection install -r /ansible/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true" - - name: Decrypt vault targets (best-effort) + - name: Preflight vault — normalize state (encrypt if plaintext, then decrypt) community.docker.docker_container_exec: container: ansible-controller command: > bash -lc ' - set -euo pipefail; + set -euo pipefail; shopt -s nullglob globstar; for p in {{ vault_targets | map('quote') | join(' ') }}; do - if [ -e "$p" ]; then - echo "[vault] decrypt $p"; - ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$p" || true; - fi + for f in $p; do + [ -f "$f" ] || continue; + if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then + echo "[vault] already encrypted: $f"; + else + echo "[vault] plaintext -> encrypt: $f"; + ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$f"; + fi + echo "[vault] decrypt for run: $f"; + ansible-vault decrypt --vault-password-file /ansible/vault-password.txt "$f"; + done done ' - - name: Run external playbook (your lab play) + - name: Run lab playbook community.docker.docker_container_exec: container: ansible-controller command: > bash -lc " ANSIBLE_ROLES_PATH=/ansible/roles - ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/molecule/default/site.yml + ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /ansible/files/playbooks/site.yml " - - name: Re-encrypt vault targets (always) + - name: Post-run — re-encrypt secrets community.docker.docker_container_exec: container: ansible-controller command: > bash -lc ' - set -euo pipefail; + set -euo pipefail; shopt -s nullglob globstar; for p in {{ vault_targets | map('quote') | join(' ') }}; do - if [ -e "$p" ]; then - echo "[vault] encrypt $p"; - ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$p" || true; - fi + for f in $p; do + [ -f "$f" ] || continue; + if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then + echo "[vault] ok (encrypted): $f"; + else + echo "[vault] encrypt back: $f"; + ansible-vault encrypt --encrypt-vault-id default --vault-password-file /ansible/vault-password.txt "$f" || true; + fi + done done ' ignore_errors: true \ No newline at end of file diff --git a/molecule/default/create.yml b/molecule/default/create.yml index 5a268df..12ef899 100644 --- a/molecule/default/create.yml +++ b/molecule/default/create.yml @@ -11,6 +11,9 @@ generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" images: debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + ubuntu: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + centos: "quay.io/centos/centos:stream9-systemd" systemd_defaults: privileged: true command: "/sbin/init" @@ -24,72 +27,99 @@ groups: [test] tasks: + - name: Install required collections + command: ansible-galaxy collection install -r /workspace/requirements.yml + delegate_to: localhost + ignore_errors: true + register: collections_install + changed_when: false + run_once: true + become: true + vars: + ansible_python_interpreter: /usr/bin/python3 + environment: + ANSIBLE_COLLECTIONS_PATH: /usr/share/ansible/collections + - name: Load preset configuration include_vars: "{{ preset_file }}" when: preset_file is file ignore_errors: true - name: Ensure network exists - command: docker network create {{ docker_network }} - delegate_to: localhost - ignore_errors: true + community.docker.docker_network: + name: "{{ docker_network }}" + state: present # SYSTEMD nodes - name: Pull systemd images - command: docker pull {{ images[item.family] }} - delegate_to: localhost + community.docker.docker_image: + name: "{{ images[item.family] }}" + source: pull loop: "{{ hosts | selectattr('type','undefined') | list }}" loop_control: { label: "{{ item.name }}" } + when: item.family is defined and images[item.family] is defined - name: Start systemd nodes - command: > - docker run -d --name {{ item.name }} - --network {{ docker_network }} - --privileged={{ systemd_defaults.privileged | lower }} - --tmpfs {{ (systemd_defaults.tmpfs | default([])) | join(' --tmpfs ') }} - --cap-add {{ (systemd_defaults.capabilities | default([])) | join(' --cap-add ') }} - {% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %} - {% for key, value in item.env | default({}) | dictsort %}--env {{ key }}={{ value }} {% endfor %} - {% for volume in (systemd_defaults.volumes | default([])) + (item.volumes | default([])) %}--volume {{ volume }} {% endfor %} - {{ images[item.family] }} {{ systemd_defaults.command }} - delegate_to: localhost + community.docker.docker_container: + name: "{{ item.name }}" + image: "{{ images[item.family] }}" + networks: + - name: "{{ docker_network }}" + privileged: "{{ systemd_defaults.privileged }}" + command: "{{ systemd_defaults.command }}" + volumes: "{{ systemd_defaults.volumes | default([]) + (item.volumes | default([])) }}" + tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}" + capabilities: "{{ systemd_defaults.capabilities | default([]) }}" + published_ports: "{{ item.publish | default([]) }}" + environment: "{{ item.env | default({}) }}" + state: started + restart_policy: unless-stopped loop: "{{ hosts | selectattr('type','undefined') | list }}" loop_control: { label: "{{ item.name }}" } + when: item.family is defined and images[item.family] is defined # DinD nodes - name: Start DinD nodes (docker:27-dind) - command: > - docker run -d --name {{ item.name }} - --network {{ docker_network }} - --privileged=true - --env DOCKER_TLS_CERTDIR="" - {% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %} - --volume {{ item.name }}-docker:/var/lib/docker - docker:27-dind - delegate_to: localhost + community.docker.docker_container: + name: "{{ item.name }}" + image: "docker:27-dind" + networks: + - name: "{{ docker_network }}" + privileged: true + environment: + DOCKER_TLS_CERTDIR: "" + published_ports: "{{ item.publish | default([]) }}" + volumes: "{{ (item.volumes | default([])) + [item.name + '-docker:/var/lib/docker'] }}" + state: started + restart_policy: unless-stopped loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}" loop_control: { label: "{{ item.name }}" } # DOoD nodes (mount docker.sock) - name: Start DOoD nodes (systemd + docker.sock mount) - command: > - docker run -d --name {{ item.name }} - --network {{ docker_network }} - --privileged={{ systemd_defaults.privileged | lower }} - --tmpfs {{ (systemd_defaults.tmpfs | default([])) | join(' --tmpfs ') }} - --cap-add {{ (systemd_defaults.capabilities | default([])) | join(' --cap-add ') }} - {% for port in item.publish | default([]) %}--publish {{ port }} {% endfor %} - {% for key, value in item.env | default({}) | dictsort %}--env {{ key }}={{ value }} {% endfor %} - {% for volume in (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) %}--volume {{ volume }} {% endfor %} - {{ images[item.family] }} {{ systemd_defaults.command }} - delegate_to: localhost + community.docker.docker_container: + name: "{{ item.name }}" + image: "{{ images[item.family] }}" + networks: + - name: "{{ docker_network }}" + privileged: "{{ systemd_defaults.privileged }}" + command: "{{ systemd_defaults.command }}" + volumes: "{{ (systemd_defaults.volumes | default([])) + ['/var/run/docker.sock:/var/run/docker.sock'] + (item.volumes | default([])) }}" + tmpfs: "{{ systemd_defaults.tmpfs | default([]) }}" + capabilities: "{{ systemd_defaults.capabilities | default([]) }}" + published_ports: "{{ item.publish | default([]) }}" + environment: "{{ item.env | default({}) }}" + state: started + restart_policy: unless-stopped loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}" loop_control: { label: "{{ item.name }}" } + when: item.family is defined and images[item.family] is defined # Build groups map - - name: Build groups map + - name: Initialize groups map set_fact: - groups_map: "{{ groups_map | default({}) }}" + groups_map: {} + - name: Append hosts to groups set_fact: groups_map: "{{ groups_map | combine({ item_group: (groups_map[item_group] | default([])) + [item_name] }) }}" @@ -122,4 +152,14 @@ copy: dest: "{{ generated_inventory }}" content: "{{ inv_content }}" - mode: "0644" \ No newline at end of file + mode: "0644" + + - name: Display inventory summary + debug: + msg: | + 📋 Inventory Summary: + - Total hosts: {{ hosts | length }} + - Groups: {{ groups_map.keys() | list | join(', ') }} + - Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }} + - DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} + - DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }} \ No newline at end of file diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index 959cd0c..d73dcf8 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -4,7 +4,7 @@ vars: # Получаем preset из переменной окружения или используем default preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" - preset_file: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') | default('/tmp') }}/../presets/{{ preset_name }}.yml" + preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" # Fallback значения если preset файл не найден docker_network: labnet @@ -19,7 +19,7 @@ when: preset_file is file ignore_errors: true - - name: Remove containers + - name: Stop and remove containers community.docker.docker_container: name: "{{ item.name }}" state: absent @@ -36,8 +36,25 @@ loop_control: { label: "{{ item.name }}" } ignore_errors: true + - name: Remove custom volumes + community.docker.docker_volume: + name: "{{ item.volumes | default([]) | select('match', '^[^:]+$') | list }}" + state: absent + loop: "{{ hosts }}" + loop_control: { label: "{{ item.name }}" } + ignore_errors: true + when: item.volumes is defined + - name: Remove network community.docker.docker_network: name: "{{ docker_network }}" state: absent - ignore_errors: true \ No newline at end of file + ignore_errors: true + + - name: Display cleanup summary + debug: + msg: | + 🧹 Cleanup Summary: + - Removed containers: {{ hosts | length }} + - Removed DinD volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} + - Network: {{ docker_network }} \ No newline at end of file diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml new file mode 100644 index 0000000..a3f237e --- /dev/null +++ b/molecule/default/verify.yml @@ -0,0 +1,122 @@ +--- +- hosts: localhost + gather_facts: false + vars: + # Получаем preset из переменной окружения или используем default + preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" + preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" + + # Fallback значения если preset файл не найден + docker_network: labnet + hosts: + - name: u1 + family: debian + groups: [test] + + tasks: + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true + + # Проверка systemd узлов + - name: Check systemd nodes status + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: systemctl is-system-running + loop: "{{ hosts | selectattr('type','undefined') | list }}" + loop_control: { label: "{{ item.name }}" } + register: systemd_status + ignore_errors: true + + - name: Display systemd nodes status + debug: + msg: "Systemd node {{ item.0.name }}: {{ item.1.stdout | default('unknown') }}" + loop: "{{ systemd_status.results | default([]) }}" + when: systemd_status is defined + + # Проверка DinD узлов + - name: Check DinD nodes docker daemon + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: docker version --format '{{.Server.Version}}' + loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}" + loop_control: { label: "{{ item.name }}" } + register: dind_status + ignore_errors: true + + - name: Display DinD nodes status + debug: + msg: "DinD node {{ item.0.name }}: Docker {{ item.1.stdout | default('not running') }}" + loop: "{{ dind_status.results | default([]) }}" + when: dind_status is defined + + # Проверка DOoD узлов + - name: Check DOoD nodes docker access + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: docker ps --format '{{.Names}}' + loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}" + loop_control: { label: "{{ item.name }}" } + register: dood_status + ignore_errors: true + + - name: Display DOoD nodes status + debug: + msg: "DOoD node {{ item.0.name }}: Can access {{ item.1.stdout_lines | length | default(0) }} containers" + loop: "{{ dood_status.results | default([]) }}" + when: dood_status is defined + + # Проверка сетевого подключения + - name: Test network connectivity between nodes + community.docker.docker_container_exec: + container: "{{ item.0.name }}" + command: ping -c 1 {{ item.1.name }} + loop: "{{ hosts | subelements(hosts, 'name') }}" + loop_control: { label: "{{ item.0.name }} -> {{ item.1.name }}" } + when: item.0.name != item.1.name + register: ping_results + ignore_errors: true + + - name: Display network connectivity results + debug: + msg: "Network test {{ item.0.name }} -> {{ item.1.name }}: {{ 'OK' if item.2.rc == 0 else 'FAILED' }}" + loop: "{{ ping_results.results | default([]) }}" + when: ping_results is defined + + # Проверка портов + - name: Check published ports + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: netstat -tlnp + loop: "{{ hosts | selectattr('publish','defined') | list }}" + loop_control: { label: "{{ item.name }}" } + register: port_status + ignore_errors: true + + - name: Display port status + debug: + msg: "Node {{ item.0.name }} ports: {{ item.1.stdout_lines | select('match', 'LISTEN') | list | length }} listening" + loop: "{{ port_status.results | default([]) }}" + when: port_status is defined + + # Проверка групп + - name: Display inventory groups + debug: + msg: | + 📋 Inventory Groups: + {% for group, members in (groups_map | default({}) | dictsort) %} + - {{ group }}: {{ members | join(', ') }} + {% endfor %} + + # Финальная сводка + - name: Display verification summary + debug: + msg: | + ✅ Verification Summary: + - Total hosts: {{ hosts | length }} + - Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }} + - DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} + - DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }} + - Groups: {{ groups_map.keys() | list | join(', ') }} + - Network: {{ docker_network }} diff --git a/molecule/presets/default.yml b/molecule/presets/default.yml index 2cf2455..6f0c66b 100644 --- a/molecule/presets/default.yml +++ b/molecule/presets/default.yml @@ -1,5 +1,5 @@ --- -# Стандартный пресет по умолчанию для тестирования +#description: Стандартный пресет по умолчанию для тестирования с 2 хостами (Debian + RHEL) # Автор: Сергей Антропов # Сайт: https://devops.org.ru diff --git a/molecule/presets/docker.yml b/molecule/presets/docker-test.yml similarity index 88% rename from molecule/presets/docker.yml rename to molecule/presets/docker-test.yml index 500383e..75418ff 100644 --- a/molecule/presets/docker.yml +++ b/molecule/presets/docker-test.yml @@ -1,5 +1,5 @@ --- -# Пресет с Docker контейнерами +#description: Пресет с Docker контейнерами (DinD + DOoD) для тестирования Docker-задач # Автор: Сергей Антропов # Сайт: https://devops.org.ru diff --git a/molecule/presets/etcd-patroni.yml b/molecule/presets/etcd-patroni.yml new file mode 100644 index 0000000..a1201b1 --- /dev/null +++ b/molecule/presets/etcd-patroni.yml @@ -0,0 +1,62 @@ +--- +#description: Пресет для тестирования кластера etcd + PostgreSQL + Patroni (9 хостов) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Описание кластера etcd + Patroni + HAProxy +hosts: + # ETCD кластер (5 узлов для высокой доступности) + - name: etcd1 + family: debian + groups: [etcd, cluster] + - name: etcd2 + family: rhel + groups: [etcd, cluster] + - name: etcd3 + family: debian + groups: [etcd, cluster] + - name: etcd4 + family: rhel + groups: [etcd, cluster] + - name: etcd5 + family: debian + groups: [etcd, cluster] + + # Patroni кластер (3 узла PostgreSQL) + - name: patroni1 + family: rhel + groups: [patroni, database, cluster] + - name: patroni2 + family: debian + groups: [patroni, database, cluster] + - name: patroni3 + family: rhel + groups: [patroni, database, cluster] + + # HAProxy для балансировки + - name: haproxy + family: debian + groups: [haproxy, loadbalancer] + publish: ["5000:5000", "5001:5001"] # RW и RO порты + + # DinD узел для тестирования Docker Compose внутри + - name: app-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080"] diff --git a/molecule/presets/minimal.yml b/molecule/presets/minimal.yml index c096043..1f46c9b 100644 --- a/molecule/presets/minimal.yml +++ b/molecule/presets/minimal.yml @@ -1,5 +1,5 @@ --- -# Минимальный пресет для быстрого тестирования +#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian) # Автор: Сергей Антропов # Сайт: https://devops.org.ru diff --git a/molecule/presets/multi-os.yml b/molecule/presets/multi-os.yml new file mode 100644 index 0000000..25fd601 --- /dev/null +++ b/molecule/presets/multi-os.yml @@ -0,0 +1,70 @@ +--- +#description: Пресет для тестирования на разных ОС с 12 хостами (Debian + RHEL) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы для разных ОС +images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + rhel: "quay.io/centos/centos:stream9-systemd" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Описание кластера с разными ОС +hosts: + # Debian серверы + - name: debian1 + family: debian + groups: [debian, servers, web] + - name: debian2 + family: debian + groups: [debian, servers, web] + - name: debian3 + family: debian + groups: [debian, servers, app] + - name: debian4 + family: debian + groups: [debian, servers, app] + + # RHEL серверы + - name: rhel1 + family: rhel + groups: [rhel, servers, web] + - name: rhel2 + family: rhel + groups: [rhel, servers, web] + - name: rhel3 + family: rhel + groups: [rhel, servers, app] + - name: rhel4 + family: rhel + groups: [rhel, servers, app] + + # База данных на разных ОС + - name: db-debian + family: debian + groups: [database, debian, db] + - name: db-rhel + family: rhel + groups: [database, rhel, db] + + # Load balancer + - name: lb-mixed + family: debian + groups: [loadbalancer, haproxy] + publish: ["80:80", "443:443"] + + # DinD узел для тестирования Docker + - name: docker-mixed + type: dind + groups: [docker, apps] + publish: ["8080:8080"] diff --git a/molecule/presets/performance.yml b/molecule/presets/performance.yml index 3216737..6515879 100644 --- a/molecule/presets/performance.yml +++ b/molecule/presets/performance.yml @@ -1,5 +1,5 @@ --- -# Пресет для тестирования производительности +#description: Пресет для нагрузочного тестирования с 12 хостами (серверы + БД + кэш) # Автор: Сергей Антропов # Сайт: https://devops.org.ru @@ -19,20 +19,55 @@ systemd_defaults: tmpfs: ["/run", "/run/lock"] capabilities: ["SYS_ADMIN"] +# Описание кластера для нагрузочного тестирования hosts: - # Нагрузочное тестирование - 5 хостов - - name: perf1 + # Основные серверы (5 узлов) + - name: server1 family: debian - groups: [test, performance] - - name: perf2 - family: debian - groups: [test, performance] - - name: perf3 + groups: [servers, web, app] + - name: server2 family: rhel - groups: [test, performance] - - name: perf4 - family: rhel - groups: [test, performance] - - name: perf5 + groups: [servers, web, app] + - name: server3 family: debian - groups: [test, performance] + groups: [servers, web, app] + - name: server4 + family: rhel + groups: [servers, web, app] + - name: server5 + family: debian + groups: [servers, web, app] + + # База данных (3 узла) + - name: db1 + family: rhel + groups: [database, db] + - name: db2 + family: debian + groups: [database, db] + - name: db3 + family: rhel + groups: [database, db] + + # Кэш (3 узла Redis) + - name: cache1 + family: debian + groups: [cache, redis] + - name: cache2 + family: rhel + groups: [cache, redis] + - name: cache3 + family: debian + groups: [cache, redis] + + # Load balancer + - name: lb1 + family: rhel + groups: [loadbalancer, haproxy] + publish: ["80:80", "443:443"] + + # DinD узел для тестирования Docker Compose + - name: compose-dind + type: dind + groups: [apps, docker] + publish: ["8080:8080", "8081:8081"] \ No newline at end of file diff --git a/molecule/presets/security.yml b/molecule/presets/security.yml index 3ecf1e8..15f562d 100644 --- a/molecule/presets/security.yml +++ b/molecule/presets/security.yml @@ -1,5 +1,5 @@ --- -# Пресет для тестирования безопасности +#description: Пресет для тестирования безопасности с 10 хостами (bastion + internal + monitoring) # Автор: Сергей Антропов # Сайт: https://devops.org.ru @@ -19,14 +19,58 @@ systemd_defaults: tmpfs: ["/run", "/run/lock"] capabilities: ["SYS_ADMIN"] +# Описание кластера для тестирования безопасности hosts: - # Тестирование безопасности - 3 хоста с разными ОС - - name: sec1 - family: debian - groups: [test, security, web] - - name: sec2 + # Bastion хосты (точки входа) + - name: bastion1 family: rhel - groups: [test, security, db] - - name: sec3 + groups: [bastion, security, jump] + publish: ["2222:22"] + - name: bastion2 family: debian - groups: [test, security, api] + groups: [bastion, security, jump] + publish: ["2223:22"] + + # Внутренние серверы (без внешнего доступа) + - name: internal1 + family: rhel + groups: [internal, servers, app] + - name: internal2 + family: debian + groups: [internal, servers, app] + - name: internal3 + family: rhel + groups: [internal, servers, app] + + # База данных (изолированная сеть) + - name: db-secure1 + family: rhel + groups: [database, secure, internal] + - name: db-secure2 + family: debian + groups: [database, secure, internal] + + # Мониторинг и логирование + - name: monitor1 + family: debian + groups: [monitoring, security, logs] + - name: monitor2 + family: rhel + groups: [monitoring, security, logs] + + # Firewall и сетевые компоненты + - name: fw1 + family: rhel + groups: [firewall, network, security] + - name: fw2 + family: debian + groups: [firewall, network, security] + + # DOoD узел для тестирования Docker безопасности + - name: docker-secure + type: dood + family: debian + groups: [docker, security, apps] + publish: ["8080:8080"] + env: + DOCKER_HOST: "unix:///var/run/docker.sock" \ No newline at end of file diff --git a/molecule/presets/standart.yml b/molecule/presets/standart.yml index aff8ee6..f96dd4f 100644 --- a/molecule/presets/standart.yml +++ b/molecule/presets/standart.yml @@ -1,5 +1,5 @@ --- -# Стандартный пресет для тестирования +#description: Стандартный пресет для тестирования с 3 хостами (Debian + RHEL) # Автор: Сергей Антропов # Сайт: https://devops.org.ru diff --git a/molecule/presets/test.yml b/molecule/presets/test.yml index c096043..1f46c9b 100644 --- a/molecule/presets/test.yml +++ b/molecule/presets/test.yml @@ -1,5 +1,5 @@ --- -# Минимальный пресет для быстрого тестирования +#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian) # Автор: Сергей Антропов # Сайт: https://devops.org.ru