feat: добавлена пометка типа операции (Build/Push) в истории сборок Dockerfile

- Добавлена колонка 'Тип' во все таблицы истории сборок
- Для push операций отображается registry вместо платформ
- Сохранение пользователя при создании push лога
- Исправлена ошибка с logger в push_docker_image endpoint
- Улучшено отображение истории сборок с визуальными индикаторами
This commit is contained in:
Сергей Антропов
2026-02-15 22:59:02 +03:00
parent 23e1a6037b
commit 1fbf9185a2
232 changed files with 38075 additions and 5 deletions

871
docs/IMPROVEMENTS.md Normal file
View File

@@ -0,0 +1,871 @@
# Предложения по улучшению DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
**Дата:** 2024
## 📋 Обзор
Этот документ содержит предложения по улучшению проекта DevOpsLab для превращения его в универсальную платформу для локального создания и тестирования Ansible ролей в любых средах.
## 🎯 Цели улучшений
1. **Упрощение создания новых ролей** - максимальная автоматизация и шаблонизация
2. **Улучшение системы тестирования** - более гибкие и мощные preset'ы
3. **Автоматизация CI/CD** - полная интеграция с популярными системами
4. **Улучшение документации** - больше примеров и руководств
5. **Мониторинг и отчетность** - визуализация результатов тестирования
6. **Производительность** - оптимизация времени тестирования
7. **Расширяемость** - плагины и интеграции
---
## 1. 🎨 Система шаблонов ролей
### 1.1. Шаблоны для разных типов ролей
**Проблема:** Сейчас все роли создаются с одинаковой базовой структурой, но разные типы ролей требуют разных подходов.
**Решение:** Создать систему шаблонов ролей с предустановленными структурами для разных типов:
```
templates/
├── role-types/
│ ├── service/ # Роль для установки сервиса (nginx, apache)
│ │ ├── tasks/
│ │ │ ├── install.yml
│ │ │ ├── configure.yml
│ │ │ ├── service.yml
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── templates/
│ │ │ └── service.conf.j2
│ │ └── defaults/
│ │ └── main.yml
│ ├── package/ # Роль для установки пакетов
│ ├── config/ # Роль для конфигурации
│ ├── database/ # Роль для работы с БД
│ ├── monitoring/ # Роль для мониторинга
│ ├── security/ # Роль для безопасности
│ └── custom/ # Кастомный шаблон
```
**Команда:**
```bash
make role create --template=service --name=nginx
make role create --template=package --name=python-packages
make role create --template=custom --name=my-custom-role
```
### 1.2. Интерактивный мастер создания роли
**Проблема:** Создание роли требует знания структуры и ручного редактирования.
**Решение:** Интерактивный мастер с вопросами:
- Тип роли (service, package, config, etc.)
- Поддерживаемые ОС
- Необходимые зависимости
- Переменные по умолчанию
- Тесты для роли
**Пример:**
```bash
make role create-wizard
# Вопросы:
# 1. Выберите тип роли: [service/package/config/database/monitoring/security/custom]
# 2. Введите имя роли: nginx
# 3. Выберите поддерживаемые ОС: [Ubuntu/Debian/CentOS/RHEL/AlmaLinux/Rocky/Alt/Astra]
# 4. Нужны ли handlers? [y/n]
# 5. Нужны ли templates? [y/n]
# 6. Нужны ли files? [y/n]
# 7. Какие переменные нужны? (интерактивно)
```
### 1.3. Генератор документации из кода
**Проблема:** Документация роли часто устаревает или неполная.
**Решение:** Автоматическая генерация документации из:
- Переменных в `defaults/main.yml`
- Комментариев в tasks
- Метаданных в `meta/main.yml`
**Команда:**
```bash
make role docs-generate nginx
# Генерирует:
# - README.md с таблицей переменных
# - EXAMPLES.md с примерами использования
# - CHANGELOG.md (если есть)
```
---
## 2. 🔧 Улучшение системы preset'ов
### 2.1. Динамические preset'ы
**Проблема:** Preset'ы статичны и требуют ручного редактирования.
**Решение:** Создание preset'ов на лету через CLI:
```bash
# Создание preset'а для конкретной роли
make preset create --name=nginx-test \
--os=ubuntu22,debian12,centos9 \
--count=3 \
--network=nginx-net
# Создание preset'а для тестирования зависимостей
make preset create --name=deps-test \
--include-roles=docker,python,repo \
--os=all
```
### 2.2. Preset'ы на основе тегов ролей
**Проблема:** Нет возможности автоматически выбрать preset для тестирования роли с определенными тегами.
**Решение:** Автоматическое создание preset'ов на основе тегов:
```yaml
# roles/nginx/meta/main.yml
galaxy_tags:
- web
- service
- nginx
# Автоматически создается preset: web-service.yml
```
### 2.3. Preset'ы для разных сценариев
**Проблема:** Ограниченный набор preset'ов для разных сценариев тестирования.
**Решение:** Расширенный набор preset'ов:
```
molecule/presets/
├── scenarios/
│ ├── single-os/ # Тестирование на одной ОС
│ ├── multi-os/ # Тестирование на нескольких ОС
│ ├── upgrade/ # Тестирование обновлений
│ ├── rollback/ # Тестирование откатов
│ ├── idempotency/ # Тестирование идемпотентности
│ ├── performance/ # Тестирование производительности
│ ├── security/ # Тестирование безопасности
│ └── integration/ # Интеграционное тестирование
```
### 2.4. Preset'ы с условиями
**Проблема:** Нет возможности условного запуска тестов.
**Решение:** Preset'ы с условиями:
```yaml
# molecule/presets/conditional.yml
hosts:
- name: ubuntu-test
family: ubuntu22
when: ansible_distribution == "Ubuntu"
- name: debian-test
family: debian12
when: ansible_distribution == "Debian"
```
---
## 3. 🤖 Автоматизация и CI/CD
### 3.1. Автоматическое тестирование при коммите
**Проблема:** Нужно вручную запускать тесты после изменений.
**Решение:** Git hooks для автоматического тестирования:
```bash
# .git/hooks/pre-commit
#!/bin/bash
make role lint
make role test minimal
# .git/hooks/post-merge
#!/bin/bash
make role test default
```
**Команда:**
```bash
make setup-git-hooks
# Устанавливает pre-commit и post-merge hooks
```
### 3.2. Интеграция с GitHub Actions
**Проблема:** CI/CD конфигурации есть, но можно улучшить.
**Решение:** Расширенные workflow'ы:
```yaml
# .github/workflows/test-roles.yml
name: Test Ansible Roles
on:
push:
paths:
- 'roles/**'
pull_request:
paths:
- 'roles/**'
jobs:
test:
strategy:
matrix:
preset: [minimal, default, all-images]
role: ${{ github.event.changed_files }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Test role
run: make role test ${{ matrix.preset }} ${{ matrix.role }}
```
### 3.3. Автоматическое обновление зависимостей
**Проблема:** Зависимости ролей могут устаревать.
**Решение:** Автоматическая проверка и обновление:
```bash
make deps check # Проверка устаревших зависимостей
make deps update # Обновление зависимостей
make deps audit # Аудит безопасности зависимостей
```
### 3.4. Автоматическая публикация в Ansible Galaxy
**Проблема:** Роли нужно вручную публиковать в Galaxy.
**Решение:** Автоматическая публикация:
```bash
make galaxy publish nginx
# Автоматически:
# - Проверяет синтаксис
# - Запускает тесты
# - Генерирует документацию
# - Публикует в Galaxy
```
---
## 4. 📊 Мониторинг и отчетность
### 4.1. Dashboard для результатов тестирования
**Проблема:** Результаты тестирования разбросаны по логам.
**Решение:** Web-дашборд для визуализации:
```bash
make dashboard start
# Запускает веб-интерфейс на http://localhost:8080
# Показывает:
# - История тестов
# - Статистика успешности
# - Время выполнения
# - Графики покрытия ОС
```
### 4.2. Отчеты в разных форматах
**Проблема:** Результаты тестов только в консоли.
**Решение:** Генерация отчетов:
```bash
make report generate --format=html,json,xml,junit
# Генерирует:
# - reports/test-report.html
# - reports/test-report.json
# - reports/test-report.xml
# - reports/junit.xml
```
### 4.3. История тестирования
**Проблема:** Нет истории результатов тестирования.
**Решение:** Сохранение истории:
```bash
make test history show --role=nginx --limit=10
make test history compare --role=nginx --from=v1.0.0 --to=v1.1.0
```
### 4.4. Уведомления о результатах
**Проблема:** Нужно вручную проверять результаты.
**Решение:** Уведомления:
```bash
make notify setup --slack,email,telegram
# Настройка уведомлений:
# - Slack webhook
# - Email
# - Telegram bot
```
---
## 5. ⚡ Производительность
### 5.1. Параллельное тестирование
**Проблема:** Тесты запускаются последовательно.
**Решение:** Параллельное выполнение:
```bash
make role test --parallel=4 --preset=all-images
# Запускает 4 теста одновременно
```
### 5.2. Кеширование результатов
**Проблема:** Повторные тесты выполняют одни и те же действия.
**Решение:** Кеширование:
```bash
make cache enable
# Кеширует:
# - Установленные пакеты
# - Скачанные файлы
# - Результаты проверок
```
### 5.3. Инкрементальное тестирование
**Проблема:** Тестируются все роли, даже если изменилась только одна.
**Решение:** Тестирование только измененных ролей:
```bash
make role test --changed-only
# Тестирует только роли, измененные в последнем коммите
```
### 5.4. Оптимизация Docker образов
**Проблема:** Образы могут быть большими и медленными.
**Решение:** Оптимизация:
```bash
make docker optimize
# Оптимизирует:
# - Размер образов
# - Время сборки
# - Кеширование слоев
```
---
## 6. 🔌 Расширяемость
### 6.1. Система плагинов
**Проблема:** Сложно добавить новую функциональность.
**Решение:** Плагинная архитектура:
```
plugins/
├── verifiers/
│ ├── testinfra/
│ ├── goss/
│ └── serverspec/
├── drivers/
│ ├── docker/
│ ├── vagrant/
│ └── cloud/
└── reporters/
├── html/
├── json/
└── junit/
```
### 6.2. Интеграция с внешними инструментами
**Проблема:** Нет интеграции с популярными инструментами.
**Решение:** Интеграции:
```bash
# Terraform
make terraform init
make terraform test
# Vagrant
make vagrant up
make vagrant test
# Cloud providers
make cloud test --provider=aws,azure,gcp
```
### 6.3. API для автоматизации
**Проблема:** Нет программного доступа к функциональности.
**Решение:** REST API:
```bash
# Запуск API сервера
make api start
# Примеры использования:
curl http://localhost:8080/api/v1/roles
curl -X POST http://localhost:8080/api/v1/roles/nginx/test
curl http://localhost:8080/api/v1/test-results/nginx
```
---
## 7. 🔐 Безопасность
### 7.1. Сканирование уязвимостей
**Проблема:** Нет автоматической проверки безопасности.
**Решение:** Интеграция сканеров:
```bash
make security scan --role=nginx
# Использует:
# - ansible-lint security rules
# - Bandit для Python кода
# - Trivy для Docker образов
# - Snyk для зависимостей
```
### 7.2. Проверка секретов
**Проблема:** Секреты могут попасть в код.
**Решение:** Автоматическая проверка:
```bash
make security check-secrets
# Проверяет:
# - Хардкод паролей
# - API ключи
# - Токены
# - Сертификаты
```
### 7.3. Подписывание ролей
**Проблема:** Нет гарантии целостности ролей.
**Решение:** GPG подписи:
```bash
make role sign nginx
make role verify nginx
```
---
## 8. 📚 Документация и примеры
### 8.1. Интерактивные туториалы
**Проблема:** Документация статична.
**Решение:** Интерактивные туториалы:
```bash
make tutorial start --topic=creating-roles
# Пошаговый интерактивный туториал
```
### 8.2. Примеры для каждого типа роли
**Проблема:** Недостаточно примеров.
**Решение:** Расширенная библиотека примеров:
```
examples/
├── roles/
│ ├── service/
│ │ ├── nginx/
│ │ ├── apache/
│ │ └── haproxy/
│ ├── database/
│ │ ├── postgresql/
│ │ ├── mysql/
│ │ └── mongodb/
│ └── monitoring/
│ ├── prometheus/
│ └── grafana/
```
### 8.3. Видео-руководства
**Проблема:** Текстовые руководства могут быть непонятны.
**Решение:** Видео-руководства в документации.
### 8.4. Чек-листы для разработки
**Проблема:** Легко забыть важные шаги.
**Решение:** Чек-листы:
```bash
make checklist show --type=role-development
# Показывает чек-лист для разработки роли
```
---
## 9. 🎯 Улучшение UX
### 9.1. Интерактивный режим
**Проблема:** Много команд для запоминания.
**Решение:** Интерактивный режим:
```bash
make interactive
# Запускает интерактивное меню:
# 1. Создать роль
# 2. Протестировать роль
# 3. Просмотреть результаты
# 4. Управление preset'ами
# ...
```
### 9.2. Автодополнение команд
**Проблема:** Нужно помнить все команды.
**Решение:** Bash/Zsh автодополнение:
```bash
make setup-completion
# Устанавливает автодополнение для:
# - make команды
# - Имена ролей
# - Preset'ы
```
### 9.3. Цветной вывод и прогресс-бары
**Проблема:** Сложно отслеживать прогресс длительных операций.
**Решение:** Улучшенный вывод:
```bash
make role test --progress
# Показывает:
# - Прогресс-бары
# - Цветной вывод
# - ETA для операций
```
### 9.4. Подсказки и советы
**Проблема:** Нет подсказок при ошибках.
**Решение:** Умные подсказки:
```bash
# При ошибке теста:
❌ Тест не прошел
💡 Возможные причины:
- Проверьте синтаксис: make role lint
- Проверьте переменные: make role vars-show
- Посмотрите логи: make logs show
```
---
## 10. 🔄 Управление версиями
### 10.1. Семантическое версионирование
**Проблема:** Версии ролей не структурированы.
**Решение:** Автоматическое версионирование:
```bash
make version bump --role=nginx --type=major,minor,patch
# Автоматически:
# - Обновляет версию в meta/main.yml
# - Создает тег в git
# - Обновляет CHANGELOG.md
```
### 10.2. Changelog генерация
**Проблема:** CHANGELOG нужно вести вручную.
**Решение:** Автоматическая генерация:
```bash
make changelog generate --role=nginx
# Генерирует CHANGELOG.md из:
# - Git коммитов
# - Pull requests
# - Issues
```
### 10.3. Тегирование ролей
**Проблема:** Нет связи между версиями ролей и git тегами.
**Решение:** Автоматическое тегирование:
```bash
make tag create --role=nginx --version=1.0.0
# Создает git тег: roles/nginx/v1.0.0
```
---
## 11. 🧪 Расширенное тестирование
### 11.1. Тестирование идемпотентности
**Проблема:** Нет автоматической проверки идемпотентности.
**Решение:** Автоматическое тестирование:
```bash
make role test --idempotency --role=nginx
# Запускает роль дважды и проверяет, что изменений нет
```
### 11.2. Тестирование откатов
**Проблема:** Нет проверки возможности отката изменений.
**Решение:** Тестирование откатов:
```bash
make role test --rollback --role=nginx
# Применяет роль, затем откатывает и проверяет
```
### 11.3. Нагрузочное тестирование
**Проблема:** Нет проверки производительности ролей.
**Решение:** Нагрузочное тестирование:
```bash
make role test --load --role=nginx --concurrent=10
# Запускает роль на 10 хостах одновременно
```
### 11.4. Тестирование совместимости
**Проблема:** Нет проверки совместимости версий.
**Решение:** Матричное тестирование:
```bash
make role test --matrix --role=nginx
# Тестирует на всех комбинациях:
# - ОС × версии Ansible × версии Python
```
---
## 12. 📦 Управление зависимостями
### 12.1. Визуализация зависимостей
**Проблема:** Сложно понять зависимости между ролями.
**Решение:** Граф зависимостей:
```bash
make deps graph --role=nginx
# Генерирует граф зависимостей в формате:
# - PNG изображение
# - Graphviz DOT
# - Интерактивный HTML
```
### 12.2. Проверка циклических зависимостей
**Проблема:** Могут быть циклические зависимости.
**Решение:** Автоматическая проверка:
```bash
make deps check-cycles
# Проверяет наличие циклов в зависимостях
```
### 12.3. Автоматическое разрешение конфликтов
**Проблема:** Конфликты версий зависимостей.
**Решение:** Автоматическое разрешение:
```bash
make deps resolve --role=nginx
# Автоматически разрешает конфликты версий
```
---
## 13. 🌐 Мультиоблачные тесты
### 13.1. Тестирование в облаках
**Проблема:** Тестирование только локально в Docker.
**Решение:** Поддержка облачных провайдеров:
```bash
make cloud test --provider=aws --role=nginx
make cloud test --provider=azure --role=nginx
make cloud test --provider=gcp --role=nginx
```
### 13.2. Унифицированный интерфейс
**Проблема:** Разные API для разных облаков.
**Решение:** Единый интерфейс:
```bash
make cloud create --provider=aws,azure,gcp --count=3
make cloud test --provider=all
make cloud destroy --provider=all
```
---
## 14. 🔍 Поиск и фильтрация
### 14.1. Поиск по ролям
**Проблема:** Сложно найти нужную роль.
**Решение:** Поиск:
```bash
make search role --query=nginx
# Ищет по:
# - Имени роли
# - Описанию
# - Тегам
# - Переменным
```
### 14.2. Фильтрация preset'ов
**Проблема:** Много preset'ов, сложно выбрать.
**Решение:** Фильтрация:
```bash
make presets list --filter=os:ubuntu,count:2-5
# Фильтрует по:
# - ОС
# - Количеству хостов
# - Тегам
```
---
## 15. 📈 Метрики и аналитика
### 15.1. Метрики ролей
**Проблема:** Нет статистики по ролям.
**Решение:** Сбор метрик:
```bash
make metrics show --role=nginx
# Показывает:
# - Время выполнения
# - Успешность тестов
# - Покрытие ОС
# - Использование переменных
```
### 15.2. Сравнение версий
**Проблема:** Сложно сравнить версии роли.
**Решение:** Сравнение:
```bash
make compare versions --role=nginx --from=v1.0.0 --to=v1.1.0
# Сравнивает:
# - Изменения в коде
# - Новые переменные
# - Изменения в тестах
```
---
## 🎯 Приоритизация улучшений
### Высокий приоритет (быстрая реализация, большой эффект)
1. ✅ Система шаблонов ролей (раздел 1.1, 1.2)
2. ✅ Интерактивный мастер создания роли (раздел 1.2)
3. ✅ Автоматическое тестирование при коммите (раздел 3.1)
4. ✅ Отчеты в разных форматах (раздел 4.2)
5. ✅ Параллельное тестирование (раздел 5.1)
6. ✅ Интерактивный режим (раздел 9.1)
### Средний приоритет (средняя сложность, хороший эффект)
1. ✅ Динамические preset'ы (раздел 2.1)
2. ✅ Dashboard для результатов (раздел 4.1)
3. ✅ Кеширование результатов (раздел 5.2)
4. ✅ Сканирование уязвимостей (раздел 7.1)
5. ✅ Интерактивные туториалы (раздел 8.1)
6. ✅ Семантическое версионирование (раздел 10.1)
### Низкий приоритет (сложная реализация, дополнительный функционал)
1. ✅ API для автоматизации (раздел 6.3)
2. ✅ Мультиоблачные тесты (раздел 13)
3. ✅ Система плагинов (раздел 6.1)
4. ✅ Нагрузочное тестирование (раздел 11.3)
---
## 📝 Заключение
Эти улучшения превратят DevOpsLab в полноценную платформу для разработки и тестирования Ansible ролей. Рекомендуется начать с высокоприоритетных улучшений и постепенно добавлять остальные.
**Следующие шаги:**
1. Выбрать приоритетные улучшения
2. Создать issues в репозитории
3. Разбить на задачи
4. Реализовать по очереди
5. Собрать обратную связь от пользователей
---
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru

