docs: agent analysis request — full project overview for new chat
This commit is contained in:
@@ -0,0 +1,318 @@
|
|||||||
|
# Запрос на полный анализ autotest — для нового чата с агентом
|
||||||
|
|
||||||
|
Дата: 2026-07-30
|
||||||
|
Версия: v1.1.48
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. ЧТО ЭТО ЗА ПРОЕКТ
|
||||||
|
|
||||||
|
**autotest** — веб-приложение для автоматизированного тестирования сервисов платформы Nubes (Cloud Director). Позволяет запускать операции (create/modify/delete/suspend/resume/redeploy) над инстансами сервисов через Nubes REST API, отслеживать статус, вести историю запусков.
|
||||||
|
|
||||||
|
Приложение запущено на тестовом стенде: `atest.pythonk8s.dev.nubes.ru`
|
||||||
|
|
||||||
|
**Стек:**
|
||||||
|
- Backend: Flask 3.0 + gunicorn (multi-worker)
|
||||||
|
- DB: PostgreSQL 17 (Zalando Operator), схемы: `runs`, `scenario_runs`, `scenario_definitions` (pending)
|
||||||
|
- Frontend: ванильный JS (один файл `app.js`, 550 строк), Jinja2-шаблон
|
||||||
|
- Nubes REST API: `https://lk-api-gateway-test.ngcloud.ru/api/v1/svc`
|
||||||
|
- Аутентификация: JWT-токен (cookie или env), автоопределение стенда (dev/test)
|
||||||
|
- Деплой: Nubes pythonk8s, кластер iot-naeel
|
||||||
|
|
||||||
|
**Автор:** naeel (tazetdinovn@gmail.com, WZ03709)
|
||||||
|
**Репозитории:**
|
||||||
|
- `https://gitea.services.ngcloud.ru/forcloud/app-autotest` — код приложения
|
||||||
|
- `https://gitea.services.ngcloud.ru/forcloud/autotest` — документация, YAML-описания сервисов
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. АРХИТЕКТУРА — ФАЙЛЫ И ИХ РОЛИ
|
||||||
|
|
||||||
|
### site/app.py — точка входа
|
||||||
|
Flask-приложение, регистрирует blueprint'ы:
|
||||||
|
- `main_bp` — главная страница, токен, инфраструктура
|
||||||
|
- `api_test_bp` — основной API (run/params/status/log/history)
|
||||||
|
- `api_scenario_bp` — API сценариев (run/status/CRUD — pending)
|
||||||
|
- `api_bp` — **УДАЛЁН в v1.1.45** (legacy: /api/run, /api/status, /api/config)
|
||||||
|
- VERSION — меняется при КАЖДОМ изменении
|
||||||
|
|
||||||
|
### site/api/http_client.py — HTTP-клиент
|
||||||
|
- `HttpClient` — обёртка над requests.Session
|
||||||
|
- GET: `raise_for_status()` → `.json()`, пустой ответ → `{}`
|
||||||
|
- POST: `json=data`, извлекает Location-заголовок → `_location` в ответе
|
||||||
|
- `raw_delete(url)` — DELETE без auth (для CMDB API)
|
||||||
|
- `detect_endpoint(token)` — автоопределение стенда (dev→test)
|
||||||
|
- `stand_name(endpoint)` — "dev"/"test" по URL
|
||||||
|
|
||||||
|
### site/api/auth.py — аутентификация
|
||||||
|
- `get_token()` — из cookie или env
|
||||||
|
- `get_client()` — HttpClient с автостендом
|
||||||
|
- `get_client_id()` — ClientID из JWT
|
||||||
|
- `get_stand()` — "dev"/"test"
|
||||||
|
- `get_token_info()` — {email, company, client_id}
|
||||||
|
|
||||||
|
### site/routes/main.py — главная страница
|
||||||
|
- `GET/POST /` — Jinja2-рендер: организация, инфраструктура, сервисы, форма токена
|
||||||
|
- `GET /api/operations/<svc_id>` — cloud-first инстансы + tracked-fallback
|
||||||
|
- `_resolve_instance_status()` — explainedStatus из облака или "creating" из трекера
|
||||||
|
|
||||||
|
### site/routes/api_test.py — ОСНОВНОЙ API (400 строк)
|
||||||
|
Эндпоинты:
|
||||||
|
- `GET /api/services` — список сервисов
|
||||||
|
- `GET /api/instances/list` — все инстансы
|
||||||
|
- `GET /api/params/<op_id>[?instanceUid=xxx]` — параметры операции (текущие или шаблон)
|
||||||
|
- `POST /api/test` — запуск операции (CREATE или non-CREATE)
|
||||||
|
- `GET /api/test/status/<op_uid>` — поллинг
|
||||||
|
- `GET /api/log` — логи
|
||||||
|
- `GET /api/history` — история из БД
|
||||||
|
|
||||||
|
Ключевые функции:
|
||||||
|
- `_send_params_terraform()` — шаги 3-7 Terraform (cfsParams → resolveRefSvc → send → validate)
|
||||||
|
- `_normalize_value()` — normalizeUniversalValueV6 (Terraform-equivalent)
|
||||||
|
- `_resolve_ref_svc()` — автоподстановка UUID инстанса для refSvcId-параметров
|
||||||
|
- `_finish_op()` — фоновый поллинг до dtFinish, сохранение в БД
|
||||||
|
- `_redact_params()` — замена secret/password/token на ***
|
||||||
|
- `_unique_display_name()` — проверка на дубликат + суффикс
|
||||||
|
- `_find_uid(resp)` — извлечение UUID из вложенных dict
|
||||||
|
- `_uid_from_location(loc)` — извлечение UUID из Location-заголовка
|
||||||
|
|
||||||
|
### site/routes/api_scenario.py — API СЦЕНАРИЕВ (90 строк)
|
||||||
|
- `GET /api/scenarios` — список из config.yaml (должен быть переключён на БД)
|
||||||
|
- `POST /api/scenario/run` — запуск (создаёт запись ДО потока, возвращает run_id + 202)
|
||||||
|
- `GET /api/scenario/run/<int:run_id>` — статус конкретного запуска
|
||||||
|
- `GET /api/scenario/status` — последние 10 запусков (legacy, должен уйти)
|
||||||
|
|
||||||
|
### site/operations/scenario.py — ЯДРО СЦЕНАРИЕВ (290 строк)
|
||||||
|
- `run_scenario()` — главный исполнитель:
|
||||||
|
1. service имя → svc_id (из config.yaml services)
|
||||||
|
2. operation имя → svcOperationId (GET /services/{id})
|
||||||
|
3. param коды → numeric IDs (GET /instanceOperations/default/{opId})
|
||||||
|
4. create: новый инстанс; остальные: переиспользовать instance_map
|
||||||
|
5. POST /instances → POST /instanceOperations → _send_params_terraform → run → poll
|
||||||
|
6. Сохранить в runs (RUNNING до API, финальный после) + scenario_runs
|
||||||
|
- `_resolve_service()` — поиск svc_id по символическому имени
|
||||||
|
- `_resolve_params()` — symbolic codes → numeric IDs
|
||||||
|
- `_find_uid()`, `_uid_from_location()` — ДУБЛИКАТЫ из api_test.py (!)
|
||||||
|
- `_save_scenario_run()` — UPDATE scenario_runs
|
||||||
|
- `_create_scenario_run()` — INSERT scenario_runs
|
||||||
|
|
||||||
|
### site/operations/get_params.py — параметры с текущими значениями
|
||||||
|
- `get_params_with_current_values()` — смержить state.params инстанса с шаблоном операции
|
||||||
|
- `_normalize_value_list()` — CSV-строка/массив → list
|
||||||
|
|
||||||
|
### site/operations/get_services.py — сервисы
|
||||||
|
- `get_services()` — GET /services → все сервисы
|
||||||
|
- `get_service_detail()` — GET /services/{id} → детали + операции
|
||||||
|
|
||||||
|
### site/operations/get_instances.py — инстансы
|
||||||
|
- `get_organization()` — инстанс с serviceId=19
|
||||||
|
- `get_instances()` — GET /instances?pageSize=500 → все инстансы
|
||||||
|
|
||||||
|
### site/operations/service_list.py — разрешённые сервисы
|
||||||
|
- `load_service_ids(stand)` — чтение `config/services_{stand}.txt`
|
||||||
|
|
||||||
|
### site/operations/tracker.py — трекер инстансов (файловый)
|
||||||
|
- JSON-файлы в /tmp/: `instances-{clientId}-{stand}.json`
|
||||||
|
- fcntl.flock для multi-worker safety
|
||||||
|
- Используется как КРАТКОСРОЧНЫЙ fallback (инстанс создан, но облако ещё не показывает)
|
||||||
|
|
||||||
|
### site/db/pool.py — connection pool
|
||||||
|
- Lazy-init ThreadedConnectionPool (1-5)
|
||||||
|
- `_ensure_schema()` → `init_db()` после успешного коннекта
|
||||||
|
- ENV: DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, DB_SSLMODE
|
||||||
|
|
||||||
|
### site/db/init_db.py — схема БД
|
||||||
|
- Таблица `runs` — история операций (id, client_id, stand, svc_id, op_name, status, duration, params JSONB, stages JSONB, scenario_run_id, step_number)
|
||||||
|
- Таблица `scenario_runs` — запуски сценариев (id, scenario_name, status, current_step, total_steps, duration, error_log)
|
||||||
|
- Миграции: ALTER TABLE ADD COLUMN IF NOT EXISTS
|
||||||
|
- **НЕТ** таблицы `scenario_definitions` — её ещё предстоит создать
|
||||||
|
|
||||||
|
### site/db/save_run.py — сохранение в БД
|
||||||
|
- `save_run()` — INSERT в runs
|
||||||
|
- Принимает опциональные `scenario_run_id` + `step_number` (добавлены в v1.1.48)
|
||||||
|
|
||||||
|
### site/runner.py — LEGACY (будет удалён)
|
||||||
|
- Старый механизм запуска тестов из config.yaml
|
||||||
|
- Используется только `load_config()` из него
|
||||||
|
|
||||||
|
### site/static/app.js — ФРОНТЕНД (550 строк)
|
||||||
|
- Глобальное состояние: svcInstances, selectedInst, selectedOp, pollTimer, currentSvcId, busy, AUTOTEST_PREFIX
|
||||||
|
- selectService(), toggleInstance(), startCreate(), runOp(), showParams(), executeOp()
|
||||||
|
- Поллинг: setFinishedState(), showStages(), stopPoll(), refreshInstances()
|
||||||
|
- История: toggleHistory(), loadHistory()
|
||||||
|
- Сценарии: toggleScenario(), loadScenarios(), runScenario(), stopScenarioPoll()
|
||||||
|
- Хелперы: _esc() (HTML-escape), validateJson()
|
||||||
|
- Логи: toggleLog(), startLogPoll()
|
||||||
|
|
||||||
|
### site/static/style.css — стили
|
||||||
|
### site/templates/index.html — Jinja2-шаблон
|
||||||
|
- Три колонки: инфраструктура | сервисы | инстансы+операции+параметры
|
||||||
|
- Секции: история (сворачиваемая), сценарии (сворачиваемая)
|
||||||
|
- window.APP: version, stand, hasUserToken, firstServiceId
|
||||||
|
|
||||||
|
### site/config.yaml — конфигурация
|
||||||
|
- services: маппинг name → service_id
|
||||||
|
- scenarios: один сценарий dummy_test (create → delete)
|
||||||
|
- **Проблема:** сценарии в контейнере, требуют redeploy для изменения
|
||||||
|
|
||||||
|
### STANDS/dev/resources_yaml/ — YAML-описания сервисов (50+ файлов)
|
||||||
|
- Полные описания: name, service_id, outputs, operations с параметрами (коды, типы, valueList, sub_params)
|
||||||
|
- Используются ТОЛЬКО как документация, код их не читает
|
||||||
|
|
||||||
|
### DOCS/ — документация
|
||||||
|
- ARCHITECTURE-FULL.md — полный обзор
|
||||||
|
- sol-answers.md — 14 ответов Sol (MVP-план)
|
||||||
|
- sol-scenario-editor.md — ответы Sol по редактору сценариев
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. ПОТОК ОПЕРАЦИИ CREATE (Terraform parity)
|
||||||
|
|
||||||
|
1. POST /instances → `instance_uid` из Location-заголовка `./UUID`
|
||||||
|
2. POST /instanceOperations → `op_uid` из Location-заголовка
|
||||||
|
3. GET /instanceOperations/{op_uid}?fields=cfsParams → шаблон параметров
|
||||||
|
4. _resolve_ref_svc → автоподстановка UUID для refSvcId-параметров
|
||||||
|
5. POST /instanceOperationCfsParams → отправить пользовательские параметры
|
||||||
|
6. POST /instanceOperationCfsParams → дослать неотправленные (с normalize)
|
||||||
|
7. GET /instanceOperations/{op_uid}/validate-cfs → валидация
|
||||||
|
8. POST /instanceOperations/{op_uid}/run → запуск
|
||||||
|
9. Поллинг GET /instanceOperations/{op_uid}?fields=dtFinish,... → dtFinish
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. ТЕКУЩЕЕ СОСТОЯНИЕ (v1.1.48)
|
||||||
|
|
||||||
|
### Работает:
|
||||||
|
- ✅ Ручной запуск операций (create/modify/delete/suspend/resume/redeploy)
|
||||||
|
- ✅ Terraform-совместимая отправка параметров (9 шагов)
|
||||||
|
- ✅ Поллинг с этапами (⏳/✅/❌)
|
||||||
|
- ✅ История в БД (runs)
|
||||||
|
- ✅ Лог-панель (fcntl.flock, ротация)
|
||||||
|
- ✅ HTML-escape (statusError, d.error, логи, currentSvcName)
|
||||||
|
- ✅ Redact secrets перед сохранением
|
||||||
|
- ✅ Валидация входов (UUID, int, dict)
|
||||||
|
- ✅ refSvcId — верхнеуровневый + в dataDescriptor
|
||||||
|
- ✅ Убран legacy api_bp
|
||||||
|
|
||||||
|
### Частично работает:
|
||||||
|
- ⚠️ Сценарии — запуск есть, но источник = config.yaml (redeploy для правки)
|
||||||
|
- ⚠️ save_run пишет scenario_run_id + step_number (v1.1.48), но не протестировано
|
||||||
|
- ⚠️ run_id возвращается клиенту (v1.1.48), поллинг по конкретному запуску
|
||||||
|
|
||||||
|
### Не работает / pending:
|
||||||
|
- ❌ Редактор сценариев в UI (нужна таблица scenario_definitions + CRUD API + UI)
|
||||||
|
- ❌ Сценарии требуют redeploy для изменения (запечены в config.yaml)
|
||||||
|
- ❌ Дубликаты _find_uid / _uid_from_location в scenario.py и api_test.py
|
||||||
|
- ❌ scenario.py не протестирован на полный цикл create→delete
|
||||||
|
- ❌ seed из config.yaml в БД при первом старте не реализован
|
||||||
|
- ❌ Нет сервисных токенов (runner использует персональный токен)
|
||||||
|
- ❌ Нет блокировки параллельных запусков сценариев
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. КЛЮЧЕВЫЕ НАХОДКИ ИЗ HAR-ТРАССИРОВКИ
|
||||||
|
|
||||||
|
POST /instances:
|
||||||
|
- Request: `{"serviceId":1,"displayName":"dummy-11255555","descr":""}`
|
||||||
|
- Response: status 201, body `{}`, Location: `./CDEBB216-E5EB-4C09-8736-7E5F01A4EE12`
|
||||||
|
- **UUID ТОЛЬКО в Location-заголовке**, тело ответа — пустой объект `{}`
|
||||||
|
|
||||||
|
POST /instanceOperations:
|
||||||
|
- Request: `{"instanceUid":"...","operation":"create"}`
|
||||||
|
- Response: также Location-заголовок с opUid
|
||||||
|
|
||||||
|
**Следствие:** `_find_uid(resp)` никогда не найдёт UUID в теле ответа (тело пустое). UUID всегда в Location. `_uid_from_location(resp.get("_location",""))` — ЕДИНСТВЕННЫЙ работающий метод извлечения.
|
||||||
|
|
||||||
|
**Но:** `_find_uid` нужен для других ответов API (get instanceOperation), где UUID внутри `instanceOperation.instanceOperationUid`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. РЕКОМЕНДАЦИИ SOL (2026-07-30)
|
||||||
|
|
||||||
|
### По редактору сценариев (sol-scenario-editor.md):
|
||||||
|
|
||||||
|
1. **Структура steps:** JSONB, поле `resource` для связи create→modify→delete одного инстанса
|
||||||
|
2. **Параметры:** выпадающие списки из живого API (сервис→операции→коды), кеш на время сессии
|
||||||
|
3. **Seed:** marker `scenario_seed_v1=completed`, `INSERT ON CONFLICT DO NOTHING`, отдельный `scenario_seed.yaml`
|
||||||
|
4. **UI:** модальное окно, кнопки вверх/вниз, мягкое удаление (is_active=false)
|
||||||
|
5. **Валидация:** при сохранении + при запуске, невалидный не запускать
|
||||||
|
6. **Критические дыры:**
|
||||||
|
- run_id до потока (✅ исправлено v1.1.48)
|
||||||
|
- GET /api/scenario/run/<id> (✅ добавлен v1.1.48)
|
||||||
|
- save_run пишет scenario_run_id/step_number (✅ исправлено v1.1.48)
|
||||||
|
- TIMEOUT: op_data инициализировать (✅ исправлено v1.1.48)
|
||||||
|
- RUNNING до API (✅ исправлено v1.1.48)
|
||||||
|
- Блокировка параллельных запусков (pending)
|
||||||
|
- version в definitions для optimistic locking (pending)
|
||||||
|
- Сервисные токены (pending)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. ЧТО НУЖНО ОТ АГЕНТА
|
||||||
|
|
||||||
|
### Проанализировать и ответить:
|
||||||
|
|
||||||
|
1. **Общая архитектура** — оценить, найти слабые места, предложить улучшения
|
||||||
|
|
||||||
|
2. **Дублирование кода** — `_find_uid` и `_uid_from_location` есть и в api_test.py и в scenario.py. Вынести в общий модуль? Куда?
|
||||||
|
|
||||||
|
3. **scenario_definitions** — спроектировать таблицу:
|
||||||
|
- Поля: id, client_id, stand, name, steps JSONB, version, is_active, created_at, updated_at, updated_by
|
||||||
|
- Индексы: UNIQUE(client_id, stand, lower(name))
|
||||||
|
- API CRUD: какие именно эндпоинты, какие проверки
|
||||||
|
- Seed: как именно импортировать из scenario_seed.yaml при первом старте
|
||||||
|
|
||||||
|
4. **UI редактора сценариев:**
|
||||||
|
- Модальное окно: структура HTML
|
||||||
|
- JS-логика: загрузка списка, создание/редактирование/удаление
|
||||||
|
- Выпадающие списки: сервисы из GET /api/services, операции из GET /api/operations/{svcId}, параметры из GET /api/params/{opId}
|
||||||
|
- Валидация на фронте перед отправкой
|
||||||
|
|
||||||
|
5. **Runner** — нужно ли что-то менять в `run_scenario()`? Он сейчас берёт шаги из config.yaml, должен из БД. Также нужно сохранять snapshot шагов в scenario_runs.
|
||||||
|
|
||||||
|
6. **Безопасность:**
|
||||||
|
- CRUD сценариев: проверка client_id+stand
|
||||||
|
- Optimistic locking (version)
|
||||||
|
- Блокировка параллельных запусков (HTTP 409)
|
||||||
|
|
||||||
|
7. **Что ещё критично упущено?** — любые дыры, которые не покрыты текущим планом
|
||||||
|
|
||||||
|
8. **Приоритетный порядок реализации:**
|
||||||
|
- Что делать сначала, что потом
|
||||||
|
- Что можно выпустить в v1.1.49, что отложить
|
||||||
|
|
||||||
|
### НЕ ДЕЛАТЬ:
|
||||||
|
- Не писать код (только анализ и план)
|
||||||
|
- Не трогать git
|
||||||
|
- Не менять файлы
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. ФАЙЛЫ ДЛЯ АНАЛИЗА (читать в этом порядке)
|
||||||
|
|
||||||
|
1. `app-autotest/site/app.py`
|
||||||
|
2. `app-autotest/site/api/http_client.py`
|
||||||
|
3. `app-autotest/site/api/auth.py`
|
||||||
|
4. `app-autotest/site/routes/main.py`
|
||||||
|
5. `app-autotest/site/routes/api_test.py` (самый важный)
|
||||||
|
6. `app-autotest/site/routes/api_scenario.py`
|
||||||
|
7. `app-autotest/site/operations/scenario.py`
|
||||||
|
8. `app-autotest/site/operations/get_params.py`
|
||||||
|
9. `app-autotest/site/operations/get_services.py`
|
||||||
|
10. `app-autotest/site/operations/get_instances.py`
|
||||||
|
11. `app-autotest/site/operations/tracker.py`
|
||||||
|
12. `app-autotest/site/operations/service_list.py`
|
||||||
|
13. `app-autotest/site/db/pool.py`
|
||||||
|
14. `app-autotest/site/db/init_db.py`
|
||||||
|
15. `app-autotest/site/db/save_run.py`
|
||||||
|
16. `app-autotest/site/runner.py`
|
||||||
|
17. `app-autotest/site/config.yaml`
|
||||||
|
18. `app-autotest/site/static/app.js`
|
||||||
|
19. `app-autotest/site/templates/index.html`
|
||||||
|
20. `app-autotest/site/static/style.css`
|
||||||
|
21. `development/dummycreate.har` (HAR-трассировка CREATE)
|
||||||
|
22. `DOCS/ARCHITECTURE-FULL.md`
|
||||||
|
23. `DOCS/sol-answers.md`
|
||||||
|
24. `DOCS/sol-scenario-editor.md`
|
||||||
|
25. `app-autotest/site/config/services_test.txt`
|
||||||
|
26. Любой YAML из `STANDS/dev/resources_yaml/` (например `1_dummy.yaml`, `115_mariadb.yaml`)
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Sol — ответы по редактору сценариев
|
||||||
|
|
||||||
|
Дата: 2026-07-30
|
||||||
|
|
||||||
|
## 1. Структура `steps`
|
||||||
|
- JSONB массив, отдельная таблица не нужна
|
||||||
|
- Обязательно поле `resource` — идентификатор инстанса внутри сценария (для связи create→modify→delete)
|
||||||
|
- `scenario_definitions`: + `version INTEGER`, `updated_by`, `is_active`/`deleted_at`, уникальность имени case-insensitive
|
||||||
|
- `scenario_runs`: + `definition_id`, `definition_version`, `steps_snapshot`
|
||||||
|
- Runner работает со snapshot, не перечитывает определение
|
||||||
|
|
||||||
|
## 2. Параметры в редакторе
|
||||||
|
- Из Nubes API: сервис→операции→`/instanceOperations/default/{opId}`→коды
|
||||||
|
- Выпадающий список с типом, обязательностью, default
|
||||||
|
- Map/array — JSON-строка с валидацией
|
||||||
|
- Кеш: браузерный на время сессии редактора ИЛИ серверный (stand+opId, TTL 5 мин)
|
||||||
|
- Свободный ввод кода не нужен
|
||||||
|
|
||||||
|
## 3. Seed из config.yaml
|
||||||
|
- Не импортировать при каждом пустом старте
|
||||||
|
- Схема: marker импорта → `INSERT ON CONFLICT DO NOTHING` → marker `scenario_seed_v1=completed`
|
||||||
|
- YAML вынести в `scenario_seed.yaml`, после rollout удалить
|
||||||
|
- Остальной config.yaml не трогать
|
||||||
|
|
||||||
|
## 4. UI редактор
|
||||||
|
- Модальное окно или боковая панель (не inline)
|
||||||
|
- Имя, список шагов, сервис, операция, параметры
|
||||||
|
- Кнопки добавить/удалить/вверх/вниз
|
||||||
|
- Drag-and-drop не нужен
|
||||||
|
- Мягкое удаление: `is_active=false`
|
||||||
|
|
||||||
|
## 5. Валидация
|
||||||
|
- При сохранении: структура, существование сервиса, доступность операции, коды параметров, типы, уникальность resource, порядок (create→modify→delete, после delete ничего)
|
||||||
|
- При запуске: повторить по актуальному API
|
||||||
|
- Невалидный сценарий не запускать частично
|
||||||
|
|
||||||
|
## 6. Критически упущенное
|
||||||
|
|
||||||
|
1. `POST /api/scenario/run` не возвращает run ID — гонка при двух запусках. Создавать запись ДО thread, вернуть HTTP 202 + run_id
|
||||||
|
2. Нужен `GET /api/scenario/runs/<id>` — поллинг конкретного запуска
|
||||||
|
3. `save_run()` не пишет `scenario_run_id` и `step_number` — шаги не связаны со сценарием
|
||||||
|
4. TIMEOUT: `op_data` может быть неинициализирована
|
||||||
|
5. Шаг нужно создавать в `runs` со статусом RUNNING ДО обращения к API, потом обновлять
|
||||||
|
6. Блокировка параллельных запусков: HTTP 409 для одного client_id+stand
|
||||||
|
7. CRUD: проверять `client_id+stand` при всех операциях
|
||||||
|
8. `version` в definitions: PUT с текущей version, 409 при конфликте
|
||||||
|
9. Runner использует персональный токен — нужен сервисный токен/клиент по stand
|
||||||
|
10. Имя не идентификатор: API запуска принимает `definition_id`, имя — редактируемое поле
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
Список задач обновлен
|
||||||
|
|
||||||
|
# Что получится из Autotest
|
||||||
|
|
||||||
|
**Autotest** станет веб-приложением для автоматической проверки операций облачных сервисов Nubes.
|
||||||
|
|
||||||
|
Сейчас приложение позволяет вручную создавать, изменять и удалять инстансы. Следующий этап — запуск готовых автоматических сценариев, например:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Создать PostgreSQL → изменить параметры → проверить результат → удалить
|
||||||
|
```
|
||||||
|
|
||||||
|
## Как это будет работать
|
||||||
|
|
||||||
|
1. В конфигурационном YAML-файле задаётся:
|
||||||
|
- какие сервисы проверять;
|
||||||
|
- какие операции выполнять;
|
||||||
|
- в какой последовательности;
|
||||||
|
- какие параметры использовать;
|
||||||
|
- нужно ли удалять созданный инстанс.
|
||||||
|
|
||||||
|
2. Пользователь открывает приложение, выбирает сценарий и стенд, нажимает **«Запустить»**.
|
||||||
|
|
||||||
|
3. Приложение последовательно выполняет операции и показывает:
|
||||||
|
- текущий шаг;
|
||||||
|
- созданный инстанс;
|
||||||
|
- продолжительность;
|
||||||
|
- успешный или неуспешный результат;
|
||||||
|
- причину ошибки.
|
||||||
|
|
||||||
|
4. Результаты сохраняются в PostgreSQL и доступны всем тестировщикам в общей истории.
|
||||||
|
|
||||||
|
## Архитектура
|
||||||
|
|
||||||
|
```text
|
||||||
|
YAML-сценарии в Git
|
||||||
|
↓
|
||||||
|
Flask-приложение
|
||||||
|
↓
|
||||||
|
Исполнитель сценариев
|
||||||
|
↓
|
||||||
|
Nubes API
|
||||||
|
↓
|
||||||
|
PostgreSQL: запуски, шаги, результаты и ошибки
|
||||||
|
```
|
||||||
|
|
||||||
|
Ручные операции и автоматические сценарии будут использовать один и тот же механизм работы с Nubes API. Благодаря этому автоматический тест будет выполнять операцию так же, как текущий ручной интерфейс и UI облака.
|
||||||
|
|
||||||
|
Для каждого стенда используется отдельный технический токен. Токен пользователя нужен только для ручных операций.
|
||||||
|
|
||||||
|
## Первый рабочий релиз
|
||||||
|
|
||||||
|
В MVP войдут:
|
||||||
|
|
||||||
|
- YAML-сценарии, хранящиеся и проверяемые через Git;
|
||||||
|
- ручной запуск сценария из веб-интерфейса;
|
||||||
|
- последовательное выполнение операций;
|
||||||
|
- поддержка dev и test;
|
||||||
|
- сценарии с временными и постоянными тестовыми инстансами;
|
||||||
|
- отображение выполнения по шагам;
|
||||||
|
- общая история всех запусков;
|
||||||
|
- сохранение результатов и ошибок в PostgreSQL;
|
||||||
|
- защита от одновременного запуска нескольких сценариев на одном стенде.
|
||||||
|
|
||||||
|
Prod на первом этапе будет заблокирован. После проверки на dev и test добавим отдельные правила безопасности для тестовой организации, карантина и разрешённых операций.
|
||||||
|
|
||||||
|
## Дальнейшее развитие
|
||||||
|
|
||||||
|
После MVP можно добавить:
|
||||||
|
|
||||||
|
- запуск по расписанию;
|
||||||
|
- уведомления о падениях;
|
||||||
|
- регулярные проверки выбранных сервисов;
|
||||||
|
- статистику успешности и длительности операций;
|
||||||
|
- безопасный запуск на prod;
|
||||||
|
- настройку сценариев через веб-интерфейс;
|
||||||
|
- impersonation и проверку операций от разных пользователей.
|
||||||
|
|
||||||
|
**Итог:** это будет не копия UI облака, а централизованный инструмент для регулярной проверки работоспособности операций Nubes: с настраиваемыми сценариями, общими результатами и контролем безопасности.
|
||||||
Reference in New Issue
Block a user