# ============================================================================= # Ansible Template - Универсальная лаборатория для тестирования Ansible ролей # Автор: Сергей Антропов # Сайт: https://devops.org.ru # ============================================================================= # ============================================================================= # ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ # ============================================================================= # Основные переменные PROJECT_NAME ?= ansible-template VERSION ?= 0.1.0 AUTHOR ?= "Сергей Антропов" SITE ?= "https://devops.org.ru" # Docker переменные DOCKER_IMAGE ?= quay.io/ansible/creator-ee:latest DOCKER_COMPOSE ?= docker compose DOCKER_NETWORK ?= labnet # Molecule переменные SCENARIO ?= universal LAB_SPEC ?= molecule/presets/minimal.yml MOLECULE_EPHEMERAL_DIRECTORY ?= /tmp/molecule # Kubernetes переменные KUBE_CONTEXT ?= kind-lab ISTIO_VERSION ?= 1.22.1 KIND_VERSION ?= v0.23.0 # Переменные окружения ENV_FILE ?= .env ROLES_DIR ?= ./roles VAULT_PASSWORD_FILE ?= vault/.vault # Цвета для вывода 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 # ============================================================================= # ОСНОВНЫЕ КОМАНДЫ # ============================================================================= .PHONY: help help: ## Показать справку по всем командам @echo "$(CYAN)Ansible Template - Универсальная лаборатория$(RESET)" @echo "$(YELLOW)Автор: $(AUTHOR)$(RESET)" @echo "$(YELLOW)Сайт: $(SITE)$(RESET)" @echo "" @echo "$(GREEN)Основные команды:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) | grep -E "^(init|setup|clean|help)" @echo "" @echo "$(GREEN)Лаборатория:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^lab-[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) @echo "" @echo "$(GREEN)Kubernetes:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^kube-[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) @echo "" @echo "$(GREEN)Отчеты и мониторинг:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^(report|kubeconfigs|open-report|full-test):.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) @echo "" @echo "$(GREEN)Пресеты:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^preset-[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) @echo "" @echo "$(GREEN)Роли:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^role-[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) @echo "" @echo "$(GREEN)Утилиты:$(RESET)" @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " $(CYAN)%-20s$(RESET) %s\n", $$1, $$2}' $(MAKEFILE_LIST) | grep -E "^(lint|env|vault|git|docker|report|snapshot|cleanup|chaos|check-secrets|idempotence)" # ============================================================================= # ИНИЦИАЛИЗАЦИЯ И НАСТРОЙКА # ============================================================================= .PHONY: init init: setup-env setup-vault setup-roles setup-precommit ## Полная инициализация проекта @echo "$(GREEN)✅ Проект успешно инициализирован!$(RESET)" @echo "$(YELLOW)📖 Документация: $(SITE)$(RESET)" @echo "$(YELLOW)🚀 Быстрый старт: make lab up$(RESET)" .PHONY: setup-env setup-env: ## Создать .env файл с настройками @if [ ! -f $(ENV_FILE) ]; then \ echo "$(YELLOW)Создание .env файла...$(RESET)"; \ echo "# Ansible Template Environment" > $(ENV_FILE); \ echo "PROJECT_NAME=$(PROJECT_NAME)" >> $(ENV_FILE); \ echo "VERSION=$(VERSION)" >> $(ENV_FILE); \ echo "AUTHOR=$(AUTHOR)" >> $(ENV_FILE); \ echo "SITE=$(SITE)" >> $(ENV_FILE); \ echo "" >> $(ENV_FILE); \ echo "# Docker settings" >> $(ENV_FILE); \ echo "DOCKER_IMAGE=$(DOCKER_IMAGE)" >> $(ENV_FILE); \ echo "DOCKER_NETWORK=$(DOCKER_NETWORK)" >> $(ENV_FILE); \ echo "" >> $(ENV_FILE); \ echo "# Molecule settings" >> $(ENV_FILE); \ echo "SCENARIO=$(SCENARIO)" >> $(ENV_FILE); \ echo "LAB_SPEC=$(LAB_SPEC)" >> $(ENV_FILE); \ echo "" >> $(ENV_FILE); \ echo "# Kubernetes settings" >> $(ENV_FILE); \ echo "KUBE_CONTEXT=$(KUBE_CONTEXT)" >> $(ENV_FILE); \ echo "ISTIO_VERSION=$(ISTIO_VERSION)" >> $(ENV_FILE); \ echo "KIND_VERSION=$(KIND_VERSION)" >> $(ENV_FILE); \ echo "" >> $(ENV_FILE); \ echo "# Paths" >> $(ENV_FILE); \ echo "ROLES_DIR=$(ROLES_DIR)" >> $(ENV_FILE); \ echo "VAULT_PASSWORD_FILE=$(VAULT_PASSWORD_FILE)" >> $(ENV_FILE); \ echo "$(GREEN)✅ .env файл создан$(RESET)"; \ else \ echo "$(YELLOW)⚠️ .env файл уже существует$(RESET)"; \ fi .PHONY: setup-vault setup-vault: ## Создать vault-password.txt @if [ ! -f $(VAULT_PASSWORD_FILE) ]; then \ echo "$(YELLOW)Создание vault-password.txt...$(RESET)"; \ echo "ansible-vault-password" > $(VAULT_PASSWORD_FILE); \ echo "$(GREEN)✅ vault-password.txt создан$(RESET)"; \ else \ echo "$(YELLOW)⚠️ vault-password.txt уже существует$(RESET)"; \ fi .PHONY: setup-roles setup-roles: ## Создать директорию для ролей @mkdir -p $(ROLES_DIR) @echo "$(GREEN)✅ Директория ролей создана: $(ROLES_DIR)$(RESET)" .PHONY: setup-precommit setup-precommit: ## Установить pre-commit хуки @if command -v pre-commit >/dev/null 2>&1; then \ pre-commit install; \ echo "$(GREEN)✅ Pre-commit хуки установлены$(RESET)"; \ else \ echo "$(YELLOW)⚠️ pre-commit не установлен. Установите: pip install pre-commit$(RESET)"; \ fi # ============================================================================= # УПРАВЛЕНИЕ ЛАБОРАТОРИЕЙ # ============================================================================= .PHONY: lab lab: ## Управление лабораторией (up|down|sh|test|create|converge|verify|destroy|reset) @case "$(word 2, $(MAKECMDGOALS))" in \ up) \ echo "$(GREEN)🚀 Поднимаем контроллер...$(RESET)"; \ $(DOCKER_COMPOSE) up -d; \ echo "$(GREEN)✅ Контроллер запущен$(RESET)";; \ down) \ echo "$(YELLOW)🛑 Останавливаем контроллер...$(RESET)"; \ $(DOCKER_COMPOSE) down -v; \ echo "$(GREEN)✅ Контроллер остановлен$(RESET)";; \ sh) \ echo "$(BLUE)🐚 Входим в контроллер...$(RESET)"; \ docker exec -it ansible-controller bash;; \ test) \ echo "$(PURPLE)🧪 Запускаем полный цикл тестирования...$(RESET)"; \ $(MAKE) lab up; \ docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=$(MOLECULE_EPHEMERAL_DIRECTORY) ansible-controller \ bash -lc 'cd /ansible && molecule test -s $(SCENARIO)'; \ echo "$(GREEN)✅ Тестирование завершено$(RESET)";; \ create) \ echo "$(BLUE)🏗️ Создаем инфраструктуру...$(RESET)"; \ $(MAKE) lab up; \ docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=$(MOLECULE_EPHEMERAL_DIRECTORY) ansible-controller \ bash -lc 'cd /ansible && molecule create -s $(SCENARIO)'; \ echo "$(GREEN)✅ Инфраструктура создана$(RESET)";; \ converge) \ echo "$(YELLOW)⚙️ Запускаем роли...$(RESET)"; \ docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=$(MOLECULE_EPHEMERAL_DIRECTORY) ansible-controller \ bash -lc 'cd /ansible && molecule converge -s $(SCENARIO)'; \ echo "$(GREEN)✅ Роли выполнены$(RESET)";; \ verify) \ echo "$(CYAN)🔍 Проверяем работу лаборатории...$(RESET)"; \ docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=$(MOLECULE_EPHEMERAL_DIRECTORY) ansible-controller \ bash -lc 'cd /ansible && molecule verify -s $(SCENARIO)'; \ echo "$(GREEN)✅ Проверка завершена$(RESET)";; \ destroy) \ echo "$(RED)💥 Уничтожаем инфраструктуру...$(RESET)"; \ docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=$(MOLECULE_EPHEMERAL_DIRECTORY) ansible-controller \ bash -lc 'cd /ansible && molecule destroy -s $(SCENARIO)'; \ echo "$(GREEN)✅ Инфраструктура уничтожена$(RESET)";; \ reset) \ echo "$(PURPLE)🔄 Полный сброс лаборатории...$(RESET)"; \ $(MAKE) lab destroy; \ $(MAKE) lab down; \ $(MAKE) lab up; \ echo "$(GREEN)✅ Лаборатория сброшена$(RESET)";; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: up, down, sh, test, create, converge, verify, destroy, reset$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ KUBERNETES # ============================================================================= .PHONY: kube kube: ## Управление Kubernetes (sh|cmd|enter|kiali|istio|grafana|prom|pf-stop) @case "$(word 2, $(MAKECMDGOALS))" in \ sh) \ echo "$(BLUE)🐚 Входим в контейнер с kubectl...$(RESET)"; \ docker exec -it ansible-controller bash;; \ cmd) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube cmd CLUSTER=lab CMD=\"get pods -A\"$(RESET)"; \ exit 1; \ fi; \ echo "$(CYAN)🔧 Выполняем kubectl команду...$(RESET)"; \ docker exec -it ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) $(CMD)';; \ enter) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube enter CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)🚪 Входим в кластер...$(RESET)"; \ docker exec -it ansible-controller bash -lc '\ POD=$$(kubectl --context kind-$(CLUSTER) -n lab-demo get pod -l app=toolbox -o jsonpath="{.items[0].metadata.name}"); \ [ -n "$$POD" ] || { echo "toolbox pod not found"; exit 1; }; \ kubectl --context kind-$(CLUSTER) -n lab-demo exec -it $$POD -- /bin/sh';; \ kiali) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube kiali CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(PURPLE)🔮 Port-forward Kiali...$(RESET)"; \ docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/kiali 20001:20001'; \ echo "$(GREEN)✅ Kiali: http://localhost:20001$(RESET)";; \ istio) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube istio CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(PURPLE)🌐 Port-forward Istio Gateway...$(RESET)"; \ docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/istio-ingressgateway 8082:80 8444:443'; \ echo "$(GREEN)✅ Istio GW: http://localhost:8082 https://localhost:8444$(RESET)";; \ grafana) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube grafana CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)📊 Port-forward Grafana...$(RESET)"; \ docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-grafana 3000:80'; \ echo "$(GREEN)✅ Grafana: http://localhost:3000 (admin/admin)$(RESET)";; \ prom) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube prom CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)📈 Port-forward Prometheus...$(RESET)"; \ docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-kube-prometheus-prometheus 9090:9090'; \ echo "$(GREEN)✅ Prometheus: http://localhost:9090$(RESET)";; \ pf-stop) \ echo "$(RED)🛑 Останавливаем все port-forward...$(RESET)"; \ docker exec -it ansible-controller bash -lc 'pkill -f "kubectl .* port-forward" || true'; \ echo "$(GREEN)✅ Port-forward остановлены$(RESET)";; \ kubeconfig) \ if [ -z "$(CLUSTER)" ]; then \ echo "$(RED)❌ Использование: make kube kubeconfig CLUSTER=lab$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)📋 Получаем kubeconfig для кластера $(CLUSTER)...$(RESET)"; \ mkdir -p reports/kubeconfigs; \ docker exec ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) config view --raw' > reports/kubeconfigs/kubeconfig-$(CLUSTER).yaml; \ echo "$(GREEN)✅ Kubeconfig сохранен: reports/kubeconfigs/kubeconfig-$(CLUSTER).yaml$(RESET)";; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: sh, cmd, enter, kiali, istio, grafana, prom, pf-stop, kubeconfig$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ ПРЕСЕТАМИ # ============================================================================= .PHONY: preset preset: ## Управление пресетами (list|create|edit|test|copy) @case "$(word 2, $(MAKECMDGOALS))" in \ list) \ echo "$(CYAN)📋 Доступные пресеты:$(RESET)"; \ echo ""; \ echo "$(GREEN)Классические пресеты:$(RESET)"; \ echo " minimal.yml - Минимальная лаборатория (1-3 машины)"; \ echo " webapp.yml - Веб-приложение (3-5 машин)"; \ echo " microservices.yml - Микросервисы (5-8 машин)"; \ echo " ha.yml - Высокая доступность (6-10 машин)"; \ echo " k8s-cluster.yml - Kubernetes кластер (8-12 машин)"; \ echo " cicd.yml - CI/CD пайплайн (10-15 машин)"; \ echo " bigdata.yml - Big Data кластер (12-18 машин)"; \ echo " servicemesh.yml - Service Mesh (15-20 машин)"; \ echo " enterprise.yml - Enterprise (18-20 машин)"; \ echo " maximum.yml - Максимальный (20 машин)"; \ echo ""; \ echo "$(GREEN)Kubernetes пресеты:$(RESET)"; \ echo " k8s-single.yml - Kubernetes Single Node"; \ echo " k8s-multi.yml - Kubernetes Multi-Cluster"; \ echo " k8s-istio-full.yml - Kubernetes + Istio Full Stack"; \ echo ""; \ echo "$(GREEN)DinD пресеты:$(RESET)"; \ echo " dind-simple.yml - DinD Simple"; \ echo " dind-swarm.yml - DinD Swarm"; \ echo " dind-compose.yml - DinD Compose"; \ echo ""; \ echo "$(GREEN)DOoD пресеты:$(RESET)"; \ echo " dood-simple.yml - DOoD Simple"; \ echo " dood-mixed.yml - DOoD Mixed"; \ echo ""; \ echo "$(GREEN)Смешанные пресеты:$(RESET)"; \ echo " mixed-k8s-dind.yml - Mixed Kubernetes + DinD"; \ echo " mixed-k8s-dood.yml - Mixed Kubernetes + DOoD"; \ echo " mixed-full.yml - Mixed Full Stack";; \ create) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make preset create NAME=my-preset$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)📝 Создаем пресет: $(NAME).yml$(RESET)"; \ $(MAKE) preset copy SOURCE=minimal.yml TARGET=$(NAME).yml; \ echo "$(GREEN)✅ Пресет создан: molecule/presets/$(NAME).yml$(RESET)";; \ edit) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make preset edit NAME=my-preset$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)✏️ Редактируем пресет: $(NAME).yml$(RESET)"; \ $${EDITOR:-vim} molecule/presets/$(NAME).yml;; \ test) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make preset test NAME=my-preset$(RESET)"; \ exit 1; \ fi; \ echo "$(PURPLE)🧪 Тестируем пресет: $(NAME).yml$(RESET)"; \ $(MAKE) lab test LAB_SPEC=molecule/presets/$(NAME).yml;; \ copy) \ if [ -z "$(SOURCE)" ] || [ -z "$(TARGET)" ]; then \ echo "$(RED)❌ Использование: make preset copy SOURCE=minimal.yml TARGET=my-preset.yml$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)📋 Копируем пресет: $(SOURCE) -> $(TARGET)$(RESET)"; \ cp molecule/presets/$(SOURCE) molecule/presets/$(TARGET); \ echo "$(GREEN)✅ Пресет скопирован$(RESET)";; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: list, create, edit, test, copy$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ РОЛЯМИ # ============================================================================= .PHONY: role role: ## Управление ролями (list|create|edit|test|lint|deploy) @case "$(word 2, $(MAKECMDGOALS))" in \ list) \ echo "$(CYAN)📋 Доступные роли:$(RESET)"; \ if [ -d "$(ROLES_DIR)" ]; then \ ls -la $(ROLES_DIR)/ | grep "^d" | awk '{print " " $$9}' | grep -v "^\.$\|^\.\.$"; \ else \ echo " $(YELLOW)Директория ролей не найдена$(RESET)"; \ fi;; \ create) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make role create NAME=my-role$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)📝 Создаем роль: $(NAME)$(RESET)"; \ mkdir -p $(ROLES_DIR)/$(NAME)/{tasks,handlers,templates,files,vars,defaults,meta,tests}; \ echo "---" > $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "# Основные задачи роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "- name: Install package" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " package:" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " name: \"{{ package_name }}\"" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " state: present" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "- name: Start service" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " service:" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " name: \"{{ service_name }}\"" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " state: started" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo " enabled: true" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \ echo "---" > $(ROLES_DIR)/$(NAME)/defaults/main.yml; \ echo "# Переменные по умолчанию для роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \ echo "" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \ echo "package_name: nginx" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \ echo "service_name: nginx" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \ echo "$(GREEN)✅ Роль создана: $(ROLES_DIR)/$(NAME)/$(RESET)";; \ edit) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make role edit NAME=my-role$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)✏️ Редактируем роль: $(NAME)$(RESET)"; \ $${EDITOR:-vim} $(ROLES_DIR)/$(NAME)/tasks/main.yml;; \ test) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make role test NAME=my-role$(RESET)"; \ exit 1; \ fi; \ echo "$(PURPLE)🧪 Тестируем роль: $(NAME)$(RESET)"; \ $(MAKE) lab test LAB_SPEC=molecule/presets/minimal.yml;; \ lint) \ echo "$(YELLOW)🔍 Проверяем роли...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-lint --config-file /ansible/.ansible-lint $(ROLES_DIR)/*'; \ echo "$(GREEN)✅ Проверка завершена$(RESET)";; \ deploy) \ echo "$(PURPLE)🚀 Развертываем роли...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-playbook -i /tmp/molecule/inventory/hosts.yml files/playbooks/site.yml'; \ echo "$(GREEN)✅ Развертывание завершено$(RESET)";; \ info) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make role info NAME=my-role$(RESET)"; \ exit 1; \ fi; \ echo "$(BLUE)📋 Информация о роли: $(NAME)$(RESET)"; \ docker exec ansible-controller bash -lc 'cat /ansible/roles/$(NAME)/README.md';; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: list, create, edit, test, lint, deploy, info$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ VAULT # ============================================================================= .PHONY: vault vault: ## Управление Ansible Vault (show|create|edit|delete|rekey|decrypt|encrypt) @case "$(word 2, $(MAKECMDGOALS))" in \ show) \ echo "$(BLUE)🔍 Показываем содержимое vault...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-vault view --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ create) \ echo "$(YELLOW)📝 Создаем vault файл...$(RESET)"; \ docker exec ansible-controller bash -lc 'echo "---" > vault/secrets.yml && ansible-vault encrypt --encrypt-vault-id default --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ edit) \ echo "$(BLUE)✏️ Редактируем vault файл...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-vault edit --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ delete) \ echo "$(RED)🗑️ Удаляем vault файл...$(RESET)"; \ docker exec ansible-controller bash -lc 'rm vault/secrets.yml';; \ rekey) \ echo "$(YELLOW)🔑 Изменяем пароль vault...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-vault rekey --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ decrypt) \ echo "$(GREEN)🔓 Расшифровываем vault файл...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-vault decrypt --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ encrypt) \ echo "$(RED)🔒 Шифруем vault файл...$(RESET)"; \ docker exec ansible-controller bash -lc 'ansible-vault encrypt --encrypt-vault-id default --vault-password-file $(VAULT_PASSWORD_FILE) vault/secrets.yml';; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: show, create, edit, delete, rekey, decrypt, encrypt$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ GIT # ============================================================================= .PHONY: git git: ## Управление Git (status|add|commit|push|pull|branch|merge) @case "$(word 2, $(MAKECMDGOALS))" in \ status) \ echo "$(CYAN)📊 Статус Git репозитория:$(RESET)"; \ git status;; \ add) \ echo "$(GREEN)➕ Добавляем файлы в Git...$(RESET)"; \ git add .;; \ commit) \ if [ -z "$(MESSAGE)" ]; then \ echo "$(RED)❌ Использование: make git commit MESSAGE=\"your commit message\"$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)💾 Создаем коммит...$(RESET)"; \ git commit -m "$(MESSAGE)";; \ push) \ echo "$(BLUE)🚀 Отправляем изменения...$(RESET)"; \ git push;; \ pull) \ echo "$(GREEN)📥 Получаем изменения...$(RESET)"; \ git pull;; \ branch) \ if [ -z "$(NAME)" ]; then \ echo "$(RED)❌ Использование: make git branch NAME=my-branch$(RESET)"; \ exit 1; \ fi; \ echo "$(PURPLE)🌿 Создаем ветку: $(NAME)$(RESET)"; \ git checkout -b $(NAME);; \ merge) \ if [ -z "$(BRANCH)" ]; then \ echo "$(RED)❌ Использование: make git merge BRANCH=my-branch$(RESET)"; \ exit 1; \ fi; \ echo "$(YELLOW)🔀 Сливаем ветку: $(BRANCH)$(RESET)"; \ git merge $(BRANCH);; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: status, add, commit, push, pull, branch, merge$(RESET)";; \ esac # ============================================================================= # УПРАВЛЕНИЕ DOCKER # ============================================================================= .PHONY: docker docker: ## Управление Docker (build|rebuild|prune|shell|logs|stop|start) @case "$(word 2, $(MAKECMDGOALS))" in \ build) \ echo "$(YELLOW)🔨 Собираем Docker образы...$(RESET)"; \ $(DOCKER_COMPOSE) build;; \ rebuild) \ echo "$(YELLOW)🔨 Пересобираем Docker образы...$(RESET)"; \ $(DOCKER_COMPOSE) build --no-cache;; \ prune) \ echo "$(RED)🧹 Очищаем Docker...$(RESET)"; \ docker system prune -af;; \ shell) \ echo "$(BLUE)🐚 Входим в Docker контейнер...$(RESET)"; \ docker exec -it ansible-controller bash;; \ logs) \ echo "$(CYAN)📋 Показываем логи...$(RESET)"; \ $(DOCKER_COMPOSE) logs -f;; \ stop) \ echo "$(RED)🛑 Останавливаем контейнеры...$(RESET)"; \ $(DOCKER_COMPOSE) stop;; \ start) \ echo "$(GREEN)▶️ Запускаем контейнеры...$(RESET)"; \ $(DOCKER_COMPOSE) start;; \ *) \ echo "$(RED)❌ Неизвестная команда. Доступные: build, rebuild, prune, shell, logs, stop, start$(RESET)";; \ esac # ============================================================================= # ОТЧЕТЫ И МОНИТОРИНГ # ============================================================================= .PHONY: report report: ## Сгенерировать HTML отчет @echo "$(PURPLE)📊 Генерируем HTML отчет...$(RESET)" @mkdir -p reports @docker exec ansible-controller bash -lc 'python3 /ansible/scripts/report_html.py /ansible/reports/lab-health.json /ansible/reports/lab-report.html' @echo "$(GREEN)✅ HTML отчет: reports/lab-report.html$(RESET)" @echo "$(YELLOW)📖 Откройте отчет в браузере:$(RESET)" @echo " $(BLUE)file://$(PWD)/reports/lab-report.html$(RESET)" .PHONY: kubeconfigs kubeconfigs: ## Получить все kubeconfig файлы @echo "$(BLUE)📋 Получаем все kubeconfig файлы...$(RESET)" @mkdir -p reports/kubeconfigs @docker exec ansible-controller bash -lc 'for cluster in $$(kind get clusters 2>/dev/null || echo ""); do \ if [ -n "$$cluster" ]; then \ echo "Получаем kubeconfig для $$cluster..."; \ kubectl --context kind-$$cluster config view --raw > /ansible/reports/kubeconfigs/kubeconfig-$$cluster.yaml; \ fi; \ done' @echo "$(GREEN)✅ Kubeconfig файлы сохранены в reports/kubeconfigs/$(RESET)" @if [ -d "reports/kubeconfigs" ] && [ -n "$$(ls reports/kubeconfigs/ 2>/dev/null)" ]; then \ echo "$(YELLOW)📁 Найденные kubeconfig файлы:$(RESET)"; \ ls -la reports/kubeconfigs/ | grep -v "^total" | awk '{print " " $$9}'; \ fi .PHONY: open-report open-report: ## Открыть HTML отчет в браузере @if [ -f "reports/lab-report.html" ]; then \ echo "$(BLUE)🌐 Открываем отчет в браузере...$(RESET)"; \ if command -v open >/dev/null 2>&1; then \ open reports/lab-report.html; \ elif command -v xdg-open >/dev/null 2>&1; then \ xdg-open reports/lab-report.html; \ else \ echo "$(YELLOW)⚠️ Откройте отчет вручную: file://$(PWD)/reports/lab-report.html$(RESET)"; \ fi; \ echo "$(GREEN)✅ Отчет открыт$(RESET)"; \ else \ echo "$(RED)❌ Отчет не найден. Сначала выполните: make report$(RESET)"; \ fi .PHONY: full-test full-test: ## Полный цикл тестирования с отчетом и kubeconfig @echo "$(PURPLE)🚀 Запускаем полный цикл тестирования...$(RESET)" @$(MAKE) lab test @echo "$(BLUE)📊 Генерируем отчеты...$(RESET)" @$(MAKE) report @$(MAKE) kubeconfigs @echo "$(GREEN)✅ Полный цикл завершен!$(RESET)" @echo "$(YELLOW)📁 Результаты:$(RESET)" @echo " $(BLUE)📊 HTML отчет: reports/lab-report.html$(RESET)" @echo " $(BLUE)📋 Kubeconfig файлы: reports/kubeconfigs/$(RESET)" @echo "$(YELLOW)🌐 Открыть отчет: make open-report$(RESET)" .PHONY: chaos chaos: ## Запустить Chaos Engineering тесты @echo "$(RED)🧨 Запускаем Chaos Engineering...$(RESET)" @docker exec ansible-controller bash -lc 'ansible-playbook -i /tmp/molecule/inventory/hosts.yml /ansible/files/playbooks/chaos.yml' @echo "$(GREEN)✅ Chaos Engineering завершен$(RESET)" .PHONY: check-secrets check-secrets: ## Проверить безопасность секретов @echo "$(YELLOW)🔍 Проверяем безопасность секретов...$(RESET)" @docker exec ansible-controller bash -lc 'bash /ansible/scripts/secret_scan.sh' @echo "$(GREEN)✅ Проверка секретов завершена$(RESET)" .PHONY: idempotence idempotence: ## Проверить идемпотентность @echo "$(BLUE)🔄 Проверяем идемпотентность...$(RESET)" @docker exec ansible-controller bash -lc 'ansible-playbook -i /tmp/molecule/inventory/hosts.yml /ansible/files/playbooks/site.yml --check' @echo "$(GREEN)✅ Идемпотентность проверена$(RESET)" .PHONY: snapshot snapshot: ## Сохранить снапшот лаборатории @echo "$(YELLOW)📸 Создаем снапшот...$(RESET)" @docker exec ansible-controller bash -lc 'bash /ansible/scripts/snapshot.sh' @echo "$(GREEN)✅ Снапшот сохранен$(RESET)" .PHONY: restore restore: ## Восстановить из снапшота @echo "$(BLUE)🔄 Восстанавливаем из снапшота...$(RESET)" @docker exec ansible-controller bash -lc 'bash /ansible/scripts/restore.sh' @echo "$(GREEN)✅ Снапшот восстановлен$(RESET)" .PHONY: cleanup cleanup: ## Очистить лабораторию @echo "$(RED)🧹 Очищаем лабораторию...$(RESET)" @docker exec ansible-controller bash -lc 'bash /ansible/scripts/cleanup.sh' @echo "$(GREEN)✅ Лаборатория очищена$(RESET)" # ============================================================================= # УТИЛИТЫ # ============================================================================= .PHONY: lint lint: ## Проверить весь проект на ошибки @echo "$(YELLOW)🔍 Проверяем весь проект...$(RESET)" @docker exec ansible-controller bash -lc 'ansible-lint --config-file /ansible/.ansible-lint molecule/universal/' @docker exec ansible-controller bash -lc 'ansible-lint --config-file /ansible/.ansible-lint files/playbooks/' @if [ -d "$(ROLES_DIR)" ] && [ -n "$$(ls $(ROLES_DIR)/ 2>/dev/null)" ]; then \ docker exec ansible-controller bash -lc 'ansible-lint --config-file /ansible/.ansible-lint $(ROLES_DIR)/*'; \ fi @echo "$(GREEN)✅ Проверка завершена$(RESET)" .PHONY: env env: ## Показать переменные окружения @echo "$(CYAN)🔧 Переменные окружения:$(RESET)" @echo "PROJECT_NAME: $(PROJECT_NAME)" @echo "VERSION: $(VERSION)" @echo "AUTHOR: $(AUTHOR)" @echo "SITE: $(SITE)" @echo "DOCKER_IMAGE: $(DOCKER_IMAGE)" @echo "DOCKER_NETWORK: $(DOCKER_NETWORK)" @echo "SCENARIO: $(SCENARIO)" @echo "LAB_SPEC: $(LAB_SPEC)" @echo "KUBE_CONTEXT: $(KUBE_CONTEXT)" @echo "ROLES_DIR: $(ROLES_DIR)" @echo "VAULT_PASSWORD_FILE: $(VAULT_PASSWORD_FILE)" .PHONY: clean clean: cleanup ## Полная очистка проекта @echo "$(RED)🧹 Полная очистка проекта...$(RESET)" @rm -rf .env @rm -rf vault/ @rm -rf reports/ @rm -rf snapshots/ @echo "$(GREEN)✅ Проект очищен$(RESET)" # ============================================================================= # ЗАГЛУШКИ ДЛЯ ПАРАМЕТРОВ # ============================================================================= %: @: # ============================================================================= # ЗАГРУЗКА ПЕРЕМЕННЫХ ИЗ .env # ============================================================================= ifneq (,$(wildcard .env)) include .env export endif