View File

@@ -0,0 +1,92 @@
# Краткое резюме предложений по улучшению DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🎯 Топ-10 улучшений для платформы тестирования Ansible ролей
### 1. 🎨 Система шаблонов ролей
**Что:** Предустановленные шаблоны для разных типов ролей (service, package, config, database, etc.)
**Зачем:** Ускоряет создание новых ролей, стандартизирует структуру
**Команда:** `make role create --template=service --name=nginx`
### 2. 🤖 Интерактивный мастер создания роли
**Что:** Пошаговый мастер с вопросами о типе роли, ОС, зависимостях
**Зачем:** Упрощает создание ролей для новичков
**Команда:** `make role create-wizard`
### 3. ⚡ Параллельное тестирование
**Что:** Запуск тестов на нескольких хостах одновременно
**Зачем:** Ускоряет тестирование в 2-4 раза
**Команда:** `make role test --parallel=4`
### 4. 📊 Dashboard для результатов
**Что:** Web-интерфейс для визуализации результатов тестирования
**Зачем:** Удобный просмотр истории и статистики
**Команда:** `make dashboard start`
### 5. 🔄 Динамические preset'ы
**Что:** Создание preset'ов на лету через CLI
**Зачем:** Гибкость в выборе окружений для тестирования
**Команда:** `make preset create --name=nginx-test --os=ubuntu22,debian12`
### 6. 📈 Отчеты в разных форматах
**Что:** Генерация отчетов в HTML, JSON, XML, JUnit
**Зачем:** Интеграция с CI/CD системами
**Команда:** `make report generate --format=html,json`
### 7. 🔍 Автоматическое тестирование при коммите
**Что:** Git hooks для автоматического запуска тестов
**Зачем:** Раннее обнаружение проблем
**Команда:** `make setup-git-hooks`
### 8. 🎯 Интерактивный режим
**Что:** Меню с выбором действий
**Зачем:** Упрощает работу для новичков
**Команда:** `make interactive`
### 9. 🔐 Сканирование уязвимостей
**Что:** Автоматическая проверка безопасности ролей
**Зачем:** Обнаружение проблем безопасности до продакшна
**Команда:** `make security scan --role=nginx`
### 10. 📦 Кеширование результатов
**Что:** Кеширование установленных пакетов и результатов проверок
**Зачем:** Ускорение повторных тестов
**Команда:** `make cache enable`
---
## 📋 Быстрый старт улучшений
### Фаза 1: Быстрые победы (1-2 недели)
- ✅ Интерактивный мастер создания роли
- ✅ Параллельное тестирование
- ✅ Отчеты в разных форматах
- ✅ Git hooks для автоматического тестирования
### Фаза 2: Основной функционал (1 месяц)
- ✅ Система шаблонов ролей
- ✅ Динамические preset'ы
- ✅ Dashboard для результатов
- ✅ Интерактивный режим
### Фаза 3: Расширенный функционал (2-3 месяца)
- ✅ Сканирование уязвимостей
- ✅ Кеширование результатов
- ✅ API для автоматизации
- ✅ Интеграция с облаками
---
## 💡 Дополнительные идеи
- **Автодополнение команд** - bash/zsh completion
- **История тестирования** - сравнение версий ролей
- **Визуализация зависимостей** - граф зависимостей ролей
- **Тестирование идемпотентности** - автоматическая проверка
- **Семантическое версионирование** - автоматическое управление версиями
---
**Полная версия:** [IMPROVEMENTS.md](IMPROVEMENTS.md)

89
docs/README.md Normal file
View File

@@ -0,0 +1,89 @@
# Документация DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 📚 Содержание
### 🚀 Быстрый старт
- **[getting-started.md](getting-started.md)** - Общий быстрый старт
- **[web-interface-quickstart.md](web-interface-quickstart.md)** - Быстрый старт веб-интерфейса
- **[web-interface-quickstart-docker.md](web-interface-quickstart-docker.md)** - Быстрый старт веб-интерфейса в Docker
- **[web-interface-start-here.md](web-interface-start-here.md)** - Начните отсюда (веб-интерфейс)
### 🌐 Веб-интерфейс
- **[web-interface-readme.md](web-interface-readme.md)** - Общая документация веб-интерфейса
- **[web-interface-docker.md](web-interface-docker.md)** - Запуск веб-интерфейса в Docker
- **[WEB_INTERFACE_PROPOSAL.md](WEB_INTERFACE_PROPOSAL.md)** - Полное предложение по веб-интерфейсу
- **[WEB_INTERFACE_DETAILS.md](WEB_INTERFACE_DETAILS.md)** - Детали работы веб-интерфейса
- **[WEB_INTERFACE_DEPLOY_IMPORT_EXPORT.md](WEB_INTERFACE_DEPLOY_IMPORT_EXPORT.md)** - Деплой, импорт и экспорт через веб-интерфейс
- **[WEB_INTERFACE_QUICKSTART.md](WEB_INTERFACE_QUICKSTART.md)** - Быстрый старт (старая версия)
- **[web-interface-deployment-status.md](web-interface-deployment-status.md)** - Статус развертывания
- **[web-interface-status.md](web-interface-status.md)** - Текущий статус веб-интерфейса
### 🔧 Ansible и Molecule
- **[molecule-guide.md](molecule-guide.md)** - Руководство по Molecule
- **[creating-roles.md](creating-roles.md)** - Создание ролей
- **[devops-role.md](devops-role.md)** - Универсальная роль devops
- **[testing-vs-deployment.md](testing-vs-deployment.md)** - Различия между тестированием и развертыванием
- **[universal-testing.md](universal-testing.md)** - Универсальное тестирование
### 🧪 Presets
- **[all-images-preset.md](all-images-preset.md)** - Пресет all-images для тестирования всех образов
- **[cod-preset.md](cod-preset.md)** - COD preset для тестирования российских и зарубежных ОС (ARM64)
- **[presets-by-os.md](presets-by-os.md)** - Presets по операционным системам
### 🚀 Развертывание
- **[deploy-yml-customization.md](deploy-yml-customization.md)** - Полное руководство по кастомизации deploy.yml
- **[run-yml-guide.md](run-yml-guide.md)** - Руководство по run.yml
- **[site-yml-guide.md](site-yml-guide.md)** - Руководство по site.yml
### 🔐 Безопасность
- **[vault-guide.md](vault-guide.md)** - Работа с Ansible Vault
- **[linting-guide.md](linting-guide.md)** - Руководство по линтингу ролей
### 🐳 Docker
- **[dockerfiles.md](dockerfiles.md)** - Полная документация по Docker образам
- **[arm64-support.md](arm64-support.md)** - Поддержка ARM64 архитектуры
- **[buildx-fixes.md](buildx-fixes.md)** - Исправление проблем с Docker Buildx
### ☸️ Kubernetes
- **[kubernetes-kind.md](kubernetes-kind.md)** - Руководство по Kubernetes (Kind)
- **[kubernetes-full-guide.md](kubernetes-full-guide.md)** - Полное руководство по Kubernetes
- **[kubernetes-commands.md](kubernetes-commands.md)** - Команды Kubernetes
- **[k8s-scripts.md](k8s-scripts.md)** - Описание K8s скриптов
- **[k8s-ingress-fix.md](k8s-ingress-fix.md)** - Исправление Ingress
### 📊 Мониторинг и диагностика
- **[monitoring.md](monitoring.md)** - Мониторинг, диагностика и troubleshooting
### 🖥️ Платформы
- **[platform-support.md](platform-support.md)** - Поддержка платформ
### 📝 Примеры
- **[examples.md](examples.md)** - Примеры использования
### 🔄 CI/CD
- **[cicd-setup.md](cicd-setup.md)** - Настройка CI/CD
### 📈 Улучшения
- **[IMPROVEMENTS.md](IMPROVEMENTS.md)** - Предложения по улучшению
- **[IMPROVEMENTS_SUMMARY.md](IMPROVEMENTS_SUMMARY.md)** - Краткое резюме улучшений
---
**Версия документации:** 3.0.0
**Последнее обновление:** 2024-02-15

View File

