Files
DevOpsLab/Makefile
Sergey Antropoff b1f681fb30 feat: Добавлена поддержка универсальных ролей для RHEL и Debian
- Роли теперь создаются универсальными для RHEL и Debian семейств
- Автоматическое создание OS-специфичных задач (debian.yml, redhat.yml)
- Универсальные playbooks с поддержкой разных ОС
- Обновлена документация с примерами и лучшими практиками

Новые возможности:
- Автоматическое определение ОС через ansible_os_family
- OS-специфичные задачи в отдельных файлах
- Универсальные playbooks с pre_tasks и post_tasks
- Поддержка apt для Debian/Ubuntu и yum для RHEL/CentOS

Структура универсальной роли:
- tasks/main.yml - общая логика и включение OS-специфичных задач
- tasks/debian.yml - задачи для Debian/Ubuntu (apt, systemd)
- tasks/redhat.yml - задачи для RHEL/CentOS (yum, systemd)
- playbooks/ - универсальные playbooks с поддержкой разных ОС

Универсальные playbooks:
- gather_facts: true - сбор информации об ОС
- pre_tasks - отображение информации об ОС
- post_tasks - проверка успешного развертывания
- Переменные роли автоматически добавляются

Документация:
- Добавлен раздел 'Универсальные роли' в docs/roles.md
- Примеры задач для Debian и RHEL семейств
- Лучшие практики для универсальных ролей
- Рекомендации по тестированию на разных ОС

Преимущества:
- Автоматическое создание универсальных ролей
- Поддержка RHEL и Debian семейств из коробки
- Лучшие практики встроены в шаблоны
- Подробная документация с примерами
- Приучение к написанию универсальных ролей

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

