# ============================================================================= # 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 ?= inecs/ansible-controller:latest DOCKER_DIND_IMAGE ?= docker:27-dind CONTAINER_NAME ?= ansible-controller # Переменные для Docker Hub DOCKER_REGISTRY ?= inecs DOCKER_VERSION ?= latest DOCKER_IMAGES := ansible-controller alt-linux astra-linux redos rhel centos alma rocky # Multi-arch поддержка DOCKER_PLATFORMS ?= linux/amd64,linux/arm64 DOCKER_BUILDX_BUILDER ?= multiarch-builder # Базовые образы и их теги BASE_IMAGES := altlinux/p9 astralinux/astra-1.7 redos/redos:9 registry.access.redhat.com/ubi8/ubi quay.io/centos/centos:stream9 almalinux:8 rockylinux:8 .PHONY: role vault git docker presets controller help # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С РОЛЯМИ # ============================================================================= role: @case "$(word 2, $(MAKECMDGOALS))" in \ lint) \ 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) \ echo "🚀 Тестирование ролей ..."; \ PRESET="default"; \ 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 ""; \ 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;; \ deploy) \ echo "🚀 Развертывание ролей на реальные серверы..."; \ echo ""; \ 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 "🚀 Запуск развертывания..."; \ 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;; \ *) \ echo "🎯 Доступные команды:"; \ echo ""; \ echo " 🚀 make role test [preset] - протестировать роли с preset'ом"; \ echo " 💡 Примеры:"; \ echo " make role test # с default preset"; \ echo " make role test minimal # с minimal preset"; \ echo " make role test etcd-patroni # с etcd-patroni preset"; \ echo ""; \ echo " 🚀 make role deploy - развернуть роли на реальные серверы"; \ echo " 💡 Требует: inventory/hosts.ini"; \ echo ""; \ echo " 🔍 make role lint - проверить синтаксис ролей"; \ echo " 💡 Использует: ansible-lint";; \ esac # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С PRESET'АМИ # ============================================================================= presets: @case "$(word 2, $(MAKECMDGOALS))" in \ 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) \ 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 ""; \ echo " 📋 make presets list - показать список всех preset'ов"; \ echo " 💡 Показывает: название, описание, количество хостов"; \ echo ""; \ echo " 📄 make presets info - подробная информация о preset'е"; \ echo " 💡 Показывает: описание, хосты, сеть, образы"; \ echo " 💡 Требует: PRESET=имя_пресета"; \ echo ""; \ echo " 🚀 make presets test - запустить тест с preset'ом"; \ echo " 💡 Запускает: molecule test с выбранным preset'ом"; \ echo " 💡 Требует: PRESET=имя_пресета"; \ echo ""; \ echo "💡 Примеры:"; \ echo " make presets list # показать все preset'ы"; \ echo " make presets info PRESET=etcd-patroni # информация о etcd-patroni"; \ echo " make presets test PRESET=minimal # тест с minimal preset"; \ echo " make presets test PRESET=performance # тест с performance preset";; \ esac # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С VAULT # ============================================================================= vault: @case "$(word 2, $(MAKECMDGOALS))" in \ create) \ 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 "🔐 Редактирование секретов..."; \ 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 "🔐 Удаление секретов..."; \ ls -la vault/*.yml 2>/dev/null || echo "Нет зашифрованных файлов"; \ echo ""; \ read -p "Введите имя файла (без .yml): " FILE; \ rm -f vault/$$FILE.yml;; \ encrypt) \ 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;; \ decrypt) \ 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;; \ rekey) \ 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;; \ 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 " 💡 Интерактивное создание зашифрованного файла"; \ echo ""; \ echo " ✏️ make vault edit - редактировать существующие секреты"; \ echo " 💡 Открывает редактор для изменения секретов"; \ echo ""; \ echo " 👁️ make vault show - показать содержимое секретов"; \ echo " 💡 Расшифровывает и показывает содержимое"; \ echo ""; \ echo " 🗑️ make vault delete - удалить файл секретов"; \ echo " 💡 Безвозвратное удаление файла"; \ echo ""; \ echo " 🔒 make vault encrypt - зашифровать существующий файл"; \ echo " 💡 Шифрует незашифрованный файл"; \ echo ""; \ echo " 🔓 make vault decrypt - расшифровать файл"; \ echo " 💡 Создает незашифрованную копию"; \ echo ""; \ echo " 🔑 make vault rekey - сменить пароль шифрования"; \ echo " 💡 Изменяет пароль для существующего файла"; \ echo ""; \ echo " ✅ make vault check - проверить vault файлы"; \ echo " 💡 Проверяет структуру и статус файлов"; \ echo ""; \ echo " 🔍 make vault scan - поиск потенциальных секретов"; \ echo " 💡 Сканирует проект на наличие незашифрованных секретов";; \ esac # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С GIT # ============================================================================= git: @case "$(word 2, $(MAKECMDGOALS))" in \ push) \ echo "📤 Отправка изменений в репозиторий..."; \ git add .; \ git commit -m "Обновление проекта"; \ git push origin main;; \ pull) \ echo "📥 Получение изменений из репозитория..."; \ git pull origin main;; \ new) \ echo "🌿 Создание новой ветки..."; \ read -p "Введите имя ветки: " BRANCH; \ git checkout -b "$$BRANCH"; \ echo "✅ Ветка '$$BRANCH' создана";; \ *) \ echo "🎯 Доступные команды:"; \ echo ""; \ echo " 📤 make git push - отправить изменения в репозиторий"; \ echo " 💡 Выполняет: git add . && git commit && git push"; \ echo ""; \ echo " 📥 make git pull - получить изменения из репозитория"; \ echo " 💡 Выполняет: git pull origin main"; \ echo ""; \ echo " 🌿 make git new - создать новую ветку"; \ echo " 💡 Интерактивно запрашивает имя ветки"; \ echo " 💡 Выполняет: git checkout -b имя_ветки";; \ esac # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С DOCKER # ============================================================================= docker: @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 образов (multi-arch)..."; \ echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ echo "📋 Builder: $(DOCKER_BUILDX_BUILDER)"; \ echo ""; \ $(MAKE) docker-setup-builder; \ for image in $(DOCKER_IMAGES); do \ echo "🔨 Сборка $(DOCKER_REGISTRY)/$$image:$(DOCKER_VERSION)"; \ $(MAKE) docker-build-image IMAGE=$$image; \ 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 образов..."; \ 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 "✅ Все образы обновлены";; \ purge) \ echo "🧹 Полная очистка Docker..."; \ echo "⚠️ ВНИМАНИЕ: Это удалит ВСЕ Docker данные!"; \ echo ""; \ read -p "Продолжить? (y/N): " confirm; \ if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \ echo "🛑 Остановка всех контейнеров..."; \ docker stop $$(docker ps -aq) 2>/dev/null || true; \ echo "🗑️ Удаление всех контейнеров..."; \ docker rm $$(docker ps -aq) 2>/dev/null || true; \ echo "🗑️ Удаление всех образов..."; \ docker rmi $$(docker images -aq) 2>/dev/null || true; \ echo "🗑️ Удаление всех томов..."; \ docker volume rm $$(docker volume ls -q) 2>/dev/null || true; \ echo "🗑️ Удаление всех сетей..."; \ docker network rm $$(docker network ls -q) 2>/dev/null || true; \ echo "🧹 Очистка системы..."; \ docker system prune -af --volumes; \ echo "✅ Docker полностью очищен"; \ else \ echo "❌ Очистка отменена"; \ fi;; \ clean-builder) \ echo "🧹 Очистка multi-arch builder..."; \ if docker buildx ls | grep -q $(DOCKER_BUILDX_BUILDER); then \ echo "🗑️ Удаление builder $(DOCKER_BUILDX_BUILDER)..."; \ docker buildx rm $(DOCKER_BUILDX_BUILDER) || true; \ echo "✅ Builder удален"; \ else \ echo "ℹ️ Builder $(DOCKER_BUILDX_BUILDER) не найден"; \ fi;; \ *) \ echo "🎯 Доступные команды:"; \ echo ""; \ echo " 🔧 make docker prepare - подготовка к работе с Docker Hub"; \ echo " 💡 Показывает: registry, version, список образов"; \ echo " 💡 Рекомендует: docker login перед работой"; \ echo ""; \ echo " 🐳 make docker build - собрать все Docker образы (multi-arch)"; \ echo " 💡 Собирает: ansible-controller, alt-linux, astra-linux, redos"; \ echo " 💡 Собирает: rhel, centos, alma, rocky"; \ echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ echo " 💡 Тегирует: inecs/образ: (автоматически извлекает теги)"; \ echo " 💡 Отправляет: автоматически в Docker Hub"; \ echo ""; \ echo " 📤 make docker push - отправить образы в Docker Hub"; \ echo " 💡 Требует: docker login"; \ echo " 💡 Отправляет: все образы в registry inecs"; \ echo ""; \ echo " 📥 make docker pull - загрузить образы из Docker Hub"; \ echo " 💡 Загружает: все образы из registry inecs"; \ echo " 💡 Пропускает: отсутствующие образы"; \ echo ""; \ echo " 🧹 make docker clean - удалить локальные образы"; \ echo " 💡 Удаляет: все образы inecs/*:latest"; \ echo " 💡 Безопасно: игнорирует ошибки"; \ echo ""; \ echo " 🧹 make docker clean-builder - очистка multi-arch builder"; \ echo " 💡 Удаляет: builder контейнер"; \ echo " 💡 Полезно: при проблемах со сборкой"; \ echo ""; \ echo " 📊 make docker info - информация о собранных образах"; \ echo " 💡 Показывает: размер, дата создания, теги"; \ echo ""; \ echo " 🔄 make docker update - обновить все образы"; \ echo " 💡 Выполняет: pull + build + push"; \ echo " 💡 Полный цикл обновления"; \ echo ""; \ echo " 💥 make docker purge - ПОЛНАЯ очистка Docker"; \ echo " ⚠️ УДАЛЯЕТ: все контейнеры, образы, тома, сети"; \ echo " ⚠️ ОСТАНОВИТ: все запущенные контейнеры"; \ echo " ⚠️ ТРЕБУЕТ: подтверждение пользователя"; \ echo ""; \ echo " 🔧 make docker-setup-builder - настройка multi-arch builder"; \ echo " 💡 Создает: builder в контейнере (не в системе)"; \ echo " 💡 Поддерживает: amd64 и arm64 архитектуры";; \ esac # ============================================================================= # ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ DOCKER # ============================================================================= # Настройка multi-arch builder docker-setup-builder: @echo "🔧 Настройка multi-arch builder в контейнере..."; \ if ! docker buildx ls | grep -q $(DOCKER_BUILDX_BUILDER); then \ echo "📦 Создание builder $(DOCKER_BUILDX_BUILDER) в контейнере..."; \ docker buildx create --name $(DOCKER_BUILDX_BUILDER) --driver docker-container --bootstrap --use; \ echo "⏳ Ожидание запуска builder..."; \ sleep 5; \ else \ echo "✅ Builder $(DOCKER_BUILDX_BUILDER) уже существует"; \ docker buildx use $(DOCKER_BUILDX_BUILDER); \ fi; \ echo "🔍 Проверка статуса builder..."; \ docker buildx inspect $(DOCKER_BUILDX_BUILDER) --bootstrap # Извлечение тега из базового образа docker-get-base-tag: @if [ -z "$(IMAGE)" ]; then \ echo "❌ Ошибка: IMAGE не указан"; \ exit 1; \ fi; \ case "$(IMAGE)" in \ alt-linux) \ BASE_IMAGE="altlinux/p9"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ astra-linux) \ BASE_IMAGE="astralinux/astra-1.7"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ redos) \ BASE_IMAGE="redos/redos:9"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ rhel) \ BASE_IMAGE="registry.access.redhat.com/ubi8/ubi"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ centos) \ BASE_IMAGE="quay.io/centos/centos:stream9"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ alma) \ BASE_IMAGE="almalinux:8"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ rocky) \ BASE_IMAGE="rockylinux:8"; \ TAG=$$(docker inspect --format='{{index .RepoDigests 0}}' $$BASE_IMAGE 2>/dev/null | cut -d'@' -f1 | cut -d':' -f2 || echo "latest");; \ ansible-controller) \ TAG="latest";; \ *) \ echo "❌ Неизвестный образ: $(IMAGE)"; \ exit 1;; \ esac; \ echo "📋 Образ: $(IMAGE)"; \ echo "📋 Базовый образ: $$BASE_IMAGE"; \ echo "📋 Тег: $$TAG"; \ echo "$$TAG" # Сборка одного образа с multi-arch docker-build-image: @if [ -z "$(IMAGE)" ]; then \ echo "❌ Ошибка: IMAGE не указан"; \ exit 1; \ fi; \ TAG=$$($(MAKE) docker-get-base-tag IMAGE=$(IMAGE)); \ echo "🔨 Сборка $(DOCKER_REGISTRY)/$(IMAGE):$$TAG"; \ cd dockerfiles/$(IMAGE) && \ docker buildx build \ --platform $(DOCKER_PLATFORMS) \ --tag $(DOCKER_REGISTRY)/$(IMAGE):$$TAG \ --tag $(DOCKER_REGISTRY)/$(IMAGE):latest \ --push \ .; \ echo "✅ $(IMAGE):$$TAG собран и отправлен" # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С ANSIBLE-CONTROLLER # ============================================================================= controller: @case "$(word 2, $(MAKECMDGOALS))" in \ build) \ echo "🔨 Сборка ansible-controller (multi-arch)..."; \ echo "📋 Платформы: $(DOCKER_PLATFORMS)"; \ $(MAKE) docker-setup-builder; \ cd dockerfiles/ansible-controller && \ docker buildx build \ --platform $(DOCKER_PLATFORMS) \ --tag $(DOCKER_REGISTRY)/ansible-controller:$(DOCKER_VERSION) \ --push \ .; \ 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 (multi-arch)"; \ echo " 💡 Собирает: inecs/ansible-controller:latest"; \ echo " 💡 Платформы: $(DOCKER_PLATFORMS)"; \ echo " 💡 Использует: dockerfiles/ansible-controller/Dockerfile"; \ echo " 💡 Requirements: dockerfiles/ansible-controller/requirements.yml"; \ echo ""; \ echo " 🚀 make controller run - запустить ansible-controller"; \ echo " 💡 Запускает: docker-compose up -d"; \ echo " 💡 Использует: dockerfiles/ansible-controller/docker-compose.yml"; \ echo ""; \ echo " 🛑 make controller stop - остановить ansible-controller"; \ echo " 💡 Останавливает: docker-compose down"; \ echo " 💡 Удаляет: контейнеры и сети";; \ esac # ============================================================================= # СПРАВКА # ============================================================================= help: @echo "==========================================" @echo "AnsibleTemplate - Универсальная система" @echo "тестирования Ansible ролей" @echo "==========================================" @echo "" @echo "📁 Структура проекта:" @echo " scripts/ - Скрипты автоматизации" @echo " inventory/ - Инвентори файлы" @echo " molecule/default/ - Molecule конфигурация" @echo " roles/ - Ansible роли" @echo " vault/ - Зашифрованные секреты" @echo " dockerfiles/ - Docker образы для тестирования" @echo "" @echo "🚀 ОСНОВНЫЕ КОМАНДЫ:" @echo " make role lint - проверить синтаксис ролей" @echo " make role test [preset] - протестировать роли с preset'ом" @echo " make role deploy - развернуть роли на реальные серверы" @echo "" @echo "📋 PRESET'Ы (тестовые окружения):" @echo " make presets list - показать все доступные preset'ы" @echo " make presets info - подробная информация о preset'е" @echo " make presets test - запустить тест с preset'ом" @echo "" @echo "🐳 DOCKER ОБРАЗЫ:" @echo " make docker prepare - подготовка к работе с Docker Hub" @echo " make docker build - собрать все Docker образы" @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)" @echo " make docker purge - ПОЛНАЯ очистка Docker (ОСТОРОЖНО!)" @echo "" @echo "🔐 VAULT (управление секретами):" @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 check - проверить vault файлы" @echo " make vault scan - поиск потенциальных секретов" @echo "" @echo "🌿 GIT (управление версиями):" @echo " make git push - отправить изменения в репозиторий" @echo " make git pull - получить изменения из репозитория" @echo " make git new - создать новую ветку" @echo "" @echo "🎮 CONTROLLER (ansible-controller):" @echo " make controller build - собрать ansible-controller" @echo " make controller run - запустить ansible-controller" @echo " make controller stop - остановить ansible-controller" @echo "" @echo "💡 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:" @echo " make presets list # показать все preset'ы" @echo " make presets test PRESET=etcd-patroni # тест с etcd-patroni" @echo " make role test minimal # быстрый тест" @echo " make docker build # собрать все образы" @echo " make docker purge # полная очистка Docker" @echo " make vault create # создать секреты" @echo "" @echo "📖 Подробная справка: make [команда]" @echo "==========================================" # Пустые цели для совместимости view create edit show delete lint deploy new advanced list info test build push pull clean prepare update run stop purge clean-builder: @true