@@ -0,0 +1,985 @@
# Деплой, импорт и экспорт ролей в веб-интерфейсе
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🎯 Обзор
Этот документ описывает функциональность деплоя на живые серверы, импорта и экспорта ролей через веб-интерфейс.
---
## 1. 🚀 Деплой на живые серверы
### 1.1. Страница деплоя роли
**URL:** `/roles/{role_name}/deploy`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Деплой роли: nginx на продакшн серверы │
├─────────────────────────────────────────────────────────┤
│ │
│ ⚠️ ВНИМАНИЕ: Вы собираетесь изменить реальные серверы!│
│ │
│ 📋 Шаг 1: Выбор inventory │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ○ Использовать существующий inventory │ │
│ │ [production ▼] [staging] [development] │ │
│ │ │ │
│ │ ● Создать/редактировать inventory │ │
│ │ [Открыть редактор inventory] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Шаг 2: Настройка переменных │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Переменные для продакшн: │ │
│ │ │ │
│ │ nginx_version: [1.25.0] │ │
│ │ nginx_worker_processes: [4] │ │
│ │ nginx_worker_connections: [2048] │ │
│ │ nginx_sites: │ │
│ │ - name: example.com │ │
│ │ root: /var/www/html │ │
│ │ ssl: ☑ │ │
│ │ │ │
│ │ [📥 Загрузить из шаблона] │ │
│ │ [💾 Сохранить как шаблон] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ⚙️ Шаг 3: Параметры деплоя │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Режим: │ │
│ │ ○ Dry-run (только проверка, без изменений) │ │
│ │ ● Реальный деплой │ │
│ │ │ │
│ │ Опции: │ │
│ │ ☑ Проверка подключения перед деплоем │ │
│ │ ☑ Проверка синтаксиса │ │
│ │ ☐ Только определенные теги │ │
│ │ [web,config] │ │
│ │ ☐ Только определенные хосты │ │
│ │ [web1,web2] │ │
│ │ ☐ Лимит хостов (для постепенного деплоя) │ │
│ │ [2 из 5] │ │
│ │ │ │
│ │ Стратегия деплоя: │ │
│ │ ○ Все хосты одновременно │ │
│ │ ● Постепенно (по одному) │ │
│ │ ○ По группам (сначала web, потом db) │ │
│ │ │ │
│ │ Rollback: │ │
│ │ ☑ Создать backup перед деплоем │ │
│ │ ☑ Включить автоматический rollback при ошибке │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🔐 Шаг 4: Безопасность │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ☑ Использовать Vault для секретов │ │
│ │ ☑ Шифровать SSH ключи │ │
│ │ ☑ Требовать подтверждение для критических операций│
│ │ │ │
│ │ Подтверждение: │ │
│ │ [ ] Я понимаю, что это изменит продакшн серверы │ │
│ │ [ ] Я проверил переменные │ │
│ │ [ ] У меня есть backup │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [🔍 Dry-run] [🚀 Запустить деплой] │
└─────────────────────────────────────────────────────────┘
```
### 1.2. Live мониторинг деплоя
**После запуска деплоя открывается страница с live логами:**
```
┌─────────────────────────────────────────────────────────┐
│ Деплой роли: nginx | Статус: 🟢 Running │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 Прогресс: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ████████████████░░░░ 80% │ │
│ │ Хостов обработано: 4 из 5 │ │
│ │ Текущий хост: web3.example.com │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🖥️ Статус хостов: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ✅ web1.example.com [Успешно] (2m 15s) │ │
│ │ ✅ web2.example.com [Успешно] (2m 10s) │ │
│ │ 🟢 web3.example.com [В процессе...] │ │
│ │ ⏳ web4.example.com [Ожидание...] │ │
│ │ ⏳ web5.example.com [Ожидание...] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Live логи (WebSocket): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [10:30:15] PLAY [web_servers] ****************** │ │
│ │ [10:30:16] TASK [nginx : Install packages] │ │
│ │ [10:30:17] changed: [web1.example.com] │ │
│ │ [10:30:18] TASK [nginx : Configure nginx] │ │
│ │ [10:30:19] changed: [web1.example.com] │ │
│ │ [10:30:20] TASK [nginx : Start nginx] │ │
│ │ [10:30:21] changed: [web1.example.com] │ │
│ │ [10:30:22] PLAY RECAP ************************** │ │
│ │ [10:30:23] web1.example.com : ok=5 changed=3 │ │
│ │ ... │ │
│ │ │ │
│ │ [Автоскролл: ☑] [Очистить] [📥 Скачать] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📈 Статистика: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Успешно: 2 │ │
│ │ В процессе: 1 │ │
│ │ Ожидание: 2 │ │
│ │ Ошибок: 0 │ │
│ │ Среднее время: 2m 12s │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [⏸️ Пауза] [⏹️ Остановить] [🔄 Retry failed] │
└─────────────────────────────────────────────────────────┘
```
### 1.3. WebSocket реализация для live деплоя
```python
# app/api/v1/endpoints/deploy.py
from fastapi import WebSocket, APIRouter
from app.core.make_executor import MakeExecutor
from app.services.deploy_service import DeployService
router = APIRouter()
@router.websocket("/ws/deploy/{deploy_id}")
async def deploy_websocket(websocket: WebSocket, deploy_id: str):
await websocket.accept()
# Получение параметров деплоя из БД
deploy_config = await get_deploy_config(deploy_id)
# Запуск ansible-playbook с потоковым выводом
executor = MakeExecutor()
process = await executor.execute_stream(
f"role deploy",
args=[
"--inventory", deploy_config["inventory"],
"--extra-vars", json.dumps(deploy_config["vars"]),
"--limit", deploy_config.get("limit", ""),
"--tags", deploy_config.get("tags", "")
]
)
# Отправка логов в реальном времени
current_host = None
async for line in process.stdout:
decoded_line = line.decode()
# Парсинг строки для определения хоста
host_match = re.search(r'\[([^\]]+)\]', decoded_line)
if host_match:
current_host = host_match.group(1)
# Отправка с метаданными
await websocket.send_json({
"type": "log",
"host": current_host,
"data": decoded_line,
"timestamp": datetime.now().isoformat(),
"level": detect_log_level(decoded_line) # info, warning, error
})
# Отправка статуса хоста
if "PLAY RECAP" in decoded_line or "ok=" in decoded_line:
status = parse_play_recap(decoded_line)
await websocket.send_json({
"type": "host_status",
"host": current_host,
"status": status["status"], # success, failed, changed
"changed": status.get("changed", 0),
"ok": status.get("ok", 0),
"failed": status.get("failed", 0)
})
# Финальный статус
await websocket.send_json({
"type": "complete",
"status": "success" if process.returncode == 0 else "failed",
"summary": await generate_deploy_summary(deploy_id)
})
```
### 1.4. Сохранение истории деплоев
**Автоматическое сохранение в БД:**
```python
# app/db/models.py
class DeployHistory(Base):
__tablename__ = "deploy_history"
id = Column(Integer, primary_key=True)
role_name = Column(String, nullable=False)
inventory = Column(String, nullable=False)
started_at = Column(DateTime, nullable=False)
completed_at = Column(DateTime)
status = Column(String) # success, failed, cancelled
duration = Column(Integer) # секунды
# Параметры деплоя
variables = Column(JSON) # Переменные роли
limit = Column(String) # Ограничение хостов
tags = Column(String) # Теги для выполнения
# Результаты
total_hosts = Column(Integer)
successful_hosts = Column(Integer)
failed_hosts = Column(Integer)
changed_hosts = Column(Integer)
# Логи
logs = Column(Text) # Полные логи
summary = Column(Text) # Краткое резюме
# Пользователь
user = Column(String)
dry_run = Column(Boolean, default=False)
```
**Интерфейс истории:**
```
┌─────────────────────────────────────────────────────────┐
│ История деплоев │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Фильтры: │
│ [Роль: nginx ▼] [Статус: Все ▼] [Дата: Последние 7 дней]│
│ │
│ 📊 Таблица деплоев: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Дата | Роль | Inventory | Статус | Действия│
│ ├─────────────────────────────────────────────────┤ │
│ │ 15.01 10:30| nginx | production| ✅ | [👁️][📥]│
│ │ 15.01 09:15| nginx | staging | ✅ | [👁️][📥]│
│ │ 14.01 16:45| docker| production| ❌ | [👁️][📥]│
│ │ 14.01 14:20| python| production| ✅ | [👁️][📥]│
│ └─────────────────────────────────────────────────┘ │
│ │
│ [📥 Экспорт в CSV] [📥 Экспорт в JSON] │
└─────────────────────────────────────────────────────────┘
```
---
## 2. 📤 Экспорт ролей в отдельные Git репозитории
### 2.1. Страница экспорта роли
**URL:** `/roles/{role_name}/export`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Экспорт роли: nginx в отдельный репозиторий │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Шаг 1: Настройка репозитория │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Тип экспорта: │ │
│ │ ○ Создать новый репозиторий │ │
│ │ ● Использовать существующий │ │
│ │ │ │
│ │ URL репозитория: │ │
│ │ [https://github.com/user/ansible-role-nginx] │ │
│ │ │ │
│ │ Ветка: [main ▼] [master] [develop] │ │
│ │ │ │
│ │ Аутентификация: │ │
│ │ ○ SSH ключ (из настроек) │ │
│ │ ● Personal Access Token │ │
│ │ [token: ****************] │ │
│ │ │ │
│ │ [🔐 Тест подключения] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📦 Шаг 2: Выбор компонентов для экспорта │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ☑ Структура роли (tasks, handlers, etc.) │ │
│ │ ☑ defaults/main.yml │ │
│ │ ☑ vars/main.yml │ │
│ │ ☑ templates/ │ │
│ │ ☑ files/ │ │
│ │ ☑ meta/main.yml │ │
│ │ ☑ README.md │ │
│ │ ☐ molecule/ (конфигурация тестирования) │ │
│ │ ☐ tests/ (тестовые playbook'и) │ │
│ │ ☐ .github/ (CI/CD workflows) │ │
│ │ │ │
│ │ ⚠️ Секреты (vars/main.yml): │ │
│ │ ○ Экспортировать зашифрованными │ │
│ │ ● Экспортировать без секретов (оставить пустыми)│
│ │ ○ Не экспортировать │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Шаг 3: Метаданные и версионирование │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Версия: [1.0.0] │ │
│ │ Тег: [v1.0.0] (создать git tag) │ │
│ │ │ │
│ │ Описание изменений: │ │
│ │ [Исправлена конфигурация nginx...] │ │
│ │ │ │
│ │ CHANGELOG.md: │ │
│ │ ☑ Автоматически обновить │ │
│ │ ☑ Создать release notes │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📋 Шаг 4: Предпросмотр │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Структура репозитория: │ │
│ │ ansible-role-nginx/ │ │
│ │ ├── tasks/ │ │
│ │ ├── handlers/ │ │
│ │ ├── defaults/ │ │
│ │ ├── vars/ │ │
│ │ ├── templates/ │ │
│ │ ├── files/ │ │
│ │ ├── meta/ │ │
│ │ ├── README.md │ │
│ │ └── .gitignore │ │
│ │ │ │
│ │ Файлов для экспорта: 47 │ │
│ │ Размер: 2.3 MB │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [👁️ Предпросмотр файлов] [📤 Экспортировать] │
└─────────────────────────────────────────────────────────┘
```
### 2.2. Процесс экспорта с прогрессом
**После нажатия "Экспортировать":**
```
┌─────────────────────────────────────────────────────────┐
│ Экспорт роли: nginx │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 Прогресс: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ████████████████████░░ 90% │ │
│ │ Этап: Загрузка в репозиторий │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📋 Этапы: │
│ ✅ Подготовка файлов │ │
│ ✅ Обработка секретов │ │
│ ✅ Создание .gitignore │ │
│ ✅ Клонирование репозитория │ │
│ ✅ Копирование файлов │ │
│ 🟢 Загрузка в репозиторий (git push) │ │
│ ⏳ Создание тега │ │
│ ⏳ Создание release │ │
│ │
│ 📝 Логи: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [10:35:15] Подготовка файлов... │ │
│ │ [10:35:16] Обработка секретов... │ │
│ │ [10:35:17] Клонирование репозитория... │ │
│ │ [10:35:20] Копирование 47 файлов... │ │
│ │ [10:35:22] git add . │ │
│ │ [10:35:23] git commit -m "v1.0.0: ..." │ │
│ │ [10:35:25] git push origin main... │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [✅ Экспорт завершен] [🔗 Открыть репозиторий] │
└─────────────────────────────────────────────────────────┘
```
### 2.3. Реализация экспорта
```python
# app/services/export_service.py
from git import Repo
import shutil
from pathlib import Path
class ExportService:
async def export_role(
self,
role_name: str,
repo_url: str,
branch: str = "main",
version: str = None,
components: List[str] = None,
include_secrets: bool = False
) -> dict:
"""Экспорт роли в Git репозиторий"""
# 1. Подготовка файлов
role_path = Path(f"roles/{role_name}")
temp_dir = Path(f"/tmp/export_{role_name}")
temp_dir.mkdir(exist_ok=True)
# 2. Копирование выбранных компонентов
components = components or ["tasks", "handlers", "defaults", "meta", "README.md"]
for component in components:
src = role_path / component
if src.exists():
if src.is_dir():
shutil.copytree(src, temp_dir / component)
else:
shutil.copy2(src, temp_dir / component)
# 3. Обработка секретов
if "vars" in components:
vars_file = role_path / "vars" / "main.yml"
if vars_file.exists():
if include_secrets:
# Копировать зашифрованным
shutil.copy2(vars_file, temp_dir / "vars" / "main.yml")
else:
# Создать без секретов
self.create_vars_without_secrets(vars_file, temp_dir / "vars" / "main.yml")
# 4. Создание .gitignore
self.create_gitignore(temp_dir)
# 5. Клонирование/обновление репозитория
repo_dir = Path(f"/tmp/repo_{role_name}")
if repo_dir.exists():
repo = Repo(repo_dir)
repo.remote().pull()
else:
repo = Repo.clone_from(repo_url, repo_dir, branch=branch)
# 6. Копирование файлов в репозиторий
for item in temp_dir.iterdir():
dest = repo_dir / item.name
if dest.exists():
if dest.is_dir():
shutil.rmtree(dest)
else:
dest.unlink()
if item.is_dir():
shutil.copytree(item, dest)
else:
shutil.copy2(item, dest)
# 7. Коммит и push
repo.git.add(A=True)
commit_message = f"{version}: {self.get_changelog_entry(role_name, version)}"
repo.index.commit(commit_message)
repo.remote().push()
# 8. Создание тега
if version:
repo.create_tag(f"v{version}")
repo.remote().push(tags=True)
# 9. Очистка
shutil.rmtree(temp_dir)
shutil.rmtree(repo_dir)
return {
"success": True,
"repo_url": repo_url,
"version": version,
"commit": repo.head.commit.hexsha
}
```
---
## 3. 📥 Импорт ролей из других репозиториев
### 3.1. Страница импорта роли
**URL:** `/roles/import`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Импорт роли из репозитория │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Шаг 1: Источник роли │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Тип источника: │ │
│ │ ○ Git репозиторий │ │
│ │ ● Ansible Galaxy │ │
│ │ ○ Локальный архив (tar.gz, zip) │ │
│ │ ○ URL (прямая ссылка на архив) │ │
│ │ │ │
│ │ ┌─ Git репозиторий ─────────────────────────┐ │ │
│ │ │ URL: │ │ │
│ │ │ [https://github.com/user/ansible-role-nginx]│ │ │
│ │ │ │ │ │
│ │ │ Ветка/тег: [main ▼] [v1.0.0] [latest] │ │ │
│ │ │ │ │ │
│ │ │ Путь к роли (если не в корне): │ │ │
│ │ │ [/roles/nginx] (оставить пустым если в корне)│ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─ Ansible Galaxy ───────────────────────────┐ │ │
│ │ │ Роль: [geerlingguy.nginx] │ │ │
│ │ │ Версия: [latest ▼] [1.0.0] [0.9.0] │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ [🔍 Проверить доступность] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Шаг 2: Настройка импорта │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Имя роли в проекте: │ │
│ │ [nginx] (автоматически из источника) │ │
│ │ │ │
│ │ Действие при конфликте: │ │
│ │ ○ Пропустить (не импортировать) │ │
│ │ ● Перезаписать существующую роль │ │
│ │ ○ Создать копию (nginx-imported) │ │
│ │ │ │
│ │ Импортировать: │ │
│ │ ☑ Структуру роли │ │
│ │ ☑ molecule конфигурацию (если есть) │ │
│ │ ☑ tests/ (тестовые playbook'и) │ │
│ │ ☐ .github/ (CI/CD workflows) │ │
│ │ ☐ Документацию (если отличается) │ │
│ │ │ │
│ │ Обработка зависимостей: │ │
│ │ ○ Импортировать зависимости автоматически │ │
│ │ ● Показать список для подтверждения │ │
│ │ ○ Пропустить зависимости │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📋 Шаг 3: Предпросмотр │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Информация о роли: │ │
│ │ ├─ Название: nginx │ │
│ │ ├─ Версия: 1.0.0 │ │
│ │ ├─ Автор: geerlingguy │ │
│ │ ├─ Описание: Install and configure nginx │ │
│ │ ├─ Платформы: Ubuntu, Debian, CentOS, RHEL │ │
│ │ └─ Зависимости: common (geerlingguy.common) │ │
│ │ │ │
│ │ Структура: │ │
│ │ roles/nginx/ │ │
│ │ ├── tasks/ (12 файлов) │ │
│ │ ├── handlers/ (2 файла) │ │
│ │ ├── defaults/ (1 файл) │ │
│ │ ├── templates/ (5 файлов) │ │
│ │ ├── meta/ (1 файл) │ │
│ │ └── README.md │ │
│ │ │ │
│ │ Файлов: 23 │ │
│ │ Размер: 1.8 MB │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [👁️ Предпросмотр файлов] [📥 Импортировать] │
└─────────────────────────────────────────────────────────┘
```
### 3.2. Процесс импорта
**После нажатия "Импортировать":**
```
┌─────────────────────────────────────────────────────────┐
│ Импорт роли: nginx │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 Прогресс: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ████████████████████░░ 95% │ │
│ │ Этап: Интеграция в проект │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📋 Этапы: │
│ ✅ Клонирование репозитория │ │
│ ✅ Извлечение роли │ │
│ ✅ Проверка структуры │ │
│ ✅ Копирование файлов │ │
│ 🟢 Интеграция в проект (обновление deploy.yml) │ │
│ ⏳ Импорт зависимостей │ │
│ │
│ 📝 Логи: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [10:40:15] Клонирование репозитория... │ │
│ │ [10:40:18] Извлечение роли nginx... │ │
│ │ [10:40:19] Проверка структуры... │ │
│ │ [10:40:20] Копирование 23 файлов... │ │
│ │ [10:40:22] Обновление roles/deploy.yml... │ │
│ │ [10:40:23] Импорт зависимости: common... │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [✅ Импорт завершен] [👁️ Просмотреть роль] │
└─────────────────────────────────────────────────────────┘
```
### 3.3. Реализация импорта
```python
# app/services/import_service.py
from git import Repo
import shutil
from pathlib import Path
import ansible_galaxy
class ImportService:
async def import_role(
self,
source: str,
source_type: str, # git, galaxy, archive, url
role_name: str = None,
version: str = None,
conflict_action: str = "overwrite" # skip, overwrite, copy
) -> dict:
"""Импорт роли из внешнего источника"""
role_path = Path(f"roles/{role_name}")
# Проверка конфликтов
if role_path.exists() and conflict_action == "skip":
return {"success": False, "error": "Роль уже существует"}
# Импорт в зависимости от типа
if source_type == "git":
await self.import_from_git(source, role_name, version)
elif source_type == "galaxy":
await self.import_from_galaxy(source, role_name, version)
elif source_type == "archive":
await self.import_from_archive(source, role_name)
elif source_type == "url":
await self.import_from_url(source, role_name)
# Обработка конфликтов
if conflict_action == "copy" and role_path.exists():
role_path = Path(f"roles/{role_name}-imported")
# Интеграция в проект
await self.integrate_role(role_name)
# Импорт зависимостей
dependencies = await self.get_role_dependencies(role_name)
if dependencies:
await self.import_dependencies(dependencies)
return {
"success": True,
"role_name": role_name,
"path": str(role_path),
"dependencies": dependencies
}
async def import_from_git(self, repo_url: str, role_name: str, version: str = None):
"""Импорт из Git репозитория"""
temp_dir = Path(f"/tmp/import_{role_name}")
temp_dir.mkdir(exist_ok=True)
# Клонирование
repo = Repo.clone_from(repo_url, temp_dir)
if version:
repo.git.checkout(version)
# Поиск роли в репозитории
role_source = self.find_role_in_repo(temp_dir, role_name)
# Копирование
role_path = Path(f"roles/{role_name}")
if role_path.exists():
shutil.rmtree(role_path)
shutil.copytree(role_source, role_path)
# Очистка
shutil.rmtree(temp_dir)
async def import_from_galaxy(self, role_id: str, role_name: str, version: str = None):
"""Импорт из Ansible Galaxy"""
# Использование ansible-galaxy
import subprocess
cmd = ["ansible-galaxy", "install", role_id]
if version:
cmd.extend(["--version", version])
subprocess.run(cmd, cwd="roles")
# Переименование если нужно
installed_name = role_id.replace(".", "-")
if installed_name != role_name:
Path(f"roles/{installed_name}").rename(f"roles/{role_name}")
async def integrate_role(self, role_name: str):
"""Интеграция роли в проект"""
# Обновление roles/deploy.yml
await self.update_deploy_yml(role_name)
# Создание molecule конфигурации если нужно
await self.setup_molecule_config(role_name)
# Обновление документации
await self.update_project_docs(role_name)
```
---
## 4. 📊 История команд и результатов
### 4.1. База данных для истории
```python
# app/db/models.py
class CommandHistory(Base):
__tablename__ = "command_history"
id = Column(Integer, primary_key=True)
command = Column(String, nullable=False) # make role test nginx
command_type = Column(String) # test, deploy, export, import
role_name = Column(String)
started_at = Column(DateTime, nullable=False)
completed_at = Column(DateTime)
status = Column(String) # success, failed, cancelled, running
duration = Column(Integer) # секунды
# Параметры
parameters = Column(JSON) # Все параметры команды
# Результаты
stdout = Column(Text)
stderr = Column(Text)
return_code = Column(Integer)
# Пользователь
user = Column(String)
ip_address = Column(String)
# Связи
test_result_id = Column(Integer, ForeignKey("test_results.id"))
deploy_id = Column(Integer, ForeignKey("deploy_history.id"))
```
### 4.2. Интерфейс истории команд
```
┌─────────────────────────────────────────────────────────┐
│ История команд │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Фильтры: │
│ [Тип: Все ▼] [Роль: Все ▼] [Статус: Все ▼] │
│ [Дата: Последние 7 дней ▼] │
│ │
│ 📊 Таблица команд: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Дата | Команда | Роль | Статус | Действия │ │
│ ├─────────────────────────────────────────────────┤ │
│ │ 15.01 10:30| test | nginx| ✅ | [👁️][📥]│
│ │ 15.01 09:15| deploy | nginx| ✅ | [👁️][📥]│
│ │ 15.01 08:45| export | nginx| ✅ | [👁️][📥]│
│ │ 14.01 16:30| import | docker| ✅ | [👁️][📥]│
│ │ 14.01 15:20| test | python| ❌ | [👁️][📥]│
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📈 Статистика: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Всего команд: 127 │ │
│ │ Успешных: 115 (90.6%) │ │
│ │ Ошибок: 12 (9.4%) │ │
│ │ Среднее время: 2m 15s │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [📥 Экспорт в CSV] [📥 Экспорт в JSON] │
└─────────────────────────────────────────────────────────┘
```
### 4.3. Детали команды
**При клике на команду:**
```
┌─────────────────────────────────────────────────────────┐
│ Детали команды: make role test nginx default │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Информация: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Команда: make role test nginx default │ │
│ │ Тип: test │ │
│ │ Роль: nginx │ │
│ │ Preset: default │ │
│ │ Статус: ✅ Успешно │ │
│ │ Начало: 15.01.2024 10:30:15 │ │
│ │ Завершение: 15.01.2024 10:32:30 │ │
│ │ Длительность: 2m 15s │ │
│ │ Пользователь: admin │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Параметры: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "role": "nginx", │ │
│ │ "preset": "default", │ │
│ │ "parallel": false, │ │
│ │ "lint": true │ │
│ │ } │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📄 Вывод (stdout): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [Показать полный вывод] │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ❌ Ошибки (stderr): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ (нет ошибок) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [📥 Скачать логи] [🔄 Повторить команду] │
└─────────────────────────────────────────────────────────┘
```
---
## 5. 🔄 Автоматическое сохранение истории
### 5.1. Middleware для логирования команд
```python
# app/core/command_logger.py
from app.db.database import SessionLocal
from app.db.models import CommandHistory
from datetime import datetime
class CommandLogger:
async def log_command(
self,
command: str,
command_type: str,
parameters: dict,
user: str = None
) -> int:
"""Сохранение команды в историю"""
db = SessionLocal()
history = CommandHistory(
command=command,
command_type=command_type,
role_name=parameters.get("role_name"),
started_at=datetime.now(),
status="running",
parameters=parameters,
user=user
)
db.add(history)
db.commit()
return history.id
async def update_command(
self,
history_id: int,
status: str,
stdout: str = None,
stderr: str = None,
return_code: int = None
):
"""Обновление результата команды"""
db = SessionLocal()
history = db.query(CommandHistory).filter_by(id=history_id).first()
history.completed_at = datetime.now()
history.status = status
history.stdout = stdout
history.stderr = stderr
history.return_code = return_code
history.duration = (history.completed_at - history.started_at).seconds
db.commit()
```
### 5.2. Интеграция с MakeExecutor
```python
# app/core/make_executor.py
class MakeExecutor:
def __init__(self):
self.logger = CommandLogger()
async def execute(
self,
command: str,
args: List[str] = None,
user: str = None
) -> Dict:
"""Выполнение команды с логированием"""
# Сохранение в историю
history_id = await self.logger.log_command(
command=command,
command_type=self.detect_command_type(command),
parameters=self.parse_parameters(command, args),
user=user
)
# Выполнение команды
cmd = ["make"] + command.split() + (args or [])
result = subprocess.run(
cmd,
capture_output=True,
text=True,
cwd=PROJECT_ROOT
)
# Обновление истории
await self.logger.update_command(
history_id=history_id,
status="success" if result.returncode == 0 else "failed",
stdout=result.stdout,
stderr=result.stderr,
return_code=result.returncode
)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr,
"history_id": history_id
}
```
---
## 📝 Резюме
Все функции доступны через веб-интерфейс:
1. **Деплой на живые серверы:**
- Выбор inventory
- Настройка переменных
- Live логи через WebSocket
- Сохранение истории
2. **Экспорт ролей:**
- В отдельные Git репозитории
- С версионированием и тегами
- С обработкой секретов
3. **Импорт ролей:**
- Из Git репозиториев
- Из Ansible Galaxy
- С автоматической интеграцией
4. **История команд:**
- Автоматическое сохранение всех команд
- Детальные логи
- Статистика и аналитика
Всё с live обновлениями, сохранением истории и удобным интерфейсом!
---
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru

View File

@@ -0,0 +1,734 @@
# Детали работы веб-интерфейса: тестирование и inventory
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🎯 Обзор
Этот документ описывает, как пользователь будет работать с тестированием ролей, выбором Docker образов, настройкой inventory и Molecule через веб-интерфейс.
---
## 1. 🐳 Выбор Docker образов и количества контейнеров
### 1.1. Страница создания/редактирования preset'а
**URL:** `/presets/create` или `/presets/{preset_name}/edit`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Создание Preset'а: "my-custom-test" │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Доступные образы: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ☑ Ubuntu 22.04 [inecs/ansible-lab:ubuntu22] │ │
│ │ ☐ Ubuntu 20.04 [inecs/ansible-lab:ubuntu20] │ │
│ │ ☑ Debian 12 [inecs/ansible-lab:debian12] │ │
│ │ ☐ Debian 11 [inecs/ansible-lab:debian11] │ │
│ │ ☑ CentOS 9 [inecs/ansible-lab:centos9] │ │
│ │ ☐ CentOS 8 [inecs/ansible-lab:centos8] │ │
│ │ ☐ RHEL 8 [inecs/ansible-lab:rhel] │ │
│ │ ☐ AlmaLinux 8 [inecs/ansible-lab:alma] │ │
│ │ ☐ Rocky Linux 8 [inecs/ansible-lab:rocky] │ │
│ │ ☐ ALT Linux 9 [inecs/ansible-lab:alt9] │ │
│ │ ☐ Astra Linux [inecs/ansible-lab:astra] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
Добавить кастомный образ: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Registry: [docker.io] │ │
│ │ Image: [my-custom/image:tag] │ │
│ │ [Добавить] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🖥️ Настройка хостов: │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Хост 1 │ │
│ │ ├─ Имя: [web1] │ │
│ │ ├─ Образ: [Ubuntu 22.04 ▼] │ │
│ │ ├─ Группы: [web, frontend] (можно добавить) │ │
│ │ └─ [🗑️ Удалить] │ │
│ ├─────────────────────────────────────────────────┤ │
│ │ Хост 2 │ │
│ │ ├─ Имя: [web2] │ │
│ │ ├─ Образ: [Debian 12 ▼] │ │
│ │ ├─ Группы: [web, backend] │ │
│ │ └─ [🗑️ Удалить] │ │
│ ├─────────────────────────────────────────────────┤ │
│ │ Хост 3 │ │
│ │ ├─ Имя: [db1] │ │
│ │ ├─ Образ: [CentOS 9 ▼] │ │
│ │ ├─ Группы: [database, backend] │ │
│ │ └─ [🗑️ Удалить] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [ Добавить хост] │
│ │
│ 📊 Предпросмотр: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Всего хостов: 3 │ │
│ │ Ubuntu 22.04: 1 │ │
│ │ Debian 12: 1 │ │
│ │ CentOS 9: 1 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [💾 Сохранить preset] [👁️ Предпросмотр YAML] │
└─────────────────────────────────────────────────────────┘
```
### 1.2. Быстрое создание preset'а при тестировании
**URL:** `/roles/{role_name}/test`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Тестирование роли: nginx │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Выбор preset'а: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ○ Использовать существующий preset │ │
│ │ [default ▼] [minimal] [all-images] │ │
│ │ │ │
│ │ ● Создать временный preset для этого теста │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Быстрый выбор: │ │ │
│ │ │ ☑ Ubuntu 22.04 [Количество: 2] │ │ │
│ │ │ ☑ Debian 12 [Количество: 2] │ │ │
│ │ │ ☐ CentOS 9 [Количество: 0] │ │ │
│ │ │ ☐ RHEL 8 [Количество: 0] │ │ │
│ │ │ │ │ │
│ │ │ Итого: 4 хоста │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Или детальная настройка: │ │
│ │ [Открыть редактор preset'а] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ⚙️ Параметры теста: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ☑ Параллельное выполнение [Количество: 2] │ │
│ │ ☑ Проверка синтаксиса (lint) │ │
│ │ ☑ Проверка идемпотентности │ │
│ │ ☐ Verbose режим │ │
│ │ ☐ Dry-run (только проверка) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [🚀 Запустить тест] │
└─────────────────────────────────────────────────────────┘
```
### 1.3. Визуальный редактор хостов (Drag & Drop)
**Интерфейс с возможностью перетаскивания:**
```
┌─────────────────────────────────────────────────────────┐
│ Редактор хостов │
├─────────────────────────────────────────────────────────┤
│ │
│ 📦 Доступные образы (перетащите для добавления): │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Ubuntu│ │Debian│ │CentOS│ │RHEL │ │
│ │ 22.04│ │ 12 │ │ 9 │ │ 8 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ │
│ 🖥️ Хосты (перетащите для изменения порядка): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ═══ web1 (Ubuntu 22.04) [web, frontend] [✏️][🗑️]│ │
│ ├─────────────────────────────────────────────────┤ │
│ │ ═══ web2 (Debian 12) [web, backend] [✏️][🗑️] │ │
│ ├─────────────────────────────────────────────────┤ │
│ │ ═══ db1 (CentOS 9) [database] [✏️][🗑️] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [ Добавить хост] [🔄 Сбросить] [💾 Сохранить] │
└─────────────────────────────────────────────────────────┘
```
**HTMX реализация:**
```html
<!-- Drag & Drop через HTMX и Alpine.js -->
<div
x-data="{ dragged: null }"
@dragstart="dragged = $event.target.dataset.image"
@drop.prevent="addHost(dragged)"
>
<!-- Образы для перетаскивания -->
<div
draggable="true"
data-image="ubuntu22"
class="draggable-image"
>
Ubuntu 22.04
</div>
<!-- Список хостов -->
<div
@drop="addHostFromDrag($event)"
class="hosts-list"
>
<!-- Хосты -->
</div>
</div>
```
---
## 2. 📝 Заполнение Inventory
### 2.1. Визуальный редактор Inventory
**URL:** `/inventory/edit` или `/presets/{preset_name}/inventory`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Редактор Inventory │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Группы хостов: │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [web_servers] │ │
│ │ ├─ web1 │ │
│ │ │ ├─ ansible_host: [172.17.0.2] │ │
│ │ │ ├─ ansible_user: [ansible] │ │
│ │ │ ├─ ansible_ssh_private_key_file: [~/.ssh/id_rsa]│
│ │ │ └─ [ Добавить переменную] │ │
│ │ │ │ │
│ │ └─ web2 │ │
│ │ ├─ ansible_host: [172.17.0.3] │ │
│ │ └─ ... │ │
│ │ │ │
│ │ [ Добавить хост в группу] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [database_servers] │ │
│ │ └─ db1 │ │
│ │ └─ ... │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [all:vars] (глобальные переменные) │ │
│ │ ├─ ansible_user: [ansible] │ │
│ │ ├─ ansible_ssh_private_key_file: [~/.ssh/id_rsa]│
│ │ ├─ ansible_python_interpreter: [/usr/bin/python3]│
│ │ └─ [ Добавить переменную] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📄 Предпросмотр INI формата: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [web_servers] │ │
│ │ web1 ansible_host=172.17.0.2 │ │
│ │ web2 ansible_host=172.17.0.3 │ │
│ │ │ │
│ │ [database_servers] │ │
│ │ db1 ansible_host=172.17.0.4 │ │
│ │ │ │
│ │ [all:vars] │ │
│ │ ansible_user=ansible │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [💾 Сохранить] [📥 Экспорт в файл] [📤 Импорт] │
└─────────────────────────────────────────────────────────┘
```
### 2.2. Автоматическая генерация Inventory из preset'а
**При создании preset'а автоматически генерируется inventory:**
```python
# app/services/inventory_service.py
class InventoryService:
def generate_from_preset(self, preset: dict) -> str:
"""Генерация inventory из preset'а"""
inventory = []
# Группировка хостов по группам
groups = {}
for host in preset['hosts']:
for group in host.get('groups', []):
if group not in groups:
groups[group] = []
groups[group].append(host)
# Формирование INI
for group_name, hosts in groups.items():
inventory.append(f"[{group_name}]")
for host in hosts:
# Получение IP из Docker контейнера
ip = self.get_container_ip(host['name'])
inventory.append(f"{host['name']} ansible_host={ip}")
inventory.append("")
# Глобальные переменные
inventory.append("[all:vars]")
inventory.append("ansible_user=ansible")
inventory.append("ansible_ssh_private_key_file=~/.ssh/id_rsa")
return "\n".join(inventory)
```
### 2.3. Редактирование Inventory для реальных серверов
**URL:** `/inventory/production/edit`
**Интерфейс для продакшн inventory:**
```
┌─────────────────────────────────────────────────────────┐
│ Production Inventory │
├─────────────────────────────────────────────────────────┤
│ │
│ ⚠️ Это inventory для реальных серверов! │
│ │
│ 📋 Группы: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [web_servers] │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ Хост: web1.example.com │ │ │
│ │ │ IP: [192.168.1.10] │ │ │
│ │ │ Пользователь: [deploy] │ │ │
│ │ │ SSH ключ: [~/.ssh/deploy_key] │ │ │
│ │ │ Порт: [22] │ │ │
│ │ │ Python: [/usr/bin/python3] │ │ │
│ │ │ [🔐 Тест подключения] │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ [ Добавить хост] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🔐 Безопасность: │
│ ☑ Использовать Vault для секретов │
│ ☑ Шифровать SSH ключи │
│ │
│ [💾 Сохранить] [🔒 Зашифровать в Vault] │
└─────────────────────────────────────────────────────────┘
```
---
## 3. 🧪 Тестирование в Molecule
### 3.1. Страница тестирования роли
**URL:** `/roles/{role_name}/test`
**Полный интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Тестирование роли: nginx │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Шаг 1: Выбор окружения │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ○ Использовать preset │ │
│ │ [default ▼] [minimal] [all-images] │ │
│ │ │ │
│ │ ● Создать кастомное окружение │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Образы и хосты: │ │ │
│ │ │ [См. раздел 1.1] │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Шаг 2: Настройка переменных роли │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Переменные из defaults/main.yml: │ │
│ │ │ │
│ │ nginx_version: [1.25.0] │ │
│ │ nginx_worker_processes: [auto] │ │
│ │ nginx_worker_connections: [1024] │ │
│ │ nginx_enabled: ☑ │ │
│ │ nginx_sites: │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ [ Добавить сайт] │ │ │
│ │ │ - name: example.com │ │ │
│ │ │ root: /var/www/html │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ │ │
│ │ [📥 Загрузить из файла] │ │
│ │ [💾 Сохранить как шаблон] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ⚙️ Шаг 3: Параметры Molecule │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Molecule сценарий: [default] │ │
│ │ │ │
│ │ Этапы тестирования: │ │
│ │ ☑ create (создание контейнеров) │ │
│ │ ☑ prepare (подготовка) │ │
│ │ ☑ converge (применение роли) │ │
│ │ ☑ idempotence (проверка идемпотентности) │ │
│ │ ☑ verify (проверка через testinfra) │ │
│ │ ☑ destroy (удаление контейнеров) │ │
│ │ │ │
│ │ Дополнительные опции: │ │
│ │ ☑ --destroy=never (не удалять после теста) │ │
│ │ ☐ --scenario-name=custom (кастомный сценарий) │ │
│ │ ☐ --driver-name=docker (драйвер) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🔍 Шаг 4: Настройка проверок (verify) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Использовать testinfra: ☑ │ │
│ │ │ │
│ │ Тесты для проверки: │ │
│ │ ☑ nginx установлен │ │
│ │ ☑ nginx запущен │ │
│ │ ☑ nginx слушает на порту 80 │ │
│ │ ☑ конфигурация валидна │ │
│ │ │ │
│ │ [ Добавить кастомный тест] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [🚀 Запустить тест] [💾 Сохранить конфигурацию] │
└─────────────────────────────────────────────────────────┘
```
### 3.2. Live мониторинг теста
**После запуска теста открывается страница с live логами:**
```
┌─────────────────────────────────────────────────────────┐
│ Тест роли: nginx | Статус: 🟢 Running │
├─────────────────────────────────────────────────────────┤
│ │
│ 📊 Прогресс: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ████████████░░░░░░░░ 60% │ │
│ │ Этап: converge (применение роли) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📋 Этапы: │
│ ✅ create - Создание контейнеров (5s) │
│ ✅ prepare - Подготовка (2s) │
│ 🟢 converge - Применение роли (в процессе...) │
│ ⏳ idempotence - Ожидание... │
│ ⏳ verify - Ожидание... │
│ ⏳ destroy - Ожидание... │
│ │
│ 📝 Логи (live): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [2024-01-15 10:30:15] TASK [nginx : Install] │ │
│ │ [2024-01-15 10:30:16] changed: [web1] │ │
│ │ [2024-01-15 10:30:17] TASK [nginx : Configure] │ │
│ │ [2024-01-15 10:30:18] changed: [web1] │ │
│ │ ... │ │
│ │ │ │
│ │ [Автоскролл: ☑] [Очистить] [📥 Скачать] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🖥️ Статус контейнеров: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ web1 (Ubuntu 22.04) 🟢 Running │ │
│ │ web2 (Debian 12) 🟢 Running │ │
│ │ db1 (CentOS 9) 🟢 Running │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [⏸️ Пауза] [⏹️ Остановить] [🔄 Перезапустить] │
└─────────────────────────────────────────────────────────┘
```
**WebSocket реализация:**
```python
# app/api/v1/endpoints/websocket.py
@router.websocket("/ws/test/{test_id}/logs")
async def test_logs_websocket(websocket: WebSocket, test_id: str):
await websocket.accept()
# Запуск molecule test с потоковым выводом
process = await asyncio.create_subprocess_exec(
"molecule", "test", "-s", "default",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
cwd=f"roles/{test_id}"
)
# Отправка логов в реальном времени
async for line in process.stdout:
await websocket.send_json({
"type": "log",
"stage": detect_stage(line), # create, converge, etc.
"data": line.decode(),
"timestamp": datetime.now().isoformat()
})
# Результат
await websocket.send_json({
"type": "complete",
"status": "success" if process.returncode == 0 else "failed"
})
```
### 3.3. Редактирование molecule.yml через интерфейс
**URL:** `/roles/{role_name}/molecule/edit`
**Интерфейс:**
```
┌─────────────────────────────────────────────────────────┐
│ Редактор molecule.yml для роли: nginx │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Вкладки: │
│ [Driver] [Platforms] [Provisioner] [Verifier] │
│ │
│ 🚗 Driver (Docker): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ driver: │ │
│ │ name: [docker ▼] │ │
│ │ options: │ │
│ │ privileged: ☑ │ │
│ │ volumes: │ │
│ │ - /sys/fs/cgroup:/sys/fs/cgroup:ro │ │
│ │ capabilities: │ │
│ │ - SYS_ADMIN │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 🖥️ Platforms (контейнеры): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [ Добавить платформу] │ │
│ │ │ │
│ │ Платформа 1: │ │
│ │ ├─ name: [web1] │ │
│ │ ├─ image: [inecs/ansible-lab:ubuntu22 ▼] │ │
│ │ ├─ pre_build_image: ☑ │ │
│ │ └─ [🗑️ Удалить] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 📝 Предпросмотр YAML: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ driver: │ │
│ │ name: docker │ │
│ │ platforms: │ │
│ │ - name: web1 │ │
│ │ image: inecs/ansible-lab:ubuntu22 │ │
│ │ pre_build_image: true │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [💾 Сохранить] [✅ Валидация] [🔄 Сбросить] │
└─────────────────────────────────────────────────────────┘
```
---
## 4. 🔄 Интеграция с существующими preset'ами
### 4.1. Использование preset'ов из `molecule/presets/`
**Автоматическое обнаружение preset'ов:**
```python
# app/services/preset_service.py
class PresetService:
def list_presets(self) -> List[dict]:
"""Список всех preset'ов из molecule/presets/"""
presets = []
preset_dir = Path("molecule/presets")
for preset_file in preset_dir.glob("*.yml"):
with open(preset_file) as f:
preset_data = yaml.safe_load(f)
presets.append({
"name": preset_file.stem,
"description": preset_data.get("description", ""),
"hosts_count": len(preset_data.get("hosts", [])),
"images": self.extract_images(preset_data),
"file": str(preset_file)
})
return presets
def load_preset(self, name: str) -> dict:
"""Загрузка preset'а"""
preset_file = Path(f"molecule/presets/{name}.yml")
with open(preset_file) as f:
return yaml.safe_load(f)
```
### 4.2. Редактирование существующих preset'ов
**Интерфейс редактирования:**
```
┌─────────────────────────────────────────────────────────┐
│ Редактирование preset'а: default │
├─────────────────────────────────────────────────────────┤
│ │
│ 📋 Информация: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Описание: [Стандартный preset для тестирования] │ │
│ │ Файл: molecule/presets/default.yml │ │
│ │ Хостов: 2 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [См. интерфейс из раздела 1.1] │
│ │
│ ⚠️ Внимание: Изменения сохраняются в файл! │
│ │
│ [💾 Сохранить] [📋 Создать копию] [🗑️ Удалить] │
└─────────────────────────────────────────────────────────┘
```
---
## 5. 🎯 Примеры использования
### 5.1. Быстрый тест на одном образе
**Сценарий:** Пользователь хочет быстро протестировать роль на Ubuntu 22.04
1. Переходит на `/roles/nginx/test`
2. Выбирает "Создать временный preset"
3. Ставит галочку только на "Ubuntu 22.04", количество: 1
4. Нажимает "Запустить тест"
5. Смотрит live логи
### 5.2. Тест на нескольких ОС
**Сценарий:** Пользователь хочет протестировать на Ubuntu, Debian и CentOS
1. Переходит на `/roles/nginx/test`
2. Выбирает "Создать временный preset"
3. Ставит галочки:
- Ubuntu 22.04 (2 хоста)
- Debian 12 (2 хоста)
- CentOS 9 (1 хост)
4. Настраивает переменные роли
5. Запускает тест
6. Смотрит результаты по каждому хосту
### 5.3. Создание и сохранение кастомного preset'а
**Сценарий:** Пользователь создает preset для тестирования веб-серверов
1. Переходит на `/presets/create`
2. Называет preset: "web-servers-test"
3. Добавляет хосты:
- web1 (Ubuntu 22.04) в группы [web, frontend]
- web2 (Debian 12) в группы [web, backend]
- lb1 (CentOS 9) в группы [web, loadbalancer]
4. Сохраняет preset
5. Использует его для тестирования: `/roles/nginx/test?preset=web-servers-test`
### 5.4. Редактирование inventory для продакшн
**Сценарий:** Пользователь настраивает inventory для реальных серверов
1. Переходит на `/inventory/production/edit`
2. Добавляет группу [web_servers]
3. Добавляет хосты с реальными IP
4. Настраивает SSH ключи
5. Тестирует подключение к каждому хосту
6. Сохраняет в Vault для безопасности
---
## 6. 🔧 Технические детали реализации
### 6.1. Генерация molecule.yml из preset'а
```python
# app/services/molecule_service.py
class MoleculeService:
def generate_molecule_yml(self, preset: dict, role_name: str) -> str:
"""Генерация molecule.yml из preset'а"""
molecule_config = {
"driver": {
"name": "docker"
},
"platforms": [],
"provisioner": {
"name": "ansible",
"inventory": {
"hosts": self.generate_inventory_hosts(preset)
}
},
"verifier": {
"name": "ansible"
}
}
# Преобразование хостов из preset'а в platforms
for host in preset['hosts']:
molecule_config['platforms'].append({
"name": host['name'],
"image": preset['images'][host['family']],
"pre_build_image": True,
**preset.get('systemd_defaults', {})
})
return yaml.dump(molecule_config)
```
### 6.2. Выполнение molecule команд
```python
# app/core/molecule_executor.py
class MoleculeExecutor:
async def test(
self,
role_name: str,
scenario: str = "default",
stream: bool = False
):
"""Запуск molecule test"""
cmd = [
"molecule", "test",
"-s", scenario,
"--destroy", "never" # Не удалять для просмотра
]
if stream:
# Для WebSocket
process = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
cwd=f"roles/{role_name}"
)
return process
else:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
cwd=f"roles/{role_name}"
)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr
}
```
---
## 📝 Резюме
Все действия по настройке тестирования выполняются через веб-интерфейс:
1. **Выбор образов и хостов:** Визуальный редактор с drag & drop
2. **Настройка inventory:** Автоматическая генерация + ручное редактирование
3. **Molecule тестирование:** Полный контроль через интерфейс с live логами
4. **Preset'ы:** Создание, редактирование, использование через UI
5. **Переменные ролей:** Формы для заполнения с валидацией
Всё интуитивно, визуально и без необходимости знать команды make или структуру файлов!
---
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru

View File

@@ -0,0 +1,702 @@
# Предложение по созданию веб-интерфейса для DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
**Дата:** 2024
## 🎯 Цель
Создать современный веб-интерфейс на FastAPI + HTMX для управления всеми возможностями проекта DevOpsLab через браузер.
---
## 🏗️ Архитектура решения
### Технологический стек
```
Frontend:
├── HTMX - динамическое обновление контента без перезагрузки
├── Alpine.js - легковесная реактивность
├── Tailwind CSS - современный UI
├── Jinja2 Templates - серверный рендеринг
└── Chart.js - визуализация данных
Backend:
├── FastAPI - современный Python веб-фреймворк
├── Pydantic - валидация данных
├── Celery + Redis - фоновые задачи (тестирование)
├── WebSocket - real-time обновления статуса
└── SQLite/PostgreSQL - хранение истории и метрик
Интеграция:
├── Вызов Makefile команд через subprocess
├── Парсинг результатов тестов
├── Управление Docker через API
└── Работа с Git через GitPython
```
### Структура проекта
```
app/
├── api/
│ ├── v1/
│ │ ├── endpoints/
│ │ │ ├── roles.py # Управление ролями
│ │ │ ├── presets.py # Управление preset'ами
│ │ │ ├── tests.py # Запуск тестов
│ │ │ ├── docker.py # Управление Docker
│ │ │ ├── vault.py # Управление секретами
│ │ │ ├── dashboard.py # Dashboard данные
│ │ │ └── websocket.py # WebSocket для real-time
│ │ └── router.py # Роутер API
│ └── dependencies.py # Зависимости (auth, db)
├── core/
│ ├── config.py # Конфигурация
│ ├── security.py # Безопасность
│ ├── make_executor.py # Выполнение Makefile команд
│ └── docker_client.py # Docker клиент
├── models/
│ ├── role.py # Модели ролей
│ ├── test.py # Модели тестов
│ └── preset.py # Модели preset'ов
├── services/
│ ├── role_service.py # Бизнес-логика ролей
│ ├── test_service.py # Бизнес-логика тестов
│ ├── preset_service.py # Бизнес-логика preset'ов
│ └── docker_service.py # Бизнес-логика Docker
├── templates/
│ ├── base.html # Базовый шаблон
│ ├── components/
│ │ ├── navbar.html
│ │ ├── sidebar.html
│ │ ├── role_card.html
│ │ ├── test_status.html
│ │ └── preset_selector.html
│ ├── pages/
│ │ ├── dashboard.html # Главная страница
│ │ ├── roles/
│ │ │ ├── list.html # Список ролей
│ │ │ ├── create.html # Создание роли
│ │ │ ├── edit.html # Редактирование роли
│ │ │ ├── detail.html # Детали роли
│ │ │ └── test.html # Тестирование роли
│ │ ├── presets/
│ │ │ ├── list.html
│ │ │ ├── create.html
│ │ │ └── edit.html
│ │ ├── tests/
│ │ │ ├── history.html # История тестов
│ │ │ ├── results.html # Результаты теста
│ │ │ └── live.html # Live тестирование
│ │ ├── docker/
│ │ │ ├── images.html # Docker образы
│ │ │ ├── containers.html # Контейнеры
│ │ │ └── build.html # Сборка образов
│ │ └── vault/
│ │ ├── list.html
│ │ └── edit.html
│ └── partials/
│ ├── role_form.html
│ ├── preset_form.html
│ └── test_logs.html
├── static/
│ ├── css/
│ │ └── main.css # Tailwind + кастомные стили
│ ├── js/
│ │ ├── htmx.min.js
│ │ ├── alpine.js
│ │ └── app.js # Кастомный JS
│ └── images/
│ └── logo.svg
├── tasks/
│ └── celery_tasks.py # Фоновые задачи Celery
├── db/
│ ├── models.py # SQLAlchemy модели
│ ├── database.py # Подключение к БД
│ └── migrations/ # Миграции
├── main.py # Точка входа FastAPI
└── requirements.txt # Зависимости Python
```
---
## 📱 Основные страницы и функциональность
### 1. Dashboard (Главная страница)
**URL:** `/`
**Функциональность:**
- Статистика по ролям (всего, протестировано, успешно)
- График успешности тестов за период
- Последние тесты с результатами
- Быстрые действия (создать роль, запустить тест)
- Статус Docker (образы, контейнеры)
- Активные задачи (Celery)
**HTMX фичи:**
- Автообновление статистики каждые 5 секунд
- Live статус тестов через WebSocket
- Интерактивные графики
### 2. Управление ролями
#### 2.1. Список ролей (`/roles`)
**Функциональность:**
- Карточки ролей с информацией:
- Имя роли
- Описание
- Последний тест (статус, дата)
- Количество переменных
- Поддерживаемые ОС
- Фильтры:
- По статусу теста
- По ОС
- По тегам
- Поиск по имени/описанию
- Действия:
- Создать новую роль
- Редактировать
- Удалить
- Запустить тест
- Просмотреть детали
**HTMX фичи:**
- Фильтрация без перезагрузки
- Модальные окна для действий
- Inline редактирование
#### 2.2. Создание роли (`/roles/create`)
**Функциональность:**
- Мастер создания роли (шаги):
1. **Базовая информация:**
- Имя роли
- Описание
- Тип роли (service, package, config, etc.)
- Шаблон (выбор из доступных)
2. **Поддерживаемые ОС:**
- Чекбоксы для каждой ОС
- Версии ОС
3. **Переменные:**
- Динамическое добавление переменных
- Тип переменной (string, int, bool, list, dict)
- Значение по умолчанию
- Описание
4. **Зависимости:**
- Выбор зависимых ролей
- Версии зависимостей
5. **Тесты:**
- Выбор preset'а для тестирования
- Настройки тестирования
6. **Превью и создание:**
- Превью структуры роли
- Кнопка создания
**HTMX фичи:**
- Прогресс-бар шагов
- Валидация на лету
- Сохранение черновика
- Предпросмотр структуры
#### 2.3. Редактирование роли (`/roles/{role_name}/edit`)
**Функциональность:**
- Редактирование tasks/main.yml (CodeMirror)
- Редактирование defaults/main.yml (форма с переменными)
- Редактирование handlers/main.yml
- Управление templates и files
- Редактирование meta/main.yml
- Редактирование README.md (Markdown редактор)
**HTMX фичи:**
- Автосохранение
- Синтаксис-подсветка
- Предпросмотр Markdown
- Валидация YAML
#### 2.4. Детали роли (`/roles/{role_name}`)
**Функциональность:**
- Вкладки:
- **Обзор:** описание, метаданные, статистика
- **Переменные:** таблица всех переменных с описаниями
- **Задачи:** список задач с описаниями
- **Тесты:** история тестирования
- **Зависимости:** граф зависимостей
- **Документация:** README.md
**HTMX фичи:**
- Переключение вкладок без перезагрузки
- Интерактивный граф зависимостей
- Фильтрация истории тестов
#### 2.5. Тестирование роли (`/roles/{role_name}/test`)
**Функциональность:**
- Выбор preset'а
- Настройка переменных (форма)
- Параметры теста:
- Параллельность
- Verbose режим
- Только lint
- Только синтаксис
- Запуск теста
- Live логи (WebSocket)
- Прогресс выполнения
- Результаты:
- Статус (успех/ошибка)
- Время выполнения
- Детальные логи
- Сравнение с предыдущим тестом
**HTMX фичи:**
- Live обновление логов
- Прогресс-бар
- Автоматическое обновление статуса
- Скачивание логов
### 3. Управление preset'ами (`/presets`)
**Функциональность:**
- Список preset'ов
- Создание preset'а:
- Визуальный редактор хостов
- Drag & drop для изменения порядка
- Выбор образов
- Настройка сети
- Редактирование preset'а
- Копирование preset'а
- Удаление preset'а
- Предпросмотр preset'а (YAML)
**HTMX фичи:**
- Визуальный редактор
- Предпросмотр YAML
- Валидация
### 4. История тестов (`/tests`)
**Функциональность:**
- Таблица всех тестов:
- Роль
- Preset
- Статус
- Дата/время
- Длительность
- Действия (просмотр, скачать логи)
- Фильтры:
- По роли
- По статусу
- По дате
- По preset'у
- Графики:
- Успешность по времени
- Время выполнения
- Распределение по ОС
**HTMX фичи:**
- Пагинация
- Сортировка
- Экспорт в CSV/JSON
### 5. Управление Docker (`/docker`)
**Функциональность:**
- Список образов:
- Статус (локально/в registry)
- Размер
- Дата создания
- Архитектуры
- Действия (pull, push, build, delete)
- Список контейнеров:
- Статус
- Образ
- Порты
- Действия (start, stop, logs, exec)
- Сборка образов:
- Выбор образа
- Параметры сборки
- Прогресс сборки
- Registry настройки
**HTMX фичи:**
- Live обновление статуса
- Прогресс сборки
- Модальные окна для действий
### 6. Управление секретами (`/vault`)
**Функциональность:**
- Список зашифрованных файлов
- Редактирование секретов:
- Форма с полями
- Шифрование/расшифровка
- Смена пароля
- Поиск секретов в коде
- Аудит безопасности
**HTMX фичи:**
- Безопасное редактирование
- Валидация перед шифрованием
---
## 🔧 Технические детали
### FastAPI структура
```python
# app/main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from app.api.v1.router import api_router
app = FastAPI(
title="DevOpsLab Web Interface",
description="Веб-интерфейс для управления Ansible ролями",
version="1.0.0"
)
# Статические файлы
app.mount("/static", StaticFiles(directory="app/static"), name="static")
# Шаблоны
templates = Jinja2Templates(directory="app/templates")
# API роуты
app.include_router(api_router, prefix="/api/v1")
# Web роуты
@app.get("/")
async def dashboard(request: Request):
return templates.TemplateResponse("pages/dashboard.html", {"request": request})
```
### Выполнение Makefile команд
```python
# app/core/make_executor.py
import subprocess
import asyncio
from typing import Optional, Dict, List
class MakeExecutor:
"""Выполнение Makefile команд с отслеживанием прогресса"""
async def execute(
self,
command: str,
args: List[str] = None,
stream: bool = False
) -> Dict:
"""Выполнение команды make"""
cmd = ["make"] + command.split() + (args or [])
if stream:
# Для live логов через WebSocket
process = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
return process
else:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
cwd=PROJECT_ROOT
)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
}
```
### WebSocket для live обновлений
```python
# app/api/v1/endpoints/websocket.py
from fastapi import WebSocket
from app.core.make_executor import MakeExecutor
@app.websocket("/ws/test/{test_id}")
async def test_websocket(websocket: WebSocket, test_id: str):
await websocket.accept()
executor = MakeExecutor()
process = await executor.execute(
f"role test {test_id}",
stream=True
)
async for line in process.stdout:
await websocket.send_json({
"type": "log",
"data": line.decode()
})
await websocket.send_json({
"type": "complete",
"status": "success"
})
```
### Celery для фоновых задач
```python
# app/tasks/celery_tasks.py
from celery import Celery
from app.core.config import settings
celery_app = Celery(
"devopslab",
broker=settings.REDIS_URL,
backend=settings.REDIS_URL
)
@celery_app.task
def run_role_test(role_name: str, preset: str):
"""Запуск теста роли в фоне"""
executor = MakeExecutor()
result = executor.execute(f"role test {preset}")
return result
```
### База данных для истории
```python
# app/db/models.py
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text
from app.db.database import Base
class TestResult(Base):
__tablename__ = "test_results"
id = Column(Integer, primary_key=True)
role_name = Column(String, nullable=False)
preset = Column(String, nullable=False)
status = Column(String) # success, failed, running
started_at = Column(DateTime)
completed_at = Column(DateTime)
duration = Column(Integer) # секунды
logs = Column(Text)
stdout = Column(Text)
stderr = Column(Text)
```
---
## 🎨 UI/UX дизайн
### Цветовая схема
```css
/* Tailwind конфигурация */
colors: {
primary: '#3B82F6', // Синий
secondary: '#10B981', // Зеленый
danger: '#EF4444', // Красный
warning: '#F59E0B', // Оранжевый
dark: '#1F2937', // Темный
light: '#F9FAFB' // Светлый
}
```
### Компоненты
1. **Navbar:**
- Логотип
- Навигация (Dashboard, Roles, Presets, Tests, Docker, Vault)
- Уведомления
- Профиль пользователя
2. **Sidebar:**
- Быстрые действия
- Последние тесты
- Статистика
3. **Card компонент:**
- Заголовок
- Контент
- Действия (кнопки)
4. **Modal компонент:**
- HTMX для открытия/закрытия
- Формы внутри
5. **Table компонент:**
- Сортировка
- Фильтрация
- Пагинация
6. **Status badges:**
- Успех (зеленый)
- Ошибка (красный)
- В процессе (синий)
- Пропущен (серый)
---
## 📦 Зависимости
```txt
# app/requirements.txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
jinja2==3.1.2
python-multipart==0.0.6
pydantic==2.5.0
pydantic-settings==2.1.0
# HTMX и статика
jinja2-partials==0.3.0
# База данных
sqlalchemy==2.0.23
alembic==1.12.1
asyncpg==0.29.0 # Для PostgreSQL
# Фоновые задачи
celery==5.3.4
redis==5.0.1
# WebSocket
websockets==12.0
# Docker
docker==6.1.3
# Git
GitPython==3.1.40
# Утилиты
python-dotenv==1.0.0
pyyaml==6.0.1
```
---
## 🚀 План реализации
### Фаза 1: Базовая инфраструктура (1 неделя)
- ✅ Настройка FastAPI проекта
- ✅ Базовая структура папок
- ✅ Интеграция с Makefile (MakeExecutor)
- ✅ Базовые шаблоны (base.html, navbar, sidebar)
- ✅ Dashboard страница (статичная)
### Фаза 2: Управление ролями (2 недели)
- ✅ Список ролей
- ✅ Создание роли (мастер)
- ✅ Редактирование роли
- ✅ Детали роли
- ✅ Интеграция с Git
### Фаза 3: Тестирование (2 недели)
- ✅ Запуск тестов через интерфейс
- ✅ WebSocket для live логов
- ✅ История тестов
- ✅ Результаты тестов
### Фаза 4: Preset'ы и Docker (1 неделя)
- ✅ Управление preset'ами
- ✅ Управление Docker образами
- ✅ Управление контейнерами
### Фаза 5: Полировка (1 неделя)
- ✅ Улучшение UI/UX
- ✅ Оптимизация производительности
- ✅ Документация
- ✅ Тестирование
---
## 🔐 Безопасность
1. **Аутентификация:**
- JWT токены
- Сессии
- OAuth2 (опционально)
2. **Авторизация:**
- Роли пользователей
- Права доступа
3. **Валидация:**
- Pydantic схемы
- Санитизация входных данных
4. **Защита от атак:**
- CSRF токены
- Rate limiting
- SQL injection защита
---
## 📊 Метрики и мониторинг
1. **Производительность:**
- Время ответа API
- Использование памяти
- CPU нагрузка
2. **Использование:**
- Количество пользователей
- Популярные роли
- Частота тестирования
3. **Ошибки:**
- Логирование ошибок
- Sentry интеграция (опционально)
---
## 🎯 Преимущества решения
1. **Удобство:**
- Не нужно знать команды make
- Визуальный интерфейс
- Интуитивная навигация
2. **Производительность:**
- HTMX - минимальный JS
- Серверный рендеринг
- Быстрая загрузка
3. **Расширяемость:**
- Модульная архитектура
- Легко добавлять новые функции
- API для интеграций
4. **Современность:**
- FastAPI - быстрый и современный
- HTMX - простота и мощность
- Tailwind - красивый UI
---
## 📝 Следующие шаги
1. Создать git ветку: `git checkout -b feature/web-interface`
2. Настроить структуру проекта
3. Реализовать базовую инфраструктуру
4. Постепенно добавлять функциональность
5. Тестировать и улучшать
---
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru

View File

@@ -0,0 +1,306 @@
# Быстрый старт веб-интерфейса DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🚀 Быстрый старт
### 1. Создание git ветки
```bash
git checkout -b feature/web-interface
git push -u origin feature/web-interface
```
### 2. Структура проекта
```
app/
├── main.py # FastAPI приложение
├── api/v1/endpoints/ # API endpoints
├── templates/ # HTMX шаблоны
├── static/ # CSS, JS
└── core/ # Ядро (MakeExecutor, DockerClient)
```
### 3. Основные компоненты
#### MakeExecutor - выполнение Makefile команд
```python
# app/core/make_executor.py
import subprocess
from typing import Dict, List
class MakeExecutor:
def execute(self, command: str, args: List[str] = None) -> Dict:
cmd = ["make"] + command.split() + (args or [])
result = subprocess.run(cmd, capture_output=True, text=True)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr
}
```
#### FastAPI роуты
```python
# app/api/v1/endpoints/roles.py
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from app.core.make_executor import MakeExecutor
router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
executor = MakeExecutor()
@router.get("/roles", response_class=HTMLResponse)
async def list_roles(request: Request):
# Получаем список ролей через make
result = executor.execute("role list")
roles = parse_roles(result["stdout"])
return templates.TemplateResponse(
"pages/roles/list.html",
{"request": request, "roles": roles}
)
@router.post("/roles/{role_name}/test")
async def test_role(role_name: str, preset: str = "default"):
# Запуск теста
result = executor.execute(f"role test {preset}")
return {"status": "success" if result["success"] else "failed"}
```
#### HTMX шаблон
```html
<!-- app/templates/pages/roles/list.html -->
{% extends "base.html" %}
{% block content %}
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
{% for role in roles %}
<div class="card">
<h3>{{ role.name }}</h3>
<p>{{ role.description }}</p>
<button
hx-post="/api/v1/roles/{{ role.name }}/test"
hx-target="#test-results"
class="btn-primary">
Запустить тест
</button>
</div>
{% endfor %}
</div>
{% endblock %}
```
### 4. Примеры страниц
#### Dashboard
```html
<!-- app/templates/pages/dashboard.html -->
<div class="dashboard">
<div class="stats">
<div class="stat-card">
<h3>Всего ролей</h3>
<p hx-get="/api/v1/stats/roles" hx-trigger="every 5s">
{{ total_roles }}
</p>
</div>
</div>
<div class="recent-tests">
<h2>Последние тесты</h2>
<div id="test-list"
hx-get="/api/v1/tests/recent"
hx-trigger="every 10s">
<!-- Загружается через HTMX -->
</div>
</div>
</div>
```
#### Создание роли
```html
<!-- app/templates/pages/roles/create.html -->
<form hx-post="/api/v1/roles/create" hx-target="#result">
<div class="step" id="step-1">
<h3>Шаг 1: Базовая информация</h3>
<input name="name" placeholder="Имя роли" required>
<textarea name="description" placeholder="Описание"></textarea>
<select name="template">
<option value="service">Service</option>
<option value="package">Package</option>
<option value="config">Config</option>
</select>
<button type="button" hx-get="/api/v1/roles/create/step/2">
Далее
</button>
</div>
<div class="step" id="step-2" style="display:none;">
<h3>Шаг 2: Переменные</h3>
<div id="variables">
<div class="variable-row">
<input name="var_name" placeholder="Имя переменной">
<input name="var_value" placeholder="Значение">
<select name="var_type">
<option value="string">String</option>
<option value="int">Integer</option>
<option value="bool">Boolean</option>
</select>
</div>
</div>
<button type="button" hx-post="/api/v1/roles/create/add-variable">
Добавить переменную
</button>
<button type="submit">Создать роль</button>
</div>
</form>
```
### 5. WebSocket для live логов
```python
# app/api/v1/endpoints/websocket.py
from fastapi import WebSocket
from app.core.make_executor import MakeExecutor
@router.websocket("/ws/test/{test_id}")
async def test_websocket(websocket: WebSocket, test_id: str):
await websocket.accept()
executor = MakeExecutor()
# Запуск теста с потоковым выводом
process = await executor.execute_stream(f"role test {test_id}")
async for line in process.stdout:
await websocket.send_json({
"type": "log",
"data": line.decode()
})
await websocket.send_json({"type": "complete"})
```
```javascript
// app/static/js/test-live.js
const ws = new WebSocket('ws://localhost:8000/ws/test/nginx');
const logContainer = document.getElementById('test-logs');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'log') {
logContainer.innerHTML += `<div>${data.data}</div>`;
}
};
```
### 6. Запуск приложения
```python
# app/main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from app.api.v1.endpoints import roles, presets, tests
app = FastAPI(title="DevOpsLab Web Interface")
# Статика
app.mount("/static", StaticFiles(directory="app/static"), name="static")
# Шаблоны
templates = Jinja2Templates(directory="app/templates")
# Роуты
app.include_router(roles.router, prefix="/api/v1")
app.include_router(presets.router, prefix="/api/v1")
app.include_router(tests.router, prefix="/api/v1")
@app.get("/")
async def dashboard(request: Request):
return templates.TemplateResponse("pages/dashboard.html", {"request": request})
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
### 7. Docker Compose для разработки
```yaml
# docker-compose.dev.yml
version: '3.8'
services:
web:
build: ./app
ports:
- "8000:8000"
volumes:
- ./app:/app
- .:/workspace
environment:
- PROJECT_ROOT=/workspace
command: uvicorn main:app --reload --host 0.0.0.0
redis:
image: redis:7-alpine
ports:
- "6379:6379"
celery:
build: ./app
command: celery -A tasks.celery_tasks worker --loglevel=info
volumes:
- ./app:/app
- .:/workspace
depends_on:
- redis
```
### 8. Команды для разработки
```bash
# Установка зависимостей
cd app
pip install -r requirements.txt
# Запуск в режиме разработки
uvicorn main:app --reload
# Запуск через Docker
docker-compose -f docker-compose.dev.yml up
# Запуск Celery worker
celery -A tasks.celery_tasks worker --loglevel=info
```
---
## 📋 Чек-лист реализации
- [ ] Создать git ветку
- [ ] Настроить структуру проекта
- [ ] Реализовать MakeExecutor
- [ ] Создать базовые шаблоны
- [ ] Реализовать Dashboard
- [ ] Реализовать список ролей
- [ ] Реализовать создание роли
- [ ] Реализовать тестирование роли
- [ ] Добавить WebSocket для live логов
- [ ] Настроить Celery для фоновых задач
- [ ] Добавить базу данных для истории
- [ ] Улучшить UI/UX
- [ ] Добавить аутентификацию
- [ ] Написать документацию
---
**Полная версия:** [WEB_INTERFACE_PROPOSAL.md](WEB_INTERFACE_PROPOSAL.md)

