Files
DevOpsLab/Makefile
Sergey Antropoff 51c76fb859 feat: Создана роль deploy для управления инфраструктурой
- Создана полноценная роль deploy в roles/deploy/
- Перенесена логика развертывания из site.yml в роль
- Обновлен site.yml для использования роли deploy
- Добавлена поддержка условного развертывания по группам

Структура роли deploy:
- tasks/main.yml - основные задачи
- tasks/etcd.yml - развертывание ETCD
- tasks/patroni.yml - развертывание Patroni
- tasks/haproxy.yml - развертывание HAProxy
- tasks/apps.yml - развертывание приложений
- tasks/dind-stack.yml - развертывание DinD стека
- templates/haproxy.cfg.j2 - конфигурация HAProxy
- templates/docker-compose.yml.j2 - конфигурация DinD стека
- handlers/main.yml - обработчики сервисов
- defaults/main.yml - переменные по умолчанию
- vars/main.yml - переменные роли
- meta/main.yml - метаданные роли
- README.md - документация роли

Обновления в site.yml:
- Упрощен до базовой установки common tools
- Добавлена роль deploy с условным развертыванием
- Поддержка развертывания по группам (etcd, patroni, haproxy, apps)

Новые команды:
- make role info NAME=deploy - информация о роли
- make role deploy - развертывание ролей с inventory

Преимущества:
- Модульная архитектура с разделением ответственности
- Условное развертывание по группам хостов
- Переиспользуемые компоненты (ETCD, Patroni, HAProxy)
- Шаблоны для конфигурации сервисов
- Обработчики для перезапуска сервисов
- Подробная документация роли

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-10-22 14:18:49 +03:00

675 lines
32 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# =============================================================================
# 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