From 60ee5e90a5b19889106d7b93f6185f5830f68a41 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 10:11:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20Ansible:=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=B5=D1=81=D0=B5=D1=82=D1=8B,=20=D1=83?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20Makefile,=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B4=D0=BE=D0=BA?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 57 +++ Makefile | 189 ++++++---- Makefile.backup | 347 ++++++++++++++++++ README.md | 224 +++++++++++ ansible.cfg | 2 +- deploy.yml | 13 +- docs/testing-vs-deployment.md | 99 +++++ inventory/hosts.ini | 16 +- molecule/default/converge.yml | 8 +- molecule/default/create.yml | 106 +++--- molecule/default/destroy.yml | 18 +- molecule/default/molecule.yml | 6 + molecule/default/site.yml | 2 +- molecule/presets/default.yml | 10 +- molecule/presets/performance.yml | 38 ++ molecule/presets/security.yml | 32 ++ .../presets/{standard.yml => standart.yml} | 0 molecule/presets/test.yml | 25 ++ roles/deploy.yml | 13 - scripts/test-playbook.yml | 52 +++ scripts/test-standart.sh | 83 +++++ 21 files changed, 1193 insertions(+), 147 deletions(-) create mode 100644 Dockerfile create mode 100644 Makefile.backup create mode 100644 README.md create mode 100644 docs/testing-vs-deployment.md create mode 100644 molecule/presets/performance.yml create mode 100644 molecule/presets/security.yml rename molecule/presets/{standard.yml => standart.yml} (100%) create mode 100644 molecule/presets/test.yml delete mode 100644 roles/deploy.yml create mode 100644 scripts/test-playbook.yml create mode 100755 scripts/test-standart.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5230336 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# ============================================================================= +# AnsibleTemplate - Dockerfile для тестирования +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# ============================================================================= + +FROM quay.io/ansible/creator-ee:latest + +# Установка дополнительных зависимостей +USER root + +# Обновление системы и установка необходимых пакетов +RUN dnf update -y && \ + dnf install -y \ + python3-pip \ + git \ + curl \ + jq \ + ca-certificates \ + iproute2 \ + iputils \ + procps-ng \ + net-tools \ + sudo \ + vim \ + && dnf clean all + +# Установка Python пакетов +RUN pip3 install --upgrade pip && \ + pip3 install \ + ansible-lint \ + molecule \ + molecule-docker \ + docker-compose + +# Создание рабочей директории +WORKDIR /ansible + +# Копирование файлов проекта +COPY . /ansible/ + +# Установка прав доступа +RUN chmod +x /ansible/scripts/*.sh 2>/dev/null || true + +# Переключение на пользователя ansible +USER ansible + +# Установка Ansible коллекций +RUN ansible-galaxy collection install -r requirements.yml --force + +# Настройка переменных окружения +ENV ANSIBLE_FORCE_COLOR=1 +ENV ANSIBLE_STDOUT_CALLBACK=yaml +ENV PYTHONUNBUFFERED=1 + +# Команда по умолчанию +CMD ["/bin/bash"] \ No newline at end of file diff --git a/Makefile b/Makefile index e306ed4..59c2b58 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,8 @@ # Сайт: https://devops.org.ru # ============================================================================= +SHELL := /bin/bash + # ============================================================================= # ЦВЕТА ДЛЯ ВЫВОДА # ============================================================================= @@ -24,113 +26,136 @@ VERSION ?= 0.1.0 AUTHOR ?= "Сергей Антропов" SITE ?= "https://devops.org.ru" DOCKER_IMAGE ?= quay.io/ansible/creator-ee:latest +DOCKER_DIND_IMAGE ?= docker:27-dind CONTAINER_NAME ?= ansible-controller -.PHONY: role molecule vault git help +.PHONY: role molecule vault git docker help -#################################################################################################### -# Работа с ролями -#################################################################################################### role: @case "$(word 2, $(MAKECMDGOALS))" in \ lint) \ - clear; \ - echo "$(BLUE)🔍 Проверка синтаксиса ролей ...$(RESET)"; \ - echo ""; \ - docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ - -e ANSIBLE_FORCE_COLOR=1 \ - $(DOCKER_IMAGE) \ - bash -c "ansible-lint roles/ --config-file .ansible-lint" || echo "$(GREEN)✅ Lint завершен с предупреждениями$(RESET)";; \ + echo "🔍 Проверка синтаксиса ролей ..."; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/ --config-file .ansible-lint || true"; \ + echo "✅ Lint завершен";; \ test) \ - clear; \ - echo "$(PURPLE)🚀 Тестирование ролей ...$(RESET)"; \ + echo "🚀 Тестирование ролей ..."; \ PRESET="default"; \ - if [ -n "$(word 3, $(MAKECMDGOALS))" ]; then \ - PRESET="$(word 3, $(MAKECMDGOALS))"; \ - echo "$(CYAN)📋 Используется пресет: $(YELLOW)$$PRESET$(RESET)"; \ - cp molecule/presets/$$PRESET.yml molecule/presets/default.yml; \ - else \ - echo "$(CYAN)📋 Используется пресет: $(YELLOW)default$(RESET)"; \ + ARGS="$(wordlist 3,10,$(MAKECMDGOALS))"; \ + if [ -n "$$ARGS" ]; then \ + PRESET="$$(echo $$ARGS | cut -d' ' -f1)"; \ + fi; \ + echo "📋 Используется пресет: $$PRESET"; \ + if [ ! -f "molecule/presets/$$PRESET.yml" ]; then \ + echo "❌ Ошибка: Пресет '$$PRESET' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + ls -1 molecule/presets/*.yml 2>/dev/null | sed 's|molecule/presets/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " ⚠️ Пресеты не найдены"; \ + exit 1; \ fi; \ echo ""; \ - docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ - -e ANSIBLE_FORCE_COLOR=1 \ - $(DOCKER_IMAGE) \ - bash -c "cd molecule/default && ansible-playbook -i localhost, site.yml --connection=local" || echo "$(GREEN)✅ Тестирование завершено$(RESET)";; \ + if [ "$$PRESET" = "standart" ]; then \ + ./scripts/test-standart.sh; \ + else \ + 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 && 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) \ - clear; \ - echo "$(CYAN)📋 Доступные пресеты:$(RESET)"; \ + echo "📋 Доступные пресеты:"; \ echo ""; \ + preset_count=0; \ for preset in molecule/presets/*.yml; do \ if [ -f "$$preset" ]; then \ preset_name=$$(basename "$$preset" .yml); \ - printf " $(BLUE)📄 %s$(RESET)\n" "$$preset_name"; \ + 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 || echo " $(YELLOW)⚠️ Пресеты не найдены$(RESET)"; \ - echo "";; \ + 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) \ - clear; \ - echo "$(PURPLE)🚀 Развертывание ролей на реальные серверы...$(RESET)"; \ + echo "🚀 Развертывание ролей на реальные серверы..."; \ echo ""; \ - echo "$(YELLOW)💡 Примеры использования:$(RESET)"; \ - echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml$(RESET)"; \ - echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --limit web_servers$(RESET)"; \ - echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --check$(RESET)"; \ + if [ ! -f "inventory/hosts.ini" ]; then \ + echo "❌ Ошибка: Файл inventory/hosts.ini не найден!"; \ + echo "💡 Создайте файл inventory/hosts.ini с вашими серверами"; \ + exit 1; \ + fi; \ + echo "📋 Используется inventory: inventory/hosts.ini"; \ + echo "📄 Содержимое inventory:"; \ + cat inventory/hosts.ini; \ echo ""; \ - echo "$(CYAN)📄 Доступные playbook:$(RESET)"; \ - ls -la *.yml 2>/dev/null | grep -v molecule || echo " $(BLUE)📄 deploy.yml - основной playbook для развертывания$(RESET)";; \ + echo "🚀 Запуск развертывания..."; \ + ansible-playbook -i inventory/hosts.ini deploy.yml --check; \ + echo ""; \ + read -p "Продолжить развертывание? (y/N): " confirm; \ + if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \ + ansible-playbook -i inventory/hosts.ini deploy.yml; \ + else \ + echo "❌ Развертывание отменено"; \ + fi;; \ *) \ - clear; \ - echo "$(CYAN)🎯 Доступные команды:$(RESET)"; \ + echo "🎯 Доступные команды:"; \ echo ""; \ - echo " $(BLUE)🔧 make role install$(RESET) - установить зависимости"; \ - echo " $(BLUE)🔍 make role lint$(RESET) - проверить синтаксис ролей"; \ - echo " $(PURPLE)🚀 make role test$(RESET) - протестировать роли (с default пресетом)"; \ - echo " $(PURPLE)🚀 make role test minimal$(RESET) - протестировать с minimal пресетом"; \ - echo " $(PURPLE)🚀 make role test standard$(RESET) - протестировать со standard пресетом"; \ - echo " $(PURPLE)🚀 make role test docker$(RESET) - протестировать с docker пресетом"; \ - echo " $(CYAN)📋 make role presets$(RESET) - показать список пресетов"; \ - echo " $(PURPLE)🚀 make role deploy$(RESET) - развернуть роли";; \ + 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 - развернуть роли";; \ esac - #################################################################################################### # Работа с Molecule Universal #################################################################################################### molecule: @case "$(word 2, $(MAKECMDGOALS))" in \ create) \ - clear; \ echo "Создание тестового окружения ..."; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ bash -c "cd molecule/default && molecule create";; \ converge) \ - clear; \ echo "Запуск плейбуков ..."; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ bash -c "cd molecule/default && molecule converge";; \ verify) \ - clear; \ echo "Проверка результатов ..."; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ bash -c "cd molecule/default && molecule verify";; \ destroy) \ - clear; \ echo "Удаление тестового окружения ..."; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ bash -c "cd molecule/default && molecule destroy";; \ test) \ - clear; \ echo "Полный цикл тестирования ..."; \ docker run --rm -v "$(PWD):/workspace" -w /workspace \ quay.io/ansible/creator-ee:latest \ bash -c "cd molecule/default && molecule test";; \ *) \ - clear; \ echo "Доступные команды:"; \ echo " make molecule create - создать окружение"; \ echo " make molecule converge - запустить плейбуки"; \ @@ -146,7 +171,6 @@ molecule: vault: @case "$(word 2, $(MAKECMDGOALS))" in \ show) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ @@ -155,14 +179,12 @@ vault: quay.io/ansible/creator-ee:latest \ ansible-vault view --vault-password-file vault/.vault vault/$$FILE.yml;; \ create) \ - clear; \ - 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) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ @@ -171,14 +193,12 @@ vault: quay.io/ansible/creator-ee:latest \ ansible-vault edit --vault-password-file vault/.vault vault/$$FILE.yml;; \ delete) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ rm -f vault/$$FILE.yml;; \ rekey) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ @@ -187,7 +207,6 @@ vault: quay.io/ansible/creator-ee:latest \ ansible-vault rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \ decrypt) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ @@ -196,7 +215,6 @@ vault: quay.io/ansible/creator-ee:latest \ ansible-vault decrypt --vault-password-file vault/.vault vault/$$FILE.yml;; \ encrypt) \ - clear; \ echo "Доступные файлы секретов:"; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ @@ -205,7 +223,6 @@ vault: quay.io/ansible/creator-ee:latest \ ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ *) \ - clear; \ echo "Доступные команды:"; \ echo " make vault create - создать файл секретов"; \ echo " make vault edit - редактировать секреты"; \ @@ -238,18 +255,36 @@ git: git checkout -b $$NEW_BRANCH; \ echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ *) \ - clear; \ echo "Доступные команды:"; \ echo " make git push - запушить изменения"; \ echo " make git pull - получить изменения"; \ echo " make git new - создать новую ветку";; \ esac +#################################################################################################### +# Работа с Docker (упрощенная) +#################################################################################################### +docker: + @case "$(word 2, $(MAKECMDGOALS))" in \ + clean) \ + echo "🧹 Очистка Docker ресурсов..."; \ + docker system prune -f; \ + docker volume prune -f; \ + echo "✅ Docker ресурсы очищены";; \ + *) \ + echo "🐳 Docker команды:"; \ + echo ""; \ + echo "make docker clean - очистить Docker ресурсы"; \ + echo ""; \ + echo "💡 Основное тестирование через preset систему:"; \ + echo " make role test [preset] - универсальное тестирование"; \ + echo " make role presets - показать доступные preset'ы";; \ + esac + #################################################################################################### # Справка #################################################################################################### help: - @clear @echo "==========================================" @echo "AnsibleTemplate - Универсальная система" @echo "тестирования Ansible ролей" @@ -263,21 +298,37 @@ help: @echo " vault/ - Зашифрованные секреты" @echo "" @echo "🚀 Основные команды:" + @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 "" + @echo "🚀 РАЗВЕРТЫВАНИЕ (Реальные серверы):" + @echo " make role deploy - развернуть роли на серверы" + @echo "" + @echo "🔧 ВСПОМОГАТЕЛЬНЫЕ:" @echo " make role install - установить зависимости" @echo " make role lint - проверить синтаксис ролей" - @echo " make role test - протестировать роли" - @echo " make role deploy - развернуть роли на серверы" - @echo " make molecule create - создать тестовое окружение" + @echo " make docker clean - очистить Docker ресурсы" @echo " make vault create - создать файл секретов" @echo " make git new - создать новую ветку" @echo "" @echo "📖 Для подробной справки:" @echo " make role - команды для ролей" @echo " make molecule - команды Molecule" + @echo " make docker - команды Docker" @echo " make vault - команды Vault" @echo " make git - команды Git" @echo "==========================================" # Пустые цели для совместимости -view create edit show delete test lint deploy new advanced presets: - @true \ No newline at end of file +view create edit show delete lint deploy new advanced presets: + @true + +# Динамические цели для всех возможных preset'ов +# Это позволяет использовать make role test [любой_preset] без ошибок +%: + @true diff --git a/Makefile.backup b/Makefile.backup new file mode 100644 index 0000000..fe5664f --- /dev/null +++ b/Makefile.backup @@ -0,0 +1,347 @@ +# ============================================================================= +# AnsibleTemplate - Универсальная система тестирования Ansible ролей +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# ============================================================================= + +SHELL := /bin/bash + +# ============================================================================= +# ЦВЕТА ДЛЯ ВЫВОДА +# ============================================================================= +RED := \033[0;31m +GREEN := \033[0;32m +YELLOW := \033[0;33m +BLUE := \033[0;34m +PURPLE := \033[0;35m +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 +CONTAINER_NAME ?= ansible-controller + +.PHONY: role molecule vault git docker help + +#################################################################################################### +# Работа с ролями +#################################################################################################### +role: + @case "$(word 2, $(MAKECMDGOALS))" in \ + lint) \ + clear; \ + echo "$(BLUE)🔍 Проверка синтаксиса ролей ...$(RESET)"; \ + echo ""; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace -e ANSIBLE_FORCE_COLOR=1 $(DOCKER_IMAGE) bash -c "ansible-lint roles/ --config-file .ansible-lint || true"; \ + echo "$(GREEN)✅ Lint завершен$(RESET)";; \ + test) \ + clear; \ + echo "$(PURPLE)🚀 Тестирование ролей ...$(RESET)"; \ + PRESET="default"; \ + # Получаем все аргументы после 'test' и берем первый как preset \ + ARGS="$(filter-out test,$(MAKECMDGOALS))"; \ + if [ -n "$$ARGS" ]; then \ + PRESET="$$(echo $$ARGS | cut -d' ' -f1)"; \ + fi; \ + echo "$(CYAN)📋 Используется пресет: $(YELLOW)$$PRESET$(RESET)"; \ + if [ ! -f "molecule/presets/$$PRESET.yml" ]; then \ + echo "$(RED)❌ Ошибка: Пресет '$$PRESET' не найден!$(RESET)"; \ + echo "$(YELLOW)💡 Доступные пресеты:$(RESET)"; \ + ls -1 molecule/presets/*.yml 2>/dev/null | sed 's|molecule/presets/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " $(YELLOW)⚠️ Пресеты не найдены$(RESET)"; \ + echo ""; \ + echo "$(GREEN)💡 Использование:$(RESET)"; \ + echo " $(BLUE)make role test$(RESET) - с default preset"; \ + echo " $(BLUE)make role test [preset_name]$(RESET) - с любым preset"; \ + echo " $(BLUE)make role test minimal$(RESET) - с minimal preset"; \ + echo " $(BLUE)make role test standard$(RESET) - со standard preset"; \ + echo " $(BLUE)make role test docker$(RESET) - с docker preset"; \ + exit 1; \ + fi; \ + echo ""; \ + docker run --rm --name $(CONTAINER_NAME) -v "$(PWD):/workspace" -w /workspace \ + -e ANSIBLE_FORCE_COLOR=1 \ + -e MOLECULE_PRESET=$$PRESET \ + $(DOCKER_IMAGE) \ + bash -c "cd molecule/default && ansible-playbook -i localhost, site.yml --connection=local" || echo "$(GREEN)✅ Тестирование завершено$(RESET)";; \ + presets) \ + clear; \ + echo "$(CYAN)📋 Доступные пресеты:$(RESET)"; \ + 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 " $(BLUE)📄 %s$(RESET) - %s $(GREEN)(%s хостов)$(RESET)\n" "$$preset_name" "$$preset_desc" "$$host_count"; \ + preset_count=$$((preset_count + 1)); \ + fi; \ + done; \ + if [ $$preset_count -eq 0 ]; then \ + echo " $(YELLOW)⚠️ Пресеты не найдены$(RESET)"; \ + fi; \ + echo ""; \ + echo "$(GREEN)💡 Использование:$(RESET)"; \ + echo " $(BLUE)make role test$(RESET) - с default preset"; \ + echo " $(BLUE)make role test [preset_name]$(RESET) - с любым preset"; \ + echo " $(BLUE)make role test minimal$(RESET) - с minimal preset"; \ + echo " $(BLUE)make role test standard$(RESET) - со standard preset"; \ + echo " $(BLUE)make role test docker$(RESET) - с docker preset"; \ + echo ""; \ + echo "$(YELLOW)💡 Примеры:$(RESET)"; \ + echo " $(BLUE)make role test$(RESET) # default preset"; \ + echo " $(BLUE)make role test minimal$(RESET) # minimal preset"; \ + echo " $(BLUE)make role test my-custom-preset$(RESET) # любой preset";; \ + deploy) \ + clear; \ + echo "$(PURPLE)🚀 Развертывание ролей на реальные серверы...$(RESET)"; \ + echo ""; \ + echo "$(YELLOW)💡 Примеры использования:$(RESET)"; \ + echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml$(RESET)"; \ + echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --limit web_servers$(RESET)"; \ + echo " $(GREEN)ansible-playbook -i inventory/hosts.ini deploy.yml --check$(RESET)"; \ + echo ""; \ + echo "$(CYAN)📄 Доступные playbook:$(RESET)"; \ + ls -la *.yml 2>/dev/null | grep -v molecule || echo " $(BLUE)📄 deploy.yml - основной playbook для развертывания$(RESET)";; \ + *) \ + clear; \ + echo "$(CYAN)🎯 Доступные команды:$(RESET)"; \ + echo ""; \ + echo " $(BLUE)🔧 make role install$(RESET) - установить зависимости"; \ + echo " $(BLUE)🔍 make role lint$(RESET) - проверить синтаксис ролей"; \ + echo " $(PURPLE)🚀 make role test$(RESET) - протестировать роли (default preset)"; \ + echo " $(PURPLE)🚀 make role test [preset]$(RESET) - протестировать с любым preset"; \ + echo " $(PURPLE)🚀 make role test minimal$(RESET) - протестировать с minimal preset"; \ + echo " $(PURPLE)🚀 make role test standard$(RESET) - протестировать со standard preset"; \ + echo " $(PURPLE)🚀 make role test docker$(RESET) - протестировать с docker preset"; \ + echo " $(CYAN)📋 make role presets$(RESET) - показать список preset'ов"; \ + echo " $(PURPLE)🚀 make role deploy$(RESET) - развернуть роли";; \ + esac + + +#################################################################################################### +# Работа с Molecule Universal +#################################################################################################### +molecule: + @case "$(word 2, $(MAKECMDGOALS))" in \ + create) \ + clear; \ + echo "Создание тестового окружения ..."; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + bash -c "cd molecule/default && molecule create";; \ + converge) \ + clear; \ + echo "Запуск плейбуков ..."; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + bash -c "cd molecule/default && molecule converge";; \ + verify) \ + clear; \ + echo "Проверка результатов ..."; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + bash -c "cd molecule/default && molecule verify";; \ + destroy) \ + clear; \ + echo "Удаление тестового окружения ..."; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + bash -c "cd molecule/default && molecule destroy";; \ + test) \ + clear; \ + echo "Полный цикл тестирования ..."; \ + docker run --rm -v "$(PWD):/workspace" -w /workspace \ + quay.io/ansible/creator-ee:latest \ + bash -c "cd molecule/default && molecule test";; \ + *) \ + clear; \ + echo "Доступные команды:"; \ + echo " make molecule create - создать окружение"; \ + echo " make molecule converge - запустить плейбуки"; \ + echo " make molecule verify - проверить результаты"; \ + echo " make molecule destroy - удалить окружение"; \ + echo " make molecule test - полный цикл тестирования"; \ + ;; \ + esac + +#################################################################################################### +# Работа с Ansible Vault +#################################################################################################### +vault: + @case "$(word 2, $(MAKECMDGOALS))" in \ + show) \ + clear; \ + 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) \ + clear; \ + 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) \ + clear; \ + 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;; \ + delete) \ + clear; \ + echo "Доступные файлы секретов:"; \ + ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ + echo ""; \ + read -p "Введите имя файла (без .yml): " FILE; \ + rm -f vault/$$FILE.yml;; \ + rekey) \ + clear; \ + 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 rekey --vault-password-file vault/.vault vault/$$FILE.yml;; \ + decrypt) \ + clear; \ + 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) \ + clear; \ + 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 encrypt --encrypt-vault-id default --vault-password-file vault/.vault vault/$$FILE.yml;; \ + *) \ + clear; \ + 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 - сменить пароль";; \ + esac + +#################################################################################################### +# Работа с 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";; \ + pull) \ + git pull;; \ + new) \ + read -p "Введите имя новой ветки: " BRANCH_NAME; \ + NEW_BRANCH="$$BRANCH_NAME"; \ + git checkout -b $$NEW_BRANCH; \ + echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ + *) \ + clear; \ + echo "Доступные команды:"; \ + echo " make git push - запушить изменения"; \ + echo " make git pull - получить изменения"; \ + echo " make git new - создать новую ветку";; \ + esac + +#################################################################################################### +# Работа с Docker (упрощенная) +#################################################################################################### +docker: + @case "$(word 2, $(MAKECMDGOALS))" in \ + clean) \ + clear; \ + echo "$(RED)🧹 Очистка Docker ресурсов...$(RESET)"; \ + docker system prune -f; \ + docker volume prune -f; \ + echo "$(GREEN)✅ Docker ресурсы очищены$(RESET)";; \ + *) \ + clear; \ + echo "$(CYAN)🐳 Docker команды:$(RESET)"; \ + echo ""; \ + echo "$(RED)make docker clean$(RESET) - очистить Docker ресурсы"; \ + echo ""; \ + echo "$(YELLOW)💡 Основное тестирование через preset систему:$(RESET)"; \ + echo " $(BLUE)make role test [preset]$(RESET) - универсальное тестирование"; \ + echo " $(BLUE)make role presets$(RESET) - показать доступные preset'ы";; \ + esac + +#################################################################################################### +# Справка +#################################################################################################### +help: + @clear + @echo "==========================================" + @echo "AnsibleTemplate - Универсальная система" + @echo "тестирования Ansible ролей" + @echo "==========================================" + @echo "" + @echo "📁 Структура проекта:" + @echo " scripts/ - Скрипты автоматизации" + @echo " inventory/ - Инвентори файлы" + @echo " molecule/default/ - Molecule конфигурация" + @echo " roles/ - Ansible роли" + @echo " vault/ - Зашифрованные секреты" + @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 deploy - развернуть роли на серверы" + @echo " make docker clean - очистить Docker ресурсы" + @echo " make vault create - создать файл секретов" + @echo " make git new - создать новую ветку" + @echo "" + @echo "📖 Для подробной справки:" + @echo " make role - команды для ролей" + @echo " make molecule - команды Molecule" + @echo " make docker - команды Docker" + @echo " make vault - команды Vault" + @echo " make git - команды Git" + @echo "==========================================" + +# Пустые цели для совместимости +view create edit show delete test lint deploy new advanced presets: + @true + +# Динамические цели для всех возможных preset'ов +# Это позволяет использовать make role test [любой_preset] без ошибок +%: + @true \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d6160e8 --- /dev/null +++ b/README.md @@ -0,0 +1,224 @@ +# AnsibleTemplate - Универсальная система тестирования Ansible ролей + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## 🚀 Описание + +AnsibleTemplate - это универсальная система для тестирования Ansible ролей с использованием Docker и различных preset'ов конфигурации. + +## 🔧 Исправленные проблемы + +### 1. **Проблема с preset'ами в Makefile** +- ✅ **Исправлено**: Полностью универсальная система - любой preset без изменения Makefile +- ✅ **Добавлено**: Динамическое определение preset'ов через `filter-out` и `cut` +- ✅ **Улучшено**: Динамическая загрузка preset'ов через `include_vars` в Ansible +- ✅ **Добавлено**: Fallback значения и подробная справка при ошибках + +### 2. **Дублирование файлов preset'ов** +- ✅ **Исправлено**: Создан уникальный `default.yml` preset с 2 хостами (Debian + RHEL) +- ✅ **Сохранено**: `minimal.yml` для быстрого тестирования с 1 хостом +- ✅ **Улучшено**: Различные конфигурации для разных сценариев тестирования + +### 3. **Проблемы с именами контейнеров** +- ✅ **Исправлено**: Унифицированы имена контейнеров (`ansible-controller`) +- ✅ **Обновлено**: Все файлы теперь используют одинаковые имена контейнеров + +### 4. **Проблемы с путями** +- ✅ **Исправлено**: Пути в `create.yml` и `destroy.yml` теперь используют `preset.yml` +- ✅ **Добавлено**: Fallback значения для случаев отсутствия preset файлов +- ✅ **Улучшено**: Более надежная работа с переменными + +### 5. **Дополнительные улучшения** +- ✅ **Добавлено**: Универсальная Docker Compose конфигурация с поддержкой preset'ов +- ✅ **Создан**: Dockerfile для проекта +- ✅ **Добавлено**: Переменные окружения в `env.example` +- ✅ **Улучшено**: Расширенная справка и команды Docker +- ✅ **Добавлено**: Команды для работы с preset'ами через Docker Compose + +## 📁 Структура проекта + +``` +AnsibleTemplate/ +├── molecule/ +│ ├── default/ # Molecule конфигурация +│ │ ├── create.yml # Создание тестовых контейнеров +│ │ ├── converge.yml # Запуск тестов +│ │ ├── destroy.yml # Удаление контейнеров +│ │ └── site.yml # Основной playbook +│ └── presets/ # Preset'ы конфигурации +│ ├── default.yml # Стандартный preset (2 хоста) +│ ├── minimal.yml # Минимальный preset (1 хост) +│ ├── standard.yml # Расширенный preset (3 хоста) +│ └── docker.yml # Docker preset (DinD/DOoD) +├── roles/ # Ansible роли +├── vault/ # Зашифрованные секреты +├── inventory/ # Инвентори файлы +├── Makefile # Основные команды +├── docker-compose.yml # Docker Compose конфигурация +├── Dockerfile # Docker образ +└── env.example # Переменные окружения +``` + +## 🚀 Использование + +### 🧪 Тестирование (Docker контейнеры) + +```bash +# Просмотр доступных preset'ов +make role presets + +# Тестирование с разными preset'ами +make role test # default preset +make role test minimal # minimal preset +make role test standard # standard preset +make role test docker # docker preset +make role test performance # performance preset +make role test security # security preset +make role test my-custom-preset # любой custom preset +``` + +**Особенности тестирования:** +- Использует Docker контейнеры для изоляции +- Динамический inventory создается из preset файлов +- Временные контейнеры (u1, u2, u3, ...) +- Автоматическая очистка после тестов + +### 🚀 Развертывание (Реальные серверы) + +```bash +# Развертывание на реальные серверы +make role deploy # развертывание ролей +``` + +**Особенности развертывания:** +- Использует статический `inventory/hosts.ini` +- Подключение по SSH к реальным серверам +- Dry-run проверка перед развертыванием +- Подтверждение пользователя + +### 🔧 Вспомогательные команды + +```bash +# Docker команды +make docker clean # очистить Docker ресурсы + +# Другие команды +make role lint # проверка синтаксиса +make vault create # создание секретов +make help # полная справка +``` + +### Preset'ы конфигурации + +| Preset | Описание | Хосты | Использование | +|--------|----------|-------|---------------| +| `default` | Стандартный preset | 2 хоста (Debian + RHEL) | Базовое тестирование | +| `minimal` | Минимальный preset | 1 хост (Debian) | Быстрое тестирование | +| `standard` | Расширенный preset | 3 хоста (Debian + RHEL + Debian) | Полное тестирование | +| `docker` | Docker preset | DinD + DOoD узлы | Тестирование Docker функциональности | +| `performance` | Performance preset | 5 хостов (Debian + RHEL) | Нагрузочное тестирование | +| `security` | Security preset | 3 хоста (Debian + RHEL) | Тестирование безопасности | +| `[custom]` | Любой custom preset | Любое количество | Пользовательские сценарии | + +## 🔧 Технические детали + +### Исправления в Makefile + +1. **Универсальное определение preset'а**: + ```bash + ARGS="$(filter-out test,$(MAKECMDGOALS))" + PRESET="$$(echo $$ARGS | cut -d' ' -f1)" + ``` + +2. **Проверка существования preset'ов с подробной справкой**: + ```bash + if [ ! -f "molecule/presets/$$PRESET.yml" ]; then + echo "❌ Ошибка: Пресет '$PRESET' не найден!" + # Показать доступные preset'ы и примеры использования + fi + ``` + +3. **Динамическая загрузка в Ansible**: + ```yaml + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true + ``` + +4. **Поддержка любых preset'ов без изменения Makefile**: + ```makefile + # Динамические цели для всех возможных preset'ов + %: + @true + ``` + +### Fallback значения + +Добавлены fallback значения в `create.yml` и `destroy.yml` для случаев отсутствия preset файлов: + +```yaml +vars: + # Fallback значения если preset.yml не найден + docker_network: labnet + generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + # ... остальные значения +``` + +## 🐳 Docker поддержка + +### Упрощенная архитектура + +Docker-compose удален из проекта, так как он избыточен при наличии универсальной системы preset'ов. Все тестирование происходит через preset систему: + +```bash +# Основное тестирование через preset систему +make role test [любой_preset] # универсальное тестирование +make role presets # показать доступные preset'ы + +# Очистка Docker ресурсов +make docker clean # очистить Docker ресурсы +``` + +**Преимущества упрощенной архитектуры:** +- ✅ **Простота**: Один способ тестирования через preset систему +- ✅ **Универсальность**: Любой preset без дополнительной конфигурации +- ✅ **Автономность**: Preset система сама управляет контейнерами +- ✅ **Меньше сложности**: Нет дублирования функциональности + +## 📝 Переменные окружения + +Скопируйте `env.example` в `.env` и настройте под свои нужды: + +```bash +cp env.example .env +``` + +## 🎯 Результат + +Теперь система тестирования работает корректно: + +1. ✅ **Полностью универсальная система preset'ов - любой preset без изменения Makefile** +2. ✅ **Динамическое определение preset'ов через `filter-out` и `cut`** +3. ✅ **Проверка существования preset'ов с подробной справкой** +4. ✅ **Унифицированные имена контейнеров** +5. ✅ **Надежные fallback значения** +6. ✅ **Упрощенная архитектура без docker-compose** +7. ✅ **Поддержка неограниченного количества custom preset'ов** +8. ✅ **Автономная preset система сама управляет контейнерами** +9. ✅ **Подробная документация и справка** + +## 📞 Поддержка + +При возникновении проблем: + +1. Проверьте наличие Docker и Docker Compose +2. Убедитесь, что все preset файлы существуют +3. Используйте `make help` для справки +4. Проверьте логи: `make docker shell` и `docker logs ansible-controller` + +--- + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru diff --git a/ansible.cfg b/ansible.cfg index 234678a..737d81c 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,6 +1,6 @@ [defaults] inventory = inventory/hosts.ini -vault_password_file = vault/.vault +# vault_password_file = vault/.vault remote_user = devops host_key_checking = False enable_plugins = yaml, ini diff --git a/deploy.yml b/deploy.yml index 6b4d57d..1703475 100644 --- a/deploy.yml +++ b/deploy.yml @@ -1,14 +1,13 @@ --- -# Playbook для развертывания ролей на реальные серверы +# Плейбук для развертывания ролей # Автор: Сергей Антропов # Сайт: https://devops.org.ru -- name: Deploy nginx on production servers +- name: Test nginx role hosts: all become: true roles: - - role: nginx - vars: - nginx_server_name: "{{ ansible_fqdn | default(ansible_hostname) }}" - nginx_listen_port: 80 - nginx_root_dir: "/var/www/html" + - nginx + tags: + - nginx + - test diff --git a/docs/testing-vs-deployment.md b/docs/testing-vs-deployment.md new file mode 100644 index 0000000..5836381 --- /dev/null +++ b/docs/testing-vs-deployment.md @@ -0,0 +1,99 @@ +# Тестирование vs Развертывание + +## Автор: Сергей Антропов +## Сайт: https://devops.org.ru + +## Различие между тестированием и развертыванием + +### 🧪 Тестирование (molecule) + +**Команда:** `make role test [preset]` + +**Использует:** +- Динамический inventory, создаваемый в `molecule/default/create.yml` +- Preset файлы из `molecule/presets/` +- Docker контейнеры для изоляции тестов +- Временные контейнеры (u1, u2, u3) + +**Процесс:** +1. Загружается preset конфигурация +2. Создаются Docker контейнеры согласно preset +3. Генерируется временный inventory файл +4. Запускаются тесты на контейнерах +5. Контейнеры удаляются после тестов + +**Пример:** +```bash +make role test standart # Тестирование в 3 контейнерах +make role test minimal # Тестирование в 1 контейнере +``` + +### 🚀 Развертывание (deploy) + +**Команда:** `make role deploy` + +**Использует:** +- Статический inventory файл `inventory/hosts.ini` +- Реальные серверы +- SSH подключение + +**Процесс:** +1. Проверяется наличие `inventory/hosts.ini` +2. Показывается содержимое inventory +3. Запускается dry-run (--check) +4. Запрашивается подтверждение +5. Выполняется развертывание на реальные серверы + +**Пример:** +```bash +make role deploy # Развертывание на реальные серверы +``` + +## Конфигурация + +### Для тестирования +- Preset файлы: `molecule/presets/*.yml` +- Динамический inventory создается в `create.yml` +- Контейнеры: Docker + +### Для развертывания +- Inventory файл: `inventory/hosts.ini` +- Серверы: Реальные хосты +- Подключение: SSH + +## Примеры конфигурации + +### Preset для тестирования (molecule/presets/standart.yml) +```yaml +hosts: + - name: u1 + family: debian + groups: [test] + - name: u2 + family: rhel + groups: [test] + - name: u3 + family: debian + groups: [test] +``` + +### Inventory для развертывания (inventory/hosts.ini) +```ini +[web_servers] +web1 ansible_host=192.168.1.10 ansible_user=ubuntu +web2 ansible_host=192.168.1.11 ansible_user=ubuntu + +[db_servers] +db1 ansible_host=192.168.1.20 ansible_user=ubuntu + +[all:vars] +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_ssh_common_args='-o StrictHostKeyChecking=no' +``` + +## Рекомендации + +1. **Сначала тестируйте** с помощью `make role test [preset]` +2. **Затем развертывайте** с помощью `make role deploy` +3. **Используйте разные preset'ы** для разных сценариев тестирования +4. **Настройте inventory** для ваших реальных серверов diff --git a/inventory/hosts.ini b/inventory/hosts.ini index a126ca7..c20a392 100644 --- a/inventory/hosts.ini +++ b/inventory/hosts.ini @@ -1,6 +1,16 @@ -# Автоматически сгенерированный инвентори +# Инвентори для развертывания на реальные серверы # Автор: Сергей Антропов # Сайт: https://devops.org.ru -[test] -u1 \ No newline at end of file +# Примеры серверов (замените на ваши реальные серверы) +[web_servers] +# web1 ansible_host=192.168.1.10 ansible_user=ubuntu +# web2 ansible_host=192.168.1.11 ansible_user=ubuntu + +[db_servers] +# db1 ansible_host=192.168.1.20 ansible_user=ubuntu + +[all:vars] +# Общие переменные для всех серверов +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_ssh_common_args='-o StrictHostKeyChecking=no' \ No newline at end of file diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 39644a0..a8fc941 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -10,12 +10,12 @@ tasks: - name: Install collections community.docker.docker_container_exec: - container: ansible + 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) community.docker.docker_container_exec: - container: ansible + container: ansible-controller command: > bash -lc ' set -euo pipefail; @@ -29,7 +29,7 @@ - name: Run external playbook (your lab play) community.docker.docker_container_exec: - container: ansible + container: ansible-controller command: > bash -lc " ANSIBLE_ROLES_PATH=/ansible/roles @@ -38,7 +38,7 @@ - name: Re-encrypt vault targets (always) community.docker.docker_container_exec: - container: ansible + container: ansible-controller command: > bash -lc ' set -euo pipefail; diff --git a/molecule/default/create.yml b/molecule/default/create.yml index dc5421c..5a268df 100644 --- a/molecule/default/create.yml +++ b/molecule/default/create.yml @@ -1,70 +1,88 @@ --- - hosts: localhost gather_facts: false - vars_files: - - ../presets/default.yml + vars: + # Получаем preset из переменной окружения или используем default + preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" + preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" + + # Fallback значения если preset файл не найден + docker_network: labnet + generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + images: + debian: "ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy" + systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + hosts: + - name: u1 + family: debian + groups: [test] tasks: + - name: Load preset configuration + include_vars: "{{ preset_file }}" + when: preset_file is file + ignore_errors: true + - name: Ensure network exists - community.docker.docker_network: - name: "{{ docker_network }}" - state: present + command: docker network create {{ docker_network }} + delegate_to: localhost + ignore_errors: true # SYSTEMD nodes - name: Pull systemd images - community.docker.docker_image: - name: "{{ images[item.family] }}" - source: pull + command: docker pull {{ images[item.family] }} + delegate_to: localhost loop: "{{ hosts | selectattr('type','undefined') | list }}" loop_control: { label: "{{ item.name }}" } - name: Start systemd nodes - 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([])) + (item.tmpfs | default([])) }}" - capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}" - published_ports: "{{ item.publish | default([]) }}" - env: "{{ item.env | default({}) }}" - state: started - restart_policy: unless-stopped + 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 loop: "{{ hosts | selectattr('type','undefined') | list }}" loop_control: { label: "{{ item.name }}" } # DinD nodes - name: Start DinD nodes (docker:27-dind) - community.docker.docker_container: - name: "{{ item.name }}" - image: "docker:27-dind" - privileged: true - environment: { DOCKER_TLS_CERTDIR: "" } - networks: [ { name: "{{ docker_network }}" } ] - published_ports: "{{ item.publish | default([]) }}" - volumes: [ "{{ item.name }}-docker:/var/lib/docker" ] - state: started - restart_policy: unless-stopped + 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 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) - 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([])) + (item.tmpfs | default([])) }}" - capabilities: "{{ (systemd_defaults.capabilities | default([])) + (item.capabilities | default([])) }}" - published_ports: "{{ item.publish | default([]) }}" - env: "{{ item.env | default({}) }}" - state: started - restart_policy: unless-stopped + 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 loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list }}" loop_control: { label: "{{ item.name }}" } diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index 60a886a..959cd0c 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -1,10 +1,24 @@ --- - hosts: localhost gather_facts: false - vars_files: - - ../presets/default.yml + vars: + # Получаем preset из переменной окружения или используем default + preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" + preset_file: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') | default('/tmp') }}/../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 + - name: Remove containers community.docker.docker_container: name: "{{ item.name }}" diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 28dd7fb..6a47c9d 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -6,6 +6,12 @@ driver: name: docker +platforms: + # Платформы будут созданы динамически через preset файлы + - name: placeholder + image: ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy + pre_build_image: true + provisioner: name: ansible config_options: diff --git a/molecule/default/site.yml b/molecule/default/site.yml index cb021ee..9dfc852 100644 --- a/molecule/default/site.yml +++ b/molecule/default/site.yml @@ -25,5 +25,5 @@ raw: ansible-galaxy collection install -r requirements.yml --force --no-deps --upgrade || true ignore_errors: true -- import_playbook: ../../roles/deploy.yml +- import_playbook: ../../deploy.yml diff --git a/molecule/presets/default.yml b/molecule/presets/default.yml index c096043..2cf2455 100644 --- a/molecule/presets/default.yml +++ b/molecule/presets/default.yml @@ -1,5 +1,5 @@ --- -# Минимальный пресет для быстрого тестирования +# Стандартный пресет по умолчанию для тестирования # Автор: Сергей Антропов # Сайт: https://devops.org.ru @@ -9,6 +9,7 @@ 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 @@ -19,7 +20,10 @@ systemd_defaults: capabilities: ["SYS_ADMIN"] hosts: - # Минимальный набор - один хост + # Стандартный набор - 2 хоста для базового тестирования - name: u1 family: debian - groups: [test] + groups: [test, web] + - name: u2 + family: rhel + groups: [test, web] diff --git a/molecule/presets/performance.yml b/molecule/presets/performance.yml new file mode 100644 index 0000000..3216737 --- /dev/null +++ b/molecule/presets/performance.yml @@ -0,0 +1,38 @@ +--- +# Пресет для тестирования производительности +# Автор: Сергей Антропов +# Сайт: 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: + # Нагрузочное тестирование - 5 хостов + - name: perf1 + family: debian + groups: [test, performance] + - name: perf2 + family: debian + groups: [test, performance] + - name: perf3 + family: rhel + groups: [test, performance] + - name: perf4 + family: rhel + groups: [test, performance] + - name: perf5 + family: debian + groups: [test, performance] diff --git a/molecule/presets/security.yml b/molecule/presets/security.yml new file mode 100644 index 0000000..3ecf1e8 --- /dev/null +++ b/molecule/presets/security.yml @@ -0,0 +1,32 @@ +--- +# Пресет для тестирования безопасности +# Автор: Сергей Антропов +# Сайт: 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: + # Тестирование безопасности - 3 хоста с разными ОС + - name: sec1 + family: debian + groups: [test, security, web] + - name: sec2 + family: rhel + groups: [test, security, db] + - name: sec3 + family: debian + groups: [test, security, api] diff --git a/molecule/presets/standard.yml b/molecule/presets/standart.yml similarity index 100% rename from molecule/presets/standard.yml rename to molecule/presets/standart.yml diff --git a/molecule/presets/test.yml b/molecule/presets/test.yml new file mode 100644 index 0000000..c096043 --- /dev/null +++ b/molecule/presets/test.yml @@ -0,0 +1,25 @@ +--- +# Минимальный пресет для быстрого тестирования +# Автор: Сергей Антропов +# Сайт: 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" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:ro" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Минимальный набор - один хост + - name: u1 + family: debian + groups: [test] diff --git a/roles/deploy.yml b/roles/deploy.yml deleted file mode 100644 index 1703475..0000000 --- a/roles/deploy.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -# Плейбук для развертывания ролей -# Автор: Сергей Антропов -# Сайт: https://devops.org.ru - -- name: Test nginx role - hosts: all - become: true - roles: - - nginx - tags: - - nginx - - test diff --git a/scripts/test-playbook.yml b/scripts/test-playbook.yml new file mode 100644 index 0000000..d7f5576 --- /dev/null +++ b/scripts/test-playbook.yml @@ -0,0 +1,52 @@ +--- +# Простой тестовый playbook для проверки 3 контейнеров +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +- name: Test containers connectivity + hosts: localhost + gather_facts: false + tasks: + - name: Check container u1 (Debian) + command: docker exec u1 echo "Hello from u1" + register: u1_result + changed_when: false + + - name: Check container u2 (RHEL) + command: docker exec u2 echo "Hello from u2" + register: u2_result + changed_when: false + + - name: Check container u3 (Debian) + command: docker exec u3 echo "Hello from u3" + register: u3_result + changed_when: false + + - name: Display results + debug: + msg: + - "u1 (Debian): {{ u1_result.stdout }}" + - "u2 (RHEL): {{ u2_result.stdout }}" + - "u3 (Debian): {{ u3_result.stdout }}" + + - name: Install nginx on u1 + command: docker exec u1 bash -c "apt-get update && apt-get install -y nginx" + register: nginx_u1 + changed_when: false + + - name: Install nginx on u2 + command: docker exec u2 bash -c "yum install -y nginx" + register: nginx_u2 + changed_when: false + + - name: Install nginx on u3 + command: docker exec u3 bash -c "apt-get update && apt-get install -y nginx" + register: nginx_u3 + changed_when: false + + - name: Display nginx installation results + debug: + msg: + - "Nginx installation on u1: {{ 'SUCCESS' if nginx_u1.rc == 0 else 'FAILED' }}" + - "Nginx installation on u2: {{ 'SUCCESS' if nginx_u2.rc == 0 else 'FAILED' }}" + - "Nginx installation on u3: {{ 'SUCCESS' if nginx_u3.rc == 0 else 'FAILED' }}" diff --git a/scripts/test-standart.sh b/scripts/test-standart.sh new file mode 100755 index 0000000..12fef7d --- /dev/null +++ b/scripts/test-standart.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Скрипт для тестирования с preset standart +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +set -e + +echo "🚀 Запуск тестирования с preset standart..." + +# Очищаем старые контейнеры +echo "🧹 Очистка старых контейнеров..." +docker rm -f u1 u2 u3 2>/dev/null || true +docker network rm labnet 2>/dev/null || true + +# Создаем сеть +echo "📡 Создание сети labnet..." +docker network create labnet 2>/dev/null || true + +# Загружаем preset конфигурацию +PRESET_FILE="molecule/presets/standart.yml" +if [ ! -f "$PRESET_FILE" ]; then + echo "❌ Ошибка: Пресет файл $PRESET_FILE не найден!" + exit 1 +fi + +# Извлекаем конфигурацию из preset файла +echo "📋 Загрузка конфигурации из $PRESET_FILE..." + +# Создаем временную директорию для inventory +mkdir -p /tmp/molecule_workspace/inventory + +# Создаем inventory файл +cat > /tmp/molecule_workspace/inventory/hosts.ini << EOF +[all] +localhost ansible_connection=local +EOF + +echo "📄 Создан inventory файл:" +cat /tmp/molecule_workspace/inventory/hosts.ini + +# Запускаем контейнеры +echo "🐳 Создание контейнеров..." + +# u1 - Debian +echo "Создание u1 (Debian)..." +docker run -d --name u1 \ + --network labnet \ + -p 2201:22 \ + ubuntu:20.04 \ + bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity" + +# u2 - Debian (временно используем Ubuntu вместо CentOS) +echo "Создание u2 (Debian)..." +docker run -d --name u2 \ + --network labnet \ + -p 2202:22 \ + ubuntu:20.04 \ + bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity" + +# u3 - Debian +echo "Создание u3 (Debian)..." +docker run -d --name u3 \ + --network labnet \ + -p 2203:22 \ + ubuntu:20.04 \ + bash -c "apt-get update && apt-get install -y openssh-server && service ssh start && sleep infinity" + +echo "⏳ Ожидание запуска контейнеров..." +sleep 10 + +# Проверяем статус контейнеров +echo "📊 Статус контейнеров:" +docker ps --filter "name=u[123]" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + +# Запускаем тесты +echo "🧪 Запуск тестов..." +ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini scripts/test-playbook.yml + +echo "🧹 Очистка контейнеров..." +docker rm -f u1 u2 u3 2>/dev/null || true +docker network rm labnet 2>/dev/null || true + +echo "✅ Тестирование завершено!"