View File

@@ -0,0 +1,133 @@
# Статус развертывания веб-интерфейса
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
**Дата:** 2024-02-15
## ✅ Статус: РАБОТАЕТ
### Проверка работоспособности
```bash
# Health check
curl http://localhost:8000/health
# Ответ: {"status":"ok","version":"1.0.0"}
# Главная страница
curl http://localhost:8000/
# Ответ: HTML страница Dashboard
# API статистики
curl http://localhost:8000/api/v1/stats/roles
# Ответ: {"count":4}
```
### Запущенные контейнеры
```bash
docker-compose ps
```
Все контейнеры должны быть в статусе `Up`:
-`devopslab-web` - Веб-интерфейс (порт 8000)
-`devopslab-redis` - Redis (порт 6379)
-`devopslab-celery-worker` - Celery worker
-`devopslab-celery-beat` - Celery beat
## 🔧 Исправленные проблемы
### 1. Конфликт зависимостей Redis
**Проблема:** `celery[redis] 5.3.4` требует `redis <5.0.0`, но был указан `redis==5.0.1`
**Решение:** Изменена версия на `redis==4.6.0`
### 2. Ошибка импорта модулей
**Проблема:** `ModuleNotFoundError: No module named 'app'`
**Решение:**
- Изменена структура в Dockerfile: файлы копируются в `/app/app/`
- Добавлен `PYTHONPATH=/app` в переменные окружения
- Изменена команда запуска на `python -m uvicorn app.main:app`
- Создан `app/app/__init__.py` для правильного пакета
### 3. Команды Celery
**Проблема:** Celery не мог найти модуль tasks
**Решение:** Изменены команды на `celery -A app.tasks.celery_tasks`
## 📋 Структура в контейнере
```
/app/ # Рабочая директория
├── app/ # Пакет приложения
│ ├── __init__.py
│ ├── main.py # Точка входа (было в корне)
│ ├── api/
│ ├── core/
│ ├── models/
│ ├── services/
│ ├── templates/
│ ├── static/
│ ├── tasks/
│ └── db/
├── logs/ # Логи
└── requirements.txt
```
## 🚀 Команды для работы
```bash
# Запуск
cd app
make up
# или
docker-compose up -d
# Остановка
make down
# или
docker-compose down
# Логи
make logs
# или
docker-compose logs -f web
# Shell в контейнере
make shell
# или
docker-compose exec web bash
# Статус
make status
# или
docker-compose ps
```
## 🌐 Доступ
- **Веб-интерфейс:** http://localhost:8000
- **API документация:** http://localhost:8000/api/docs
- **ReDoc:** http://localhost:8000/api/redoc
- **Health check:** http://localhost:8000/health
## ✅ Проверка работоспособности
1. ✅ Контейнеры запускаются
2.Веб-интерфейс отвечает на запросы
3. ✅ API endpoints работают
4. ✅ Redis подключен
5. ✅ Celery worker запущен
6. ✅ Доступ к Docker socket работает
7. ✅ Монтирование проекта работает
## 📝 Следующие шаги
1. Реализовать список ролей
2. Реализовать создание роли
3. Реализовать тестирование с live логами
4. Добавить базу данных для истории
---
**Статус:** ✅ Готово к разработке

