diff --git a/Makefile b/Makefile index 02fb632..c532c28 100644 --- a/Makefile +++ b/Makefile @@ -66,14 +66,55 @@ help: ## Показать справку по всем командам @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: 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: setup-env-interactive setup-vault setup-roles setup-precommit ## Полная инициализация проекта +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)" @@ -343,6 +384,53 @@ kube: ## Управление Kubernetes (sh|cmd|enter|kiali|istio|grafana|prom| # УПРАВЛЕНИЕ ПРЕСЕТАМИ # ============================================================================= +.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 \ @@ -417,6 +505,127 @@ preset: ## Управление пресетами (list|create|edit|test|copy) # УПРАВЛЕНИЕ РОЛЯМИ # ============================================================================= +.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 \