- Создано главное интерактивное меню с 13 разделами - Добавлено интерактивное меню помощи с 6 подразделами - Команда по умолчанию (make) теперь запускает главное меню - Создано интерактивное создание playbooks - Исправлены ошибки с return/exit в меню Интерактивные меню: - 🧪 Управление лабораторией (8 команд) - ☸️ Управление Kubernetes (7 команд) - 📋 Управление пресетами (6 команд) - 🎭 Управление ролями (8 команд) - 🔐 Управление vault (5 команд) - 📊 Генерация отчетов (4 команды) - 🔍 Проверка синтаксиса (5 команд) - 📸 Снимки лаборатории (3 команды) - 🧹 Очистка данных (5 команд) - 🎯 Интерактивные команды (3 команды) - 📚 Документация (6 разделов) - ❓ Помощь и справка (6 разделов) Меню помощи включает: - 📋 Обзор проекта - 🚀 Быстрый старт - ⌨️ Список команд - 💡 Примеры использования - 🔧 Решение проблем - ℹ️ О проекте Преимущества: - Полноценный TUI интерфейс - Навигация через меню - Красивые диалоги с эмодзи - Подробная справка - Минимум ручного труда - Удобство использования Автор: Сергей Антропов Сайт: https://devops.org.ru
1470 lines
82 KiB
Makefile
1470 lines
82 KiB
Makefile
# =============================================================================
|
||
# 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
|
||
|
||
# =============================================================================
|
||
# ОСНОВНЫЕ КОМАНДЫ
|
||
# =============================================================================
|
||
|
||
# Команда по умолчанию - интерактивное меню
|
||
.DEFAULT_GOAL := menu
|
||
|
||
.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 "$(GREEN)Интерактивные команды:$(RESET)"
|
||
@echo " $(CYAN)make preset-create-interactive$(RESET) - Интерактивное создание пресета"
|
||
@echo " $(CYAN)make role-create-interactive$(RESET) - Интерактивное создание роли"
|
||
@echo ""
|
||
@echo "$(YELLOW)Подробная документация: docs/$(RESET)"
|
||
|
||
.PHONY: menu
|
||
menu: check-whiptail ## Интерактивное главное меню
|
||
@while true; do \
|
||
CHOICE=$$(whiptail --title "Ansible Template - Универсальная лаборатория" \
|
||
--menu "Выберите действие:" 20 60 13 \
|
||
"lab" "🧪 Управление лабораторией" \
|
||
"kube" "☸️ Управление Kubernetes" \
|
||
"preset" "📋 Управление пресетами" \
|
||
"role" "🎭 Управление ролями" \
|
||
"vault" "🔐 Управление vault" \
|
||
"report" "📊 Генерация отчетов" \
|
||
"lint" "🔍 Проверка синтаксиса" \
|
||
"snapshot" "📸 Снимки лаборатории" \
|
||
"cleanup" "🧹 Очистка данных" \
|
||
"interactive" "🎯 Интерактивные команды" \
|
||
"docs" "📚 Документация" \
|
||
"help" "❓ Помощь и справка" \
|
||
"exit" "🚪 Выход" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "exit" ]; then \
|
||
echo "$(YELLOW)👋 До свидания!$(RESET)"; \
|
||
break; \
|
||
fi; \
|
||
case "$$CHOICE" in \
|
||
"lab") make menu-lab;; \
|
||
"kube") make menu-kube;; \
|
||
"preset") make menu-preset;; \
|
||
"role") make menu-role;; \
|
||
"vault") make menu-vault;; \
|
||
"report") make menu-report;; \
|
||
"lint") make menu-lint;; \
|
||
"snapshot") make menu-snapshot;; \
|
||
"cleanup") make menu-cleanup;; \
|
||
"interactive") make menu-interactive;; \
|
||
"docs") make menu-docs;; \
|
||
"help") make menu-help;; \
|
||
esac; \
|
||
done
|
||
|
||
# =============================================================================
|
||
# ИНТЕРАКТИВНЫЕ МЕНЮ
|
||
# =============================================================================
|
||
|
||
.PHONY: menu-lab
|
||
menu-lab: check-whiptail ## Меню управления лабораторией
|
||
@CHOICE=$$(whiptail --title "🧪 Управление лабораторией" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"up" "🚀 Запустить лабораторию" \
|
||
"down" "🛑 Остановить лабораторию" \
|
||
"test" "🧪 Тестировать лабораторию" \
|
||
"destroy" "💥 Уничтожить лабораторию" \
|
||
"status" "📊 Статус лаборатории" \
|
||
"logs" "📝 Просмотр логов" \
|
||
"shell" "🐚 Подключиться к контейнеру" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"up") make lab up;; \
|
||
"down") make lab down;; \
|
||
"test") make lab test;; \
|
||
"destroy") make lab destroy;; \
|
||
"status") make lab status;; \
|
||
"logs") make lab logs;; \
|
||
"shell") make lab shell;; \
|
||
esac
|
||
|
||
.PHONY: menu-kube
|
||
menu-kube: check-whiptail ## Меню управления Kubernetes
|
||
@CHOICE=$$(whiptail --title "☸️ Управление Kubernetes" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"logs" "📝 Просмотр логов" \
|
||
"exec" "🐚 Выполнить команду" \
|
||
"port-forward" "🔗 Проброс портов" \
|
||
"kiali" "🔍 Kiali Dashboard" \
|
||
"istio" "🌐 Istio Gateway" \
|
||
"grafana" "📊 Grafana Dashboard" \
|
||
"prometheus" "📈 Prometheus" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"logs") make kube logs;; \
|
||
"exec") make kube exec;; \
|
||
"port-forward") make kube port-forward;; \
|
||
"kiali") make kube kiali;; \
|
||
"istio") make kube istio;; \
|
||
"grafana") make kube grafana;; \
|
||
"prometheus") make kube prometheus;; \
|
||
esac
|
||
|
||
.PHONY: menu-preset
|
||
menu-preset: check-whiptail ## Меню управления пресетами
|
||
@CHOICE=$$(whiptail --title "📋 Управление пресетами" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"list" "📋 Список пресетов" \
|
||
"create" "➕ Создать пресет" \
|
||
"edit" "✏️ Редактировать пресет" \
|
||
"test" "🧪 Тестировать пресет" \
|
||
"copy" "📋 Копировать пресет" \
|
||
"interactive" "🎯 Интерактивное создание" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"list") make preset list;; \
|
||
"create") make preset create;; \
|
||
"edit") make preset edit;; \
|
||
"test") make preset test;; \
|
||
"copy") make preset copy;; \
|
||
"interactive") make preset-create-interactive;; \
|
||
esac
|
||
|
||
.PHONY: menu-role
|
||
menu-role: check-whiptail ## Меню управления ролями
|
||
@CHOICE=$$(whiptail --title "🎭 Управление ролями" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"list" "📋 Список ролей" \
|
||
"create" "➕ Создать роль" \
|
||
"edit" "✏️ Редактировать роль" \
|
||
"test" "🧪 Тестировать роль" \
|
||
"lint" "🔍 Проверка синтаксиса" \
|
||
"deploy" "🚀 Развертывание ролей" \
|
||
"playbook" "📝 Управление playbooks" \
|
||
"interactive" "🎯 Интерактивное создание" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"list") make role list;; \
|
||
"create") make role create;; \
|
||
"edit") make role edit;; \
|
||
"test") make role test;; \
|
||
"lint") make role lint;; \
|
||
"deploy") make role deploy;; \
|
||
"playbook") make role playbook;; \
|
||
"interactive") make role-create-interactive;; \
|
||
esac
|
||
|
||
.PHONY: menu-vault
|
||
menu-vault: check-whiptail ## Меню управления vault
|
||
@CHOICE=$$(whiptail --title "🔐 Управление vault" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"view" "👁️ Просмотр секретов" \
|
||
"create" "➕ Создать секрет" \
|
||
"edit" "✏️ Редактировать секрет" \
|
||
"encrypt" "🔒 Зашифровать файл" \
|
||
"decrypt" "🔓 Расшифровать файл" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"view") make vault view;; \
|
||
"create") make vault create;; \
|
||
"edit") make vault edit;; \
|
||
"encrypt") make vault encrypt;; \
|
||
"decrypt") make vault decrypt;; \
|
||
esac
|
||
|
||
.PHONY: menu-report
|
||
menu-report: check-whiptail ## Меню генерации отчетов
|
||
@CHOICE=$$(whiptail --title "📊 Генерация отчетов" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"html" "📄 HTML отчет" \
|
||
"json" "📋 JSON отчет" \
|
||
"health" "🏥 Отчет о здоровье" \
|
||
"topology" "🗺️ Топология сети" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"html") make report;; \
|
||
"json") make report-json;; \
|
||
"health") make health-report;; \
|
||
"topology") make topology;; \
|
||
esac
|
||
|
||
.PHONY: menu-lint
|
||
menu-lint: check-whiptail ## Меню проверки синтаксиса
|
||
@CHOICE=$$(whiptail --title "🔍 Проверка синтаксиса" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"all" "🔍 Проверить все" \
|
||
"roles" "🎭 Проверить роли" \
|
||
"playbooks" "📝 Проверить playbooks" \
|
||
"vault" "🔐 Проверить vault" \
|
||
"secrets" "🔍 Проверить секреты" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"all") make lint;; \
|
||
"roles") make role lint;; \
|
||
"playbooks") make lint-playbooks;; \
|
||
"vault") make lint-vault;; \
|
||
"secrets") make check-secrets;; \
|
||
esac
|
||
|
||
.PHONY: menu-snapshot
|
||
menu-snapshot: check-whiptail ## Меню снимков лаборатории
|
||
@CHOICE=$$(whiptail --title "📸 Снимки лаборатории" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"create" "📸 Создать снимок" \
|
||
"restore" "🔄 Восстановить снимок" \
|
||
"list" "📋 Список снимков" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"create") make snapshot;; \
|
||
"restore") make restore;; \
|
||
"list") make snapshot-list;; \
|
||
esac
|
||
|
||
.PHONY: menu-cleanup
|
||
menu-cleanup: check-whiptail ## Меню очистки данных
|
||
@CHOICE=$$(whiptail --title "🧹 Очистка данных" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"all" "🧹 Очистить все" \
|
||
"containers" "🐳 Очистить контейнеры" \
|
||
"images" "🖼️ Очистить образы" \
|
||
"volumes" "💾 Очистить тома" \
|
||
"reports" "📊 Очистить отчеты" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"all") make cleanup;; \
|
||
"containers") make cleanup-containers;; \
|
||
"images") make cleanup-images;; \
|
||
"volumes") make cleanup-volumes;; \
|
||
"reports") make cleanup-reports;; \
|
||
esac
|
||
|
||
.PHONY: menu-interactive
|
||
menu-interactive: check-whiptail ## Меню интерактивных команд
|
||
@CHOICE=$$(whiptail --title "🎯 Интерактивные команды" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"preset" "📋 Создать пресет" \
|
||
"role" "🎭 Создать роль" \
|
||
"playbook" "📝 Создать playbook" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"preset") make preset-create-interactive;; \
|
||
"role") make role-create-interactive;; \
|
||
"playbook") make playbook-create-interactive;; \
|
||
esac
|
||
|
||
.PHONY: menu-docs
|
||
menu-docs: check-whiptail ## Меню документации
|
||
@CHOICE=$$(whiptail --title "📚 Документация" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"readme" "📖 README" \
|
||
"lab" "🧪 Универсальная лаборатория" \
|
||
"presets" "📋 Пресеты" \
|
||
"roles" "🎭 Роли" \
|
||
"examples" "💡 Примеры" \
|
||
"api" "🔧 API Reference" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"readme") cat README.md | less;; \
|
||
"lab") cat docs/universal-lab.md | less;; \
|
||
"presets") cat docs/presets.md | less;; \
|
||
"roles") cat docs/roles.md | less;; \
|
||
"examples") cat docs/examples.md | less;; \
|
||
"api") cat docs/api.md | less;; \
|
||
esac
|
||
|
||
.PHONY: menu-help
|
||
menu-help: check-whiptail ## Меню помощи и справки
|
||
@CHOICE=$$(whiptail --title "❓ Помощь и справка" \
|
||
--menu "Выберите действие:" 15 50 8 \
|
||
"overview" "📋 Обзор проекта" \
|
||
"quickstart" "🚀 Быстрый старт" \
|
||
"commands" "⌨️ Список команд" \
|
||
"examples" "💡 Примеры использования" \
|
||
"troubleshooting" "🔧 Решение проблем" \
|
||
"about" "ℹ️ О проекте" \
|
||
"back" "⬅️ Назад" \
|
||
3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ] || [ "$$CHOICE" = "back" ]; then exit 0; fi; \
|
||
case "$$CHOICE" in \
|
||
"overview") \
|
||
whiptail --title "📋 Обзор проекта" \
|
||
--msgbox "Ansible Template - Универсальная лаборатория для тестирования Ansible ролей и playbooks.\n\nОсновные возможности:\n• 🧪 Универсальная лаборатория с Docker\n• ☸️ Kubernetes кластеры (Kind)\n• 📋 Готовые пресеты для разных сценариев\n• 🎭 Управление Ansible ролями\n• 🔐 Безопасное хранение секретов\n• 📊 Генерация отчетов\n• 🎯 Интерактивные команды\n\nАвтор: $(AUTHOR)\nСайт: $(SITE)" 20 70;; \
|
||
"quickstart") \
|
||
whiptail --title "🚀 Быстрый старт" \
|
||
--msgbox "Быстрый старт:\n\n1. Инициализация проекта:\n make init\n\n2. Запуск лаборатории:\n make lab up\n\n3. Создание роли:\n make role-create-interactive\n\n4. Создание пресета:\n make preset-create-interactive\n\n5. Генерация отчета:\n make report\n\nВсе команды доступны через интерактивное меню!" 20 70;; \
|
||
"commands") \
|
||
whiptail --title "⌨️ Список команд" \
|
||
--msgbox "Основные команды:\n\n• make - Главное меню\n• make help - Справка\n• make init - Инициализация\n• make lab up - Запуск лаборатории\n• make lab down - Остановка\n• make lab test - Тестирование\n• make role list - Список ролей\n• make preset list - Список пресетов\n• make vault view - Просмотр секретов\n• make report - Генерация отчета\n• make lint - Проверка синтаксиса\n• make cleanup - Очистка данных" 20 70;; \
|
||
"examples") \
|
||
whiptail --title "💡 Примеры использования" \
|
||
--msgbox "Примеры использования:\n\n1. Создание роли nginx:\n make role-create-interactive\n\n2. Создание пресета для 5 хостов:\n make preset-create-interactive\n\n3. Запуск лаборатории с пресетом:\n make lab up PRESET=my-preset\n\n4. Тестирование роли:\n make role test NAME=nginx\n\n5. Генерация HTML отчета:\n make report" 20 70;; \
|
||
"troubleshooting") \
|
||
whiptail --title "🔧 Решение проблем" \
|
||
--msgbox "Решение проблем:\n\n• whiptail не найден:\n make check-whiptail\n\n• Docker не запускается:\n make lab down && make lab up\n\n• Проблемы с vault:\n make vault view\n\n• Очистка всех данных:\n make cleanup\n\n• Проверка синтаксиса:\n make lint\n\n• Просмотр логов:\n make lab logs" 20 70;; \
|
||
"about") \
|
||
whiptail --title "ℹ️ О проекте" \
|
||
--msgbox "Ansible Template v$(VERSION)\n\nУниверсальная лаборатория для тестирования Ansible ролей и playbooks с поддержкой Docker, Kubernetes, и множества готовых пресетов.\n\nАвтор: $(AUTHOR)\nСайт: $(SITE)\nЛицензия: MIT\n\nОсобенности:\n• 🎯 Интерактивный интерфейс\n• 🧪 Универсальная лаборатория\n• ☸️ Kubernetes поддержка\n• 📋 21 готовый пресет\n• 🔐 Безопасность vault\n• 📊 Красивые отчеты" 20 70;; \
|
||
esac
|
||
|
||
# =============================================================================
|
||
# ИНИЦИАЛИЗАЦИЯ И НАСТРОЙКА
|
||
# =============================================================================
|
||
|
||
.PHONY: check-whiptail
|
||
check-whiptail: ## Проверить и установить whiptail
|
||
@if ! command -v whiptail >/dev/null 2>&1; then \
|
||
echo "$(YELLOW)🔧 whiptail не найден, устанавливаем...$(RESET)"; \
|
||
if command -v brew >/dev/null 2>&1; then \
|
||
echo "$(BLUE)🍺 Устанавливаем через Homebrew...$(RESET)"; \
|
||
brew install newt; \
|
||
elif command -v apt-get >/dev/null 2>&1; then \
|
||
echo "$(BLUE)📦 Устанавливаем через apt-get...$(RESET)"; \
|
||
sudo apt-get update && sudo apt-get install -y whiptail; \
|
||
elif command -v yum >/dev/null 2>&1; then \
|
||
echo "$(BLUE)📦 Устанавливаем через yum...$(RESET)"; \
|
||
sudo yum install -y newt; \
|
||
elif command -v dnf >/dev/null 2>&1; then \
|
||
echo "$(BLUE)📦 Устанавливаем через dnf...$(RESET)"; \
|
||
sudo dnf install -y newt; \
|
||
elif command -v pacman >/dev/null 2>&1; then \
|
||
echo "$(BLUE)📦 Устанавливаем через pacman...$(RESET)"; \
|
||
sudo pacman -S --noconfirm libnewt; \
|
||
elif command -v zypper >/dev/null 2>&1; then \
|
||
echo "$(BLUE)📦 Устанавливаем через zypper...$(RESET)"; \
|
||
sudo zypper install -y newt; \
|
||
else \
|
||
echo "$(RED)❌ Не удалось определить пакетный менеджер для установки whiptail$(RESET)"; \
|
||
echo "$(YELLOW)📖 Установите whiptail вручную для вашей ОС$(RESET)"; \
|
||
exit 1; \
|
||
fi; \
|
||
if command -v whiptail >/dev/null 2>&1; then \
|
||
echo "$(GREEN)✅ whiptail успешно установлен$(RESET)"; \
|
||
else \
|
||
echo "$(RED)❌ Ошибка установки whiptail$(RESET)"; \
|
||
exit 1; \
|
||
fi; \
|
||
else \
|
||
echo "$(GREEN)✅ whiptail уже установлен$(RESET)"; \
|
||
fi
|
||
|
||
.PHONY: init
|
||
init: check-whiptail setup-env-interactive setup-vault setup-roles setup-precommit ## Полная инициализация проекта
|
||
@echo "$(GREEN)✅ Проект успешно инициализирован!$(RESET)"
|
||
@echo "$(YELLOW)📖 Документация: $(SITE)$(RESET)"
|
||
@echo "$(YELLOW)🚀 Быстрый старт: make lab up$(RESET)"
|
||
|
||
.PHONY: setup-env-interactive
|
||
setup-env-interactive: ## Интерактивное создание .env файла
|
||
@if [ ! -f $(ENV_FILE) ]; then \
|
||
echo "$(CYAN)🔧 Настройка проекта Ansible Template$(RESET)"; \
|
||
echo "$(YELLOW)📝 Заполните параметры проекта (можно оставить пустыми для значений по умолчанию):$(RESET)"; \
|
||
echo ""; \
|
||
read -p "$(YELLOW)📦 Название проекта [$(PROJECT_NAME)]: $(RESET)" USER_PROJECT_NAME; \
|
||
USER_PROJECT_NAME=$${USER_PROJECT_NAME:-$(PROJECT_NAME)}; \
|
||
read -p "$(YELLOW)📋 Версия проекта [$(VERSION)]: $(RESET)" USER_VERSION; \
|
||
USER_VERSION=$${USER_VERSION:-$(VERSION)}; \
|
||
read -p "$(YELLOW)👤 Автор проекта [Сергей Антропов]: $(RESET)" USER_AUTHOR; \
|
||
USER_AUTHOR=$${USER_AUTHOR:-Сергей Антропов}; \
|
||
read -p "$(YELLOW)🌐 Сайт проекта [https://devops.org.ru]: $(RESET)" USER_SITE; \
|
||
USER_SITE=$${USER_SITE:-https://devops.org.ru}; \
|
||
echo ""; \
|
||
echo "$(BLUE)🐳 Настройки Docker:$(RESET)"; \
|
||
read -p "$(YELLOW)🐳 Docker образ [$(DOCKER_IMAGE)]: $(RESET)" USER_DOCKER_IMAGE; \
|
||
USER_DOCKER_IMAGE=$${USER_DOCKER_IMAGE:-$(DOCKER_IMAGE)}; \
|
||
read -p "$(YELLOW)🌐 Docker сеть [$(DOCKER_NETWORK)]: $(RESET)" USER_DOCKER_NETWORK; \
|
||
USER_DOCKER_NETWORK=$${USER_DOCKER_NETWORK:-$(DOCKER_NETWORK)}; \
|
||
echo ""; \
|
||
echo "$(BLUE)🧪 Настройки лаборатории:$(RESET)"; \
|
||
read -p "$(YELLOW)📋 Сценарий Molecule [$(SCENARIO)]: $(RESET)" USER_SCENARIO; \
|
||
USER_SCENARIO=$${USER_SCENARIO:-$(SCENARIO)}; \
|
||
read -p "$(YELLOW)📄 Пресет лаборатории [$(LAB_SPEC)]: $(RESET)" USER_LAB_SPEC; \
|
||
USER_LAB_SPEC=$${USER_LAB_SPEC:-$(LAB_SPEC)}; \
|
||
echo ""; \
|
||
echo "$(BLUE)☸️ Настройки Kubernetes:$(RESET)"; \
|
||
read -p "$(YELLOW)☸️ Kubernetes контекст [$(KUBE_CONTEXT)]: $(RESET)" USER_KUBE_CONTEXT; \
|
||
USER_KUBE_CONTEXT=$${USER_KUBE_CONTEXT:-$(KUBE_CONTEXT)}; \
|
||
read -p "$(YELLOW)🔗 Версия Istio [$(ISTIO_VERSION)]: $(RESET)" USER_ISTIO_VERSION; \
|
||
USER_ISTIO_VERSION=$${USER_ISTIO_VERSION:-$(ISTIO_VERSION)}; \
|
||
read -p "$(YELLOW)☸️ Версия Kind [$(KIND_VERSION)]: $(RESET)" USER_KIND_VERSION; \
|
||
USER_KIND_VERSION=$${USER_KIND_VERSION:-$(KIND_VERSION)}; \
|
||
echo ""; \
|
||
echo "$(BLUE)📁 Настройки путей:$(RESET)"; \
|
||
read -p "$(YELLOW)📁 Папка ролей [$(ROLES_DIR)]: $(RESET)" USER_ROLES_DIR; \
|
||
USER_ROLES_DIR=$${USER_ROLES_DIR:-$(ROLES_DIR)}; \
|
||
read -p "$(YELLOW)🔐 Файл пароля vault [$(VAULT_PASSWORD_FILE)]: $(RESET)" USER_VAULT_PASSWORD_FILE; \
|
||
USER_VAULT_PASSWORD_FILE=$${USER_VAULT_PASSWORD_FILE:-$(VAULT_PASSWORD_FILE)}; \
|
||
echo ""; \
|
||
echo "$(BLUE)📝 Создание .env файла...$(RESET)"; \
|
||
echo "# Ansible Template Environment" > $(ENV_FILE); \
|
||
echo "# Автор: $(AUTHOR)" >> $(ENV_FILE); \
|
||
echo "# Сайт: $(SITE)" >> $(ENV_FILE); \
|
||
echo "" >> $(ENV_FILE); \
|
||
echo "# Основные настройки" >> $(ENV_FILE); \
|
||
echo "PROJECT_NAME=$$USER_PROJECT_NAME" >> $(ENV_FILE); \
|
||
echo "VERSION=$$USER_VERSION" >> $(ENV_FILE); \
|
||
echo "AUTHOR=$$USER_AUTHOR" >> $(ENV_FILE); \
|
||
echo "SITE=$$USER_SITE" >> $(ENV_FILE); \
|
||
echo "" >> $(ENV_FILE); \
|
||
echo "# Docker settings" >> $(ENV_FILE); \
|
||
echo "DOCKER_IMAGE=$$USER_DOCKER_IMAGE" >> $(ENV_FILE); \
|
||
echo "DOCKER_NETWORK=$$USER_DOCKER_NETWORK" >> $(ENV_FILE); \
|
||
echo "" >> $(ENV_FILE); \
|
||
echo "# Molecule settings" >> $(ENV_FILE); \
|
||
echo "SCENARIO=$$USER_SCENARIO" >> $(ENV_FILE); \
|
||
echo "LAB_SPEC=$$USER_LAB_SPEC" >> $(ENV_FILE); \
|
||
echo "" >> $(ENV_FILE); \
|
||
echo "# Kubernetes settings" >> $(ENV_FILE); \
|
||
echo "KUBE_CONTEXT=$$USER_KUBE_CONTEXT" >> $(ENV_FILE); \
|
||
echo "ISTIO_VERSION=$$USER_ISTIO_VERSION" >> $(ENV_FILE); \
|
||
echo "KIND_VERSION=$$USER_KIND_VERSION" >> $(ENV_FILE); \
|
||
echo "" >> $(ENV_FILE); \
|
||
echo "# Paths" >> $(ENV_FILE); \
|
||
echo "ROLES_DIR=$$USER_ROLES_DIR" >> $(ENV_FILE); \
|
||
echo "VAULT_PASSWORD_FILE=$$USER_VAULT_PASSWORD_FILE" >> $(ENV_FILE); \
|
||
echo "$(GREEN)✅ .env файл создан с вашими настройками$(RESET)"; \
|
||
else \
|
||
echo "$(YELLOW)⚠️ .env файл уже существует$(RESET)"; \
|
||
echo "$(BLUE)📝 Текущие настройки:$(RESET)"; \
|
||
grep -v "^#" $(ENV_FILE) | grep -v "^$$" | head -10; \
|
||
fi
|
||
|
||
.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-create-interactive
|
||
preset-create-interactive: check-whiptail ## Интерактивное создание пресета
|
||
@echo "$(CYAN)🎯 Создание нового пресета лаборатории$(RESET)"; \
|
||
PRESET_NAME=$$(whiptail --inputbox "Введите имя пресета (например: my-lab):" 8 50 "my-lab" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
PRESET_DESC=$$(whiptail --inputbox "Введите описание пресета:" 8 50 "Мой лабораторный пресет" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
HOST_COUNT=$$(whiptail --inputbox "Количество хостов:" 8 50 "3" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
OS_FAMILY=$$(whiptail --menu "Выберите семейство ОС:" 15 50 4 "debian" "Debian/Ubuntu" "redhat" "RHEL/CentOS" "mixed" "Смешанное" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
FEATURES=$$(whiptail --checklist "Выберите функции:" 15 50 6 "docker" "Docker" off "dind" "Docker-in-Docker" off "k8s" "Kubernetes" off "istio" "Istio" off "monitoring" "Мониторинг" off "chaos" "Chaos Engineering" off 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
echo "$(BLUE)📝 Создание пресета: $$PRESET_NAME$(RESET)"; \
|
||
mkdir -p molecule/presets; \
|
||
echo "---" > molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "# Пресет: $$PRESET_DESC" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "# Автор: $(AUTHOR)" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "# Сайт: $(SITE)" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "hosts:" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
for i in $$(seq 1 $$HOST_COUNT); do \
|
||
echo " - name: host$$i" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
if [ "$$OS_FAMILY" = "debian" ]; then \
|
||
echo " family: debian" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
elif [ "$$OS_FAMILY" = "redhat" ]; then \
|
||
echo " family: redhat" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
else \
|
||
if [ $$((i % 2)) -eq 0 ]; then \
|
||
echo " family: debian" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
else \
|
||
echo " family: redhat" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
fi; \
|
||
fi; \
|
||
echo " groups: [all]" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
done; \
|
||
echo "" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "features:" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " docker: $$(echo $$FEATURES | grep -q docker && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " dind: $$(echo $$FEATURES | grep -q dind && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " k8s: $$(echo $$FEATURES | grep -q k8s && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " istio: $$(echo $$FEATURES | grep -q istio && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " monitoring: $$(echo $$FEATURES | grep -q monitoring && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo " chaos: $$(echo $$FEATURES | grep -q chaos && echo 'true' || echo 'false')" >> molecule/presets/$$PRESET_NAME.yml; \
|
||
echo "$(GREEN)✅ Пресет $$PRESET_NAME создан: molecule/presets/$$PRESET_NAME.yml$(RESET)"; \
|
||
echo "$(BLUE)📋 Использование: make lab up PRESET=$$PRESET_NAME$(RESET)"
|
||
|
||
.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: playbook-create-interactive
|
||
playbook-create-interactive: check-whiptail ## Интерактивное создание playbook
|
||
@echo "$(CYAN)🎯 Создание нового Ansible playbook$(RESET)"; \
|
||
PLAYBOOK_NAME=$$(whiptail --inputbox "Введите имя playbook (например: deploy.yml):" 8 50 "deploy.yml" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
PLAYBOOK_DESC=$$(whiptail --inputbox "Введите описание playbook:" 8 50 "Развертывание приложения" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
PLAYBOOK_HOSTS=$$(whiptail --inputbox "Целевые хосты (по умолчанию: all):" 8 50 "all" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
PLAYBOOK_ROLES=$$(whiptail --inputbox "Роли через запятую (например: nginx,apache):" 8 50 "nginx" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
PLAYBOOK_TAGS=$$(whiptail --inputbox "Теги через запятую (например: deploy,web):" 8 50 "deploy" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
echo "$(BLUE)📝 Создание playbook: $$PLAYBOOK_NAME$(RESET)"; \
|
||
mkdir -p files/playbooks; \
|
||
echo "---" > files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "# Playbook: $$PLAYBOOK_DESC" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "# Автор: $(AUTHOR)" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "# Сайт: $(SITE)" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "- name: $$PLAYBOOK_DESC" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " hosts: $$PLAYBOOK_HOSTS" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " gather_facts: true" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " tags: [$$PLAYBOOK_TAGS]" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " pre_tasks:" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " - name: Update system packages" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " package:" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " name: '*'"; \
|
||
echo " state: latest" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " when: ansible_os_family in ['Debian', 'RedHat']" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " roles:" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
for role in $$(echo $$PLAYBOOK_ROLES | tr ',' ' '); do \
|
||
echo " - role: $$role" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
done; \
|
||
echo "" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " post_tasks:" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " - name: Verify deployment" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " debug:" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo " msg: \"Playbook $$PLAYBOOK_NAME completed successfully\"" >> files/playbooks/$$PLAYBOOK_NAME; \
|
||
echo "$(GREEN)✅ Playbook $$PLAYBOOK_NAME создан$(RESET)"; \
|
||
echo "$(BLUE)📁 Файл: files/playbooks/$$PLAYBOOK_NAME$(RESET)"; \
|
||
echo "$(BLUE)📋 Запуск: ansible-playbook files/playbooks/$$PLAYBOOK_NAME$(RESET)"
|
||
|
||
.PHONY: role-create-interactive
|
||
role-create-interactive: check-whiptail ## Интерактивное создание роли
|
||
@echo "$(CYAN)🎯 Создание новой Ansible роли$(RESET)"; \
|
||
ROLE_NAME=$$(whiptail --inputbox "Введите имя роли (например: nginx):" 8 50 "nginx" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
ROLE_DESC=$$(whiptail --inputbox "Введите описание роли:" 8 50 "Установка и настройка nginx" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
ROLE_PACKAGE=$$(whiptail --inputbox "Основной пакет (по умолчанию: $$ROLE_NAME):" 8 50 "$$ROLE_NAME" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
ROLE_SERVICE=$$(whiptail --inputbox "Имя сервиса (по умолчанию: $$ROLE_NAME):" 8 50 "$$ROLE_NAME" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
ROLE_PLATFORMS=$$(whiptail --checklist "Поддерживаемые платформы:" 15 50 4 "ubuntu" "Ubuntu" on "centos" "CentOS" on "rhel" "RHEL" off "debian" "Debian" off 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
ROLE_TAGS=$$(whiptail --inputbox "Теги через запятую (по умолчанию: $$ROLE_NAME):" 8 50 "$$ROLE_NAME,web,server" 3>&1 1>&2 2>&3); \
|
||
if [ $$? -ne 0 ]; then echo "$(RED)❌ Отменено$(RESET)"; exit 1; fi; \
|
||
echo "$(BLUE)📝 Создание роли: $$ROLE_NAME$(RESET)"; \
|
||
mkdir -p $(ROLES_DIR)/$$ROLE_NAME/{tasks,handlers,templates,files,vars,defaults,meta,tests,playbooks}; \
|
||
echo "$(BLUE)📝 Создаем основные файлы...$(RESET)"; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "# Основные задачи роли $$ROLE_NAME" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "- name: $$ROLE_NAME placeholder" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " debug:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " msg: \"Роль $$ROLE_NAME готова для настройки\"" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "- name: Include OS-specific tasks" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " include_tasks: \"{{ ansible_os_family | lower }}.yml\"" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "- name: Start $$ROLE_NAME service" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " systemd:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " name: \"{{ $$ROLE_NAME}_service | default('$$ROLE_SERVICE') }\"" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " state: started" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " enabled: true" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo " when: $$ROLE_NAME}_service is defined" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "# Задачи для Debian/Ubuntu семейства" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "- name: Update apt cache (Debian)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " apt:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " update_cache: true" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " cache_valid_time: 3600" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " when: ansible_os_family == 'Debian'" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "- name: Install $$ROLE_NAME package (Debian)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " apt:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " name: \"{{ $$ROLE_NAME}_package | default('$$ROLE_PACKAGE') }\"" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " state: present" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo " when: ansible_os_family == 'Debian'" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/debian.yml; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "# Задачи для RHEL/CentOS семейства" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "- name: Update yum cache (RHEL)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " yum:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " update_cache: true" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " when: ansible_os_family == 'RedHat'" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "- name: Install $$ROLE_NAME package (RHEL)" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " yum:" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " name: \"{{ $$ROLE_NAME}_package | default('$$ROLE_PACKAGE') }\"" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " state: present" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo " when: ansible_os_family == 'RedHat'" >> $(ROLES_DIR)/$$ROLE_NAME/tasks/redhat.yml; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "# Переменные по умолчанию для роли $$ROLE_NAME" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "# Автор: $(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "# Сайт: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "$$ROLE_NAME}_enabled: true" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "$$ROLE_NAME}_package: $$ROLE_PACKAGE" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "$$ROLE_NAME}_service: $$ROLE_SERVICE" >> $(ROLES_DIR)/$$ROLE_NAME/defaults/main.yml; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo "galaxy_info:" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " author: $(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " description: $$ROLE_DESC" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " company: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " license: MIT" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " min_ansible_version: 2.9" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " platforms:" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " - name: Ubuntu" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " versions: [focal, jammy]" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " - name: CentOS" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " versions: [7, 8, 9]" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " - name: RHEL" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " versions: [7, 8, 9]" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo " galaxy_tags: [$$ROLE_TAGS]" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo "dependencies: []" >> $(ROLES_DIR)/$$ROLE_NAME/meta/main.yml; \
|
||
echo "---" > $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "# Роль $$ROLE_NAME" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "$$ROLE_DESC" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "## Переменные" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "| Переменная | По умолчанию | Описание |" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "|------------|--------------|----------|" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "| \`$$ROLE_NAME}_enabled\` | \`true\` | Включить роль |" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "| \`$$ROLE_NAME}_package\` | \`$$ROLE_PACKAGE\` | Имя пакета |" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "| \`$$ROLE_NAME}_service\` | \`$$ROLE_SERVICE\` | Имя сервиса |" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "## Использование" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "\`\`\`yaml" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "- hosts: all" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo " roles:" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo " - role: $$ROLE_NAME" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "\`\`\`" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "## Автор" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "$(AUTHOR)" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "Сайт: $(SITE)" >> $(ROLES_DIR)/$$ROLE_NAME/README.md; \
|
||
echo "$(GREEN)✅ Роль $$ROLE_NAME создана$(RESET)"; \
|
||
echo "$(BLUE)📁 Структура: $(ROLES_DIR)/$$ROLE_NAME/$(RESET)"; \
|
||
echo "$(BLUE)📝 Основной файл: $(ROLES_DIR)/$$ROLE_NAME/tasks/main.yml$(RESET)"; \
|
||
echo "$(BLUE)📋 Playbooks: $(ROLES_DIR)/$$ROLE_NAME/playbooks/$(RESET)"
|
||
|
||
.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 |