View File

@@ -0,0 +1,219 @@
# Запуск веб-интерфейса в Docker
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🐳 Быстрый старт
### 1. Запуск через docker-compose
```bash
cd app
make up
# или
docker-compose up -d
```
### 2. Проверка статуса
```bash
make status
# или
docker-compose ps
```
### 3. Просмотр логов
```bash
make logs
# или
docker-compose logs -f web
```
### 4. Открыть в браузере
- Веб-интерфейс: http://localhost:8000
- API документация: http://localhost:8000/api/docs
## 📋 Доступные команды
```bash
make build # Собрать образы
make up # Запустить контейнеры
make down # Остановить контейнеры
make restart # Перезапустить контейнеры
make logs # Показать логи веб-интерфейса
make logs-all # Показать логи всех сервисов
make shell # Открыть shell в контейнере web
make shell-celery # Открыть shell в контейнере celery-worker
make rebuild # Пересобрать и перезапустить
make clean # Очистить контейнеры и volumes
make status # Показать статус контейнеров
```
## 🏗️ Архитектура
### Сервисы
1. **web** - Веб-интерфейс FastAPI
- Порт: 8000
- Доступ к Docker socket для управления контейнерами
- Монтирование проекта для доступа к roles, molecule
2. **redis** - Redis для Celery
- Порт: 6379
- Хранение задач и результатов
3. **celery-worker** - Celery worker для фоновых задач
- Выполнение тестов, деплоев в фоне
- Доступ к Docker socket
4. **celery-beat** - Celery beat для периодических задач
- Опционально, для планирования задач
### Volumes
- `/workspace` - Весь проект DevOpsLab (монтируется из родительской директории)
- `/app` - Код веб-интерфейса (для hot reload)
- `/var/run/docker.sock` - Docker socket для управления контейнерами
### Networks
- `devopslab-network` - Внутренняя сеть для связи между сервисами
## 🔧 Настройка
### Переменные окружения
Все настройки через переменные окружения в `docker-compose.yml`:
- `PROJECT_ROOT=/workspace` - Корень проекта
- `DOCKER_HOST=unix:///var/run/docker.sock` - Docker socket
- `REDIS_URL=redis://redis:6379/0` - Redis для Celery
### Переопределение для разработки
Создайте `docker-compose.override.yml` для локальных настроек:
```yaml
version: '3.8'
services:
web:
ports:
- "8000:8000"
volumes:
- ./logs:/app/logs
```
## 🐛 Troubleshooting
### Ошибка: Cannot connect to Docker daemon
Убедитесь, что Docker socket доступен:
```bash
ls -la /var/run/docker.sock
```
### Ошибка: Permission denied
Добавьте пользователя в группу docker:
```bash
sudo usermod -aG docker $USER
```
Или запустите с sudo (не рекомендуется):
```bash
sudo docker-compose up -d
```
### Ошибка: Port already in use
Измените порт в `docker-compose.yml`:
```yaml
ports:
- "8001:8000" # Внешний порт:внутренний порт
```
### Просмотр логов всех сервисов
```bash
docker-compose logs -f
```
### Перезапуск конкретного сервиса
```bash
docker-compose restart web
docker-compose restart celery-worker
```
## 📊 Мониторинг
### Статус контейнеров
```bash
docker-compose ps
```
### Использование ресурсов
```bash
docker stats devopslab-web devopslab-redis devopslab-celery-worker
```
### Логи Redis
```bash
docker-compose logs redis
```
## 🔄 Обновление
### Обновление кода
```bash
# Остановить
make down
# Обновить код (git pull, etc.)
# Пересобрать и запустить
make rebuild
```
### Обновление зависимостей
```bash
# Отредактировать requirements.txt
# Пересобрать образ
make rebuild
```
## 🧹 Очистка
### Очистка контейнеров и volumes
```bash
make clean
```
### Очистка образов
```bash
docker-compose down --rmi all
```
### Полная очистка
```bash
make clean
docker system prune -a
```
## 📝 Примечания
- Веб-интерфейс имеет доступ к Docker socket для управления контейнерами тестирования
- Весь проект монтируется в `/workspace` для доступа к roles, molecule, etc.
- Redis данные сохраняются в volume `redis-data`
- Для разработки используйте `docker-compose.override.yml`