833 lines
44 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)"
@echo " $(CYAN)make lab <команда>$(RESET) - Управление лабораторией (up|down|test|destroy)"
@echo " $(CYAN)make kube <команда>$(RESET) - Управление Kubernetes (logs|exec|port-forward)"
@echo " $(CYAN)make preset <команда>$(RESET) - Управление пресетами (list|create|test)"
@echo " $(CYAN)make role <команда>$(RESET) - Управление ролями (list|create|test|lint|playbook)"
@echo " $(CYAN)make vault <команда>$(RESET) - Управление vault (view|create|edit|encrypt)"
@echo " $(CYAN)make report$(RESET) - Генерация HTML отчета"
@echo " $(CYAN)make lint$(RESET) - Проверка синтаксиса"
@echo " $(CYAN)make snapshot$(RESET) - Создание снимка лаборатории"
@echo " $(CYAN)make restore$(RESET) - Восстановление из снимка"
@echo " $(CYAN)make cleanup$(RESET) - Очистка всех данных"
@echo ""
@echo "$(YELLOW)Подробная документация: docs/$(RESET)"
# =============================================================================
# ИНИЦИАЛИЗАЦИЯ И НАСТРОЙКА
# =============================================================================
.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)"; \
echo "$(BLUE)🔧 Настройка роли...$(RESET)"; \
read -p "$(YELLOW)📝 Описание роли: $(RESET)" ROLE_DESC; \
read -p "$(YELLOW)📦 Основной пакет (по умолчанию: $(NAME)): $(RESET)" ROLE_PACKAGE; \
ROLE_PACKAGE=$${ROLE_PACKAGE:-$(NAME)}; \
read -p "$(YELLOW)🔧 Сервис (по умолчанию: $(NAME)): $(RESET)" ROLE_SERVICE; \
ROLE_SERVICE=$${ROLE_SERVICE:-$(NAME)}; \
read -p "$(YELLOW)📋 Платформы (ubuntu,centos,rhel) через запятую: $(RESET)" ROLE_PLATFORMS; \
ROLE_PLATFORMS=$${ROLE_PLATFORMS:-ubuntu,centos}; \
read -p "$(YELLOW)🏷️ Теги через запятую: $(RESET)" ROLE_TAGS; \
ROLE_TAGS=$${ROLE_TAGS:-$(NAME)}; \
echo "$(BLUE)📁 Создаем структуру роли...$(RESET)"; \
mkdir -p $(ROLES_DIR)/$(NAME)/{tasks,handlers,templates,files,vars,defaults,meta,tests,playbooks}; \
echo "$(BLUE)📝 Создаем основные файлы...$(RESET)"; \
echo "---" > $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "# Основные задачи роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "- name: $(NAME) placeholder" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo " debug:" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo " msg: \"Роль $(NAME) готова для настройки\"" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "- name: Include OS-specific tasks" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo " include_tasks: \"{{ ansible_os_family | lower }}.yml\"" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "- name: Start $(NAME) service" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo " systemd:" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo " name: \"{{ $(NAME)_service | default('$(ROLE_SERVICE)') }}\"" >> $(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 " when: $(NAME)_service is defined" >> $(ROLES_DIR)/$(NAME)/tasks/main.yml; \
echo "---" > $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "# Задачи для Debian/Ubuntu семейства" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "- name: Update apt cache (Debian)" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " apt:" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " update_cache: true" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " cache_valid_time: 3600" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " when: ansible_os_family == 'Debian'" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "- name: Install $(NAME) package (Debian)" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " apt:" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " name: \"{{ $(NAME)_package | default('$(ROLE_PACKAGE)') }}\"" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " state: present" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo " when: ansible_os_family == 'Debian'" >> $(ROLES_DIR)/$(NAME)/tasks/debian.yml; \
echo "---" > $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "# Задачи для RHEL/CentOS семейства" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "- name: Update yum cache (RHEL)" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " yum:" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " update_cache: true" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " when: ansible_os_family == 'RedHat'" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "- name: Install $(NAME) package (RHEL)" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " yum:" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " name: \"{{ $(NAME)_package | default('$(ROLE_PACKAGE)') }}\"" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " state: present" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo " when: ansible_os_family == 'RedHat'" >> $(ROLES_DIR)/$(NAME)/tasks/redhat.yml; \
echo "---" > $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "# Переменные по умолчанию для роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "$(NAME)_enabled: true" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "$(NAME)_package: $(ROLE_PACKAGE)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "$(NAME)_service: $(ROLE_SERVICE)" >> $(ROLES_DIR)/$(NAME)/defaults/main.yml; \
echo "---" > $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo "galaxy_info:" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " author: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " description: $(ROLE_DESC)" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " company: $(SITE)" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " license: MIT" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " min_ansible_version: 2.9" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " platforms:" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " - name: Ubuntu" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " versions: [focal, jammy]" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " - name: CentOS" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " versions: [7, 8, 9]" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " - name: RHEL" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " versions: [7, 8, 9]" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo " galaxy_tags: [$(ROLE_TAGS)]" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo "dependencies: []" >> $(ROLES_DIR)/$(NAME)/meta/main.yml; \
echo "---" > $(ROLES_DIR)/$(NAME)/README.md; \
echo "# Роль $(NAME)" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "$(ROLE_DESC)" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "## Переменные" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "| Переменная | По умолчанию | Описание |" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "|------------|--------------|----------|" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "| \`$(NAME)_enabled\` | \`true\` | Включить роль |" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "| \`$(NAME)_package\` | \`$(ROLE_PACKAGE)\` | Имя пакета |" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "| \`$(NAME)_service\` | \`$(ROLE_SERVICE)\` | Имя сервиса |" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "## Использование" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "\`\`\`yaml" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "- hosts: all" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo " roles:" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo " - role: $(NAME)" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "\`\`\`" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "## Автор" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "$(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/README.md; \
echo "$(GREEN)✅ Роль $(NAME) создана$(RESET)"; \
echo "$(BLUE)📁 Структура: $(ROLES_DIR)/$(NAME)/$(RESET)"; \
echo "$(BLUE)📝 Основной файл: $(ROLES_DIR)/$(NAME)/tasks/main.yml$(RESET)"; \
echo "$(BLUE)📋 Playbooks: $(ROLES_DIR)/$(NAME)/playbooks/$(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';; \
playbook) \
if [ -z "$(NAME)" ]; then \
echo "$(RED)❌ Использование: make role playbook NAME=my-role$(RESET)"; \
exit 1; \
fi; \
echo "$(BLUE)📋 Управление playbooks для роли: $(NAME)$(RESET)"; \
echo "$(YELLOW)Доступные команды:$(RESET)"; \
echo " $(CYAN)create$(RESET) - Создать новый playbook"; \
echo " $(CYAN)list$(RESET) - Список playbooks"; \
echo " $(CYAN)edit$(RESET) - Редактировать playbook"; \
echo " $(CYAN)run$(RESET) - Запустить playbook"; \
read -p "$(YELLOW)Выберите команду: $(RESET)" PLAYBOOK_CMD; \
case "$$PLAYBOOK_CMD" in \
create) \
read -p "$(YELLOW)📝 Имя playbook: $(RESET)" PLAYBOOK_NAME; \
if [ -z "$$PLAYBOOK_NAME" ]; then \
echo "$(RED)❌ Имя playbook обязательно$(RESET)"; \
exit 1; \
fi; \
echo "---" > $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "# Playbook: $$PLAYBOOK_NAME для роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "- name: $$PLAYBOOK_NAME" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " hosts: all" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " become: true" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " gather_facts: true" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " vars:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " # Переменные для роли $(NAME)" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " $(NAME)_enabled: true" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " pre_tasks:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " - name: Display OS information" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " debug:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " msg: \"OS Family: {{ ansible_os_family }}, OS: {{ ansible_distribution }} {{ ansible_distribution_version }}\"" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " roles:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " - role: $(NAME)" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " post_tasks:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " - name: Verify $(NAME) installation" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " debug:" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo " msg: \"$(NAME) successfully deployed on {{ inventory_hostname }}\"" >> $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
echo "$(GREEN)✅ Playbook $$PLAYBOOK_NAME создан$(RESET)";; \
list) \
echo "$(CYAN)📋 Playbooks для роли $(NAME):$(RESET)"; \
if [ -d "$(ROLES_DIR)/$(NAME)/playbooks" ]; then \
ls -la $(ROLES_DIR)/$(NAME)/playbooks/*.yml 2>/dev/null | awk '{print " " $$9}' || echo " $(YELLOW)Нет playbooks$(RESET)"; \
else \
echo " $(YELLOW)Директория playbooks не найдена$(RESET)"; \
fi;; \
edit) \
read -p "$(YELLOW)📝 Имя playbook для редактирования: $(RESET)" PLAYBOOK_NAME; \
if [ -f "$(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml" ]; then \
$${EDITOR:-vim} $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml; \
else \
echo "$(RED)❌ Playbook $$PLAYBOOK_NAME не найден$(RESET)"; \
fi;; \
run) \
read -p "$(YELLOW)📝 Имя playbook для запуска: $(RESET)" PLAYBOOK_NAME; \
if [ -f "$(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml" ]; then \
echo "$(BLUE)🚀 Запускаем playbook: $$PLAYBOOK_NAME$(RESET)"; \
docker exec ansible-controller bash -lc "ansible-playbook -i /tmp/molecule/inventory/hosts.yml $(ROLES_DIR)/$(NAME)/playbooks/$$PLAYBOOK_NAME.yml"; \
else \
echo "$(RED)❌ Playbook $$PLAYBOOK_NAME не найден$(RESET)"; \
fi;; \
*) \
echo "$(RED)❌ Неизвестная команда playbook$(RESET)";; \
esac;; \
*) \
echo "$(RED)❌ Неизвестная команда. Доступные: list, create, edit, test, lint, deploy, info, playbook$(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