View File

@@ -0,0 +1,80 @@
# Быстрый старт веб-интерфейса в Docker
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🚀 Запуск за 3 шага
### 1. Перейти в директорию app
```bash
cd app
```
### 2. Запустить docker-compose
```bash
make up
# или
docker-compose up -d
```
### 3. Открыть в браузере
http://localhost:8000
## ✅ Готово!
Веб-интерфейс запущен и готов к работе. Ничего не нужно устанавливать на локальную машину - всё работает в Docker!
## 📋 Что запускается
- **web** - Веб-интерфейс на порту 8000
- **redis** - Redis для Celery на порту 6379
- **celery-worker** - Worker для фоновых задач
- **celery-beat** - Планировщик задач (опционально)
## 🔧 Полезные команды
```bash
# Просмотр логов
make logs
# Остановка
make down
# Перезапуск
make restart
# Shell в контейнере
make shell
# Статус
make status
```
## 🐛 Если что-то не работает
### Проверьте Docker
```bash
docker ps
docker-compose ps
```
### Проверьте логи
```bash
docker-compose logs web
docker-compose logs redis
```
### Пересоберите
```bash
make rebuild
```
## 📚 Подробная документация
См. `README_DOCKER.md` для полной документации.

View File

@@ -0,0 +1,153 @@
# Быстрый старт веб-интерфейса DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## ✅ Что уже сделано
1. ✅ Создана git ветка `feature/web-interface`
2. ✅ Создана базовая структура проекта
3. ✅ Настроен FastAPI с базовыми шаблонами
4. ✅ Реализован MakeExecutor для выполнения команд
5. ✅ Создан Dashboard с базовой статистикой
6. ✅ Настроены HTMX шаблоны
## 🚀 Запуск
### 1. Установка зависимостей
```bash
cd app
pip install -r requirements.txt
```
### 2. Настройка окружения
```bash
# Скопируйте пример конфигурации
cp env.example .env
# Отредактируйте .env (особенно PROJECT_ROOT)
# PROJECT_ROOT должен указывать на корень проекта DevOpsLab
```
### 3. Запуск приложения
```bash
# Из директории app/
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# Или через Python
python main.py
```
### 4. Открыть в браузере
- Веб-интерфейс: http://localhost:8000
- API документация: http://localhost:8000/api/docs
## 📁 Структура проекта
```
app/
├── api/v1/endpoints/ # API endpoints
│ └── stats.py # ✅ Статистика (реализовано)
├── core/ # Ядро
│ ├── config.py # ✅ Конфигурация
│ └── make_executor.py # ✅ Выполнение Makefile команд
├── templates/ # HTMX шаблоны
│ ├── base.html # ✅ Базовый шаблон
│ ├── components/ # ✅ Компоненты (navbar, sidebar)
│ └── pages/ # Страницы
│ └── dashboard.html # ✅ Dashboard
├── static/ # Статические файлы
│ ├── css/main.css # ✅ Стили
│ └── js/app.js # ✅ JavaScript
└── main.py # ✅ Точка входа FastAPI
```
## 📋 Следующие шаги
### Приоритет 1: Базовый функционал
- [ ] Реализовать список ролей (`/roles`)
- [ ] Реализовать создание роли (`/roles/create`)
- [ ] Реализовать тестирование роли (`/roles/{name}/test`)
### Приоритет 2: Preset'ы и тестирование
- [ ] Управление preset'ами (`/presets`)
- [ ] WebSocket для live логов тестирования
- [ ] История тестов (`/tests`)
### Приоритет 3: Деплой и импорт/экспорт
- [ ] Деплой на живые серверы (`/roles/{name}/deploy`)
- [ ] Экспорт ролей (`/roles/{name}/export`)
- [ ] Импорт ролей (`/roles/import`)
### Приоритет 4: Дополнительно
- [ ] База данных для истории
- [ ] Celery для фоновых задач
- [ ] Аутентификация
## 🔧 Разработка
### Добавление нового endpoint
1. Создайте файл в `app/api/v1/endpoints/`
2. Создайте роутер:
```python
from fastapi import APIRouter
router = APIRouter()
@router.get("/example")
async def example():
return {"message": "Hello"}
```
3. Подключите в `app/api/v1/router.py`:
```python
from app.api.v1.endpoints import example
api_router.include_router(example.router, prefix="/example")
```
### Добавление новой страницы
1. Создайте шаблон в `app/templates/pages/`
2. Добавьте роут в `app/main.py`:
```python
@app.get("/example", response_class=HTMLResponse)
async def example_page(request: Request):
return templates.TemplateResponse("pages/example.html", {"request": request})
```
## 📚 Документация
- `docs/WEB_INTERFACE_PROPOSAL.md` - Полное предложение
- `docs/WEB_INTERFACE_DETAILS.md` - Детали работы
- `docs/WEB_INTERFACE_DEPLOY_IMPORT_EXPORT.md` - Деплой, импорт, экспорт
- `docs/WEB_INTERFACE_QUICKSTART.md` - Быстрый старт
## 🐛 Troubleshooting
### Ошибка: ModuleNotFoundError
Убедитесь, что вы установили зависимости:
```bash
pip install -r requirements.txt
```
### Ошибка: PROJECT_ROOT не найден
Проверьте `.env` файл и убедитесь, что `PROJECT_ROOT` указывает на правильный путь.
### Ошибка: Порт уже занят
Измените порт в `.env` или убейте процесс:
```bash
lsof -ti:8000 | xargs kill
```
## 📝 Примечания
- Проект находится в ветке `feature/web-interface`
- Все изменения должны быть в директории `app/`
- Не изменяйте существующий код проекта (roles/, molecule/, etc.)

View File

@@ -0,0 +1,74 @@
# DevOpsLab Web Interface
Веб-интерфейс для управления Ansible ролями в проекте DevOpsLab.
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## 🚀 Быстрый старт
### Установка зависимостей
```bash
cd app
pip install -r requirements.txt
```
### Настройка окружения
```bash
cp .env.example .env
# Отредактируйте .env файл
```
### Запуск приложения
```bash
# Режим разработки
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# Или через Python
python main.py
```
### Доступ к приложению
- Веб-интерфейс: http://localhost:8000
- API документация: http://localhost:8000/api/docs
- ReDoc: http://localhost:8000/api/redoc
## 📁 Структура проекта
```
app/
├── api/v1/endpoints/ # API endpoints
├── core/ # Ядро (config, make_executor)
├── models/ # Модели данных
├── services/ # Бизнес-логика
├── templates/ # HTMX шаблоны
├── static/ # Статические файлы
├── tasks/ # Celery задачи
├── db/ # База данных
└── main.py # Точка входа
```
## 🔧 Разработка
### Добавление нового endpoint
1. Создайте файл в `api/v1/endpoints/`
2. Создайте роутер с endpoints
3. Подключите роутер в `api/v1/router.py`
### Добавление новой страницы
1. Создайте шаблон в `templates/pages/`
2. Добавьте роут в `main.py`
3. Используйте `base.html` как базовый шаблон
## 📚 Документация
Полная документация находится в `docs/`:
- `WEB_INTERFACE_PROPOSAL.md` - Полное предложение
- `WEB_INTERFACE_DETAILS.md` - Детали работы
- `WEB_INTERFACE_DEPLOY_IMPORT_EXPORT.md` - Деплой, импорт, экспорт

View File

@@ -0,0 +1,96 @@
# 🚀 Начните отсюда!
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## Быстрый запуск веб-интерфейса в Docker
### Шаг 1: Перейти в директорию app
```bash
cd app
```
### Шаг 2: Запустить docker-compose
```bash
make up
```
Или напрямую:
```bash
docker-compose up -d
```
### Шаг 3: Открыть в браузере
http://localhost:8000
## ✅ Готово!
Веб-интерфейс запущен! Ничего не нужно устанавливать на локальную машину.
## 📋 Что запускается
- **web** (порт 8000) - Веб-интерфейс FastAPI
- **redis** (порт 6379) - Redis для Celery
- **celery-worker** - Worker для фоновых задач
- **celery-beat** - Планировщик задач
## 🔧 Полезные команды
```bash
# Просмотр логов
make logs
# Остановка
make down
# Перезапуск
make restart
# Shell в контейнере
make shell
# Статус контейнеров
make status
# Пересборка
make rebuild
```
## 📚 Документация
- `README_DOCKER.md` - Полная документация по Docker
- `QUICKSTART_DOCKER.md` - Быстрый старт
- `README.md` - Общая документация
## 🐛 Проблемы?
### Проверьте Docker
```bash
docker ps
docker-compose ps
```
### Проверьте логи
```bash
docker-compose logs web
```
### Пересоберите
```bash
make rebuild
```
## 💡 Особенности
- ✅ Всё работает в Docker - ничего не нужно устанавливать локально
- ✅ Доступ к Docker socket для управления контейнерами тестирования
- ✅ Весь проект монтируется в контейнер
- ✅ Hot reload для разработки
- ✅ Celery для фоновых задач

View File

@@ -0,0 +1,116 @@
# ✅ Статус развертывания веб-интерфейса DevOpsLab
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
**Дата проверки:** 2024-02-15
## 🎉 УСПЕШНО ЗАПУЩЕНО!
### Проверка работоспособности
```bash
# ✅ Health check
$ curl http://localhost:8000/health
{"status":"ok","version":"1.0.0"}
# ✅ Главная страница
$ curl http://localhost:8000/
<!DOCTYPE html>... (HTML загружается)
# ✅ API статистики
$ curl http://localhost:8000/api/v1/stats/roles
{"count":4}
```
### Статус контейнеров
```
✅ devopslab-web Up - порт 8000
✅ devopslab-redis Up - порт 6379
✅ devopslab-celery-worker Up - готов к работе
✅ devopslab-celery-beat Up - готов к работе
```
## 🔧 Исправленные проблемы
### 1. Конфликт зависимостей Redis
- **Было:** `redis==5.0.1` (несовместимо с celery[redis] 5.3.4)
- **Стало:** `redis==4.6.0`
### 2. Ошибка импорта модулей
- **Было:** `ModuleNotFoundError: No module named 'app'`
- **Исправлено:**
- Структура: файлы в `/app/app/`
- `PYTHONPATH=/app`
- Команда: `python -m uvicorn app.main:app`
- Создан `app/app/__init__.py`
### 3. Команды Celery
- **Было:** `celery -A tasks.celery_tasks`
- **Стало:** `celery -A app.tasks.celery_tasks`
## 📁 Структура проекта
```
app/
├── Dockerfile ✅ Готов
├── docker-compose.yml ✅ Готов
├── requirements.txt ✅ Исправлен (redis 4.6.0)
├── main.py ✅ Работает
├── app/ ✅ Пакет Python
│ ├── __init__.py ✅ Создан
│ ├── main.py
│ ├── api/
│ ├── core/
│ ├── templates/
│ └── ...
└── ...
```
## 🌐 Доступные endpoints
-`GET /` - Главная страница (Dashboard)
-`GET /health` - Health check
-`GET /api/v1/stats/roles` - Количество ролей
-`GET /api/docs` - Swagger документация
-`GET /api/redoc` - ReDoc документация
## 🚀 Команды для работы
```bash
# Запуск
cd app && make up
# Остановка
make down
# Логи
make logs
# Shell
make shell
# Статус
make status
```
## ✅ Что работает
1. ✅ Docker сборка проходит успешно
2. ✅ Контейнеры запускаются
3.Веб-интерфейс отвечает на запросы
4. ✅ API endpoints работают
5. ✅ Redis подключен
6. ✅ Celery worker запущен и готов
7. ✅ Доступ к Docker socket работает
8. ✅ Монтирование проекта работает
9. ✅ HTMX шаблоны загружаются
10. ✅ Статистика ролей работает
## 📝 Готово к разработке!
Веб-интерфейс полностью настроен и готов к дальнейшей разработке функционала.
---
**Статус:****РАБОТАЕТ**