DOCS: architecture-next update + opus frontend/instance/review prompts

This commit is contained in:
2026-07-31 12:49:42 +04:00
parent c7b1f4d459
commit 89aa5268e7
5 changed files with 305 additions and 28 deletions
+23 -27
View File
@@ -1,38 +1,34 @@
# Архитектура app-autotest — план рефакторинга (2026-07-31)
# Архитектура app-autotest — рефакторинг (2026-07-31)
> Полный план: `DOCS/opus-plan-2026-07-31.md`
> Ветка: `opus-architecture-2026-07-31`
> План: `DOCS/opus-plan-2026-07-31.md` | Ревью: `DOCS/opus-review-v1.2.0.md`
> Текущая версия: **v1.2.1** ✅
## Проблемы
## ✅ Реализовано (Фазы 1-3)
1. **Дублирование CREATE-флоу:** `routes/api_test.py` и `operations/scenario.py` содержат идентичную логику POST /instances → POST /instanceOperations → send_params_terraform → /run.
2. **Ограничение instance_map:** сценарий привязан к `service_id`, нельзя два инстанса одного сервиса.
3. **Нет общей функции** — правки Terraform-флоу надо делать в двух местах.
### Новые модули
- `api/utils.py` — find_uid(), uid_from_location() (вместо 2 дублей)
- `operations/poll.py` — poll_until_done() (общий поллинг)
- `operations/executor.py` — execute_operation() (единый CREATE/non-CREATE флоу, tracker_add внутри)
## Решение
### Рефакторинг
- `api_test.py` — через executor + poll_until_done, CMDB delete отдельно
- `scenario.py` — через executor + poll, output/ref/bindings резолвинг
- `api_scenario_defs.py` — _validate_steps: output/instance_ref/instance_uid
- `init_db.py` — startup cleanup зависших scenario_runs (>1ч)
- `params-render.js` — общий рендер параметров (вынесен из operations.js)
### Новые файлы
- `operations/executor.py``execute_operation()` (единый флоу до /run)
- `operations/poll.py``poll_until_done()` (общий цикл поллинга)
- `api/utils.py``find_uid()`, `uid_from_location()` (вместо дублей)
- `static/js/params-render.js` — общий рендер параметров
### Новый формат шагов
### Формат шагов (JSONB, без изменений схемы)
```json
{"service_id": 1, "operation": "create", "params": {}, "output": "d1"}
{"service_id": 1, "operation": "modify", "params": {}, "instance_ref": "d1"}
{"service_id": 1, "operation": "delete", "params": {}, "instance_uid": "UUID"}
```
Старый формат (без output/ref) — обратная совместимость через fallback.
### Исправляемые файлы
- `routes/api_test.py` — через executor (+ CMDB delete отдельно)
- `operations/scenario.py` — через executor + poll_until_done + output/ref резолвинг
- `routes/api_scenario_defs.py` — _validate_steps с новыми ключами
- `db/init_db.py` — startup cleanup зависших scenario_runs
- `static/js/scenario-form.js` — модальный редактор с параметрами
- `static/js/operations.js` — использовать params-render.js
- `templates/index.html` — модал + params-render.js
- `app.py` — bump VERSION
## ❌ Не реализовано (Фаза 4)
### Порядок
Фаза 1 (общие модули) → Фаза 2 (формат шагов) → Фаза 3 (миграция вызывающих) → Фаза 4 (UI)
### Модальный редактор сценариев
- `scenario-form.js` — нужна полная переделка
- `index.html` — разметка модала
- Дропдауны сервисов/операций, автоподгрузка параметров
- Поля output/instance_ref
- [↑][↓] перестановка шагов
+96
View File
@@ -0,0 +1,96 @@
# Prompt for Opus — Frontend Scenario Editor UI
## Что это за проект
Nubes Autotest — Flask + vanilla JS + PostgreSQL. Автотесты для облачной платформы Nubes.
Текущая версия: v1.2.3. Backend-рефакторинг завершён (unified executor, гибкие ссылки).
Сейчас нужно доработать **фронтенд редактора сценариев**.
**ВСЕ файлы фронтенда лежат здесь:**
`/home/naeel/nubes/autotest/app-autotest/site/`
## Файлы фронтенда (читай в этом порядке)
### 1. Страница и стили
`/home/naeel/nubes/autotest/app-autotest/site/templates/index.html`
- Три колонки: infra (280px) | svc (240px) | main (flex)
- В main: inst-list → params-area → create-btn-area → history-card → scenario-card
- Модал: #scenario-modal (уже есть разметка в CSS)
- Загрузка JS: utils.js → params-render.js → instances.js → operations.js → history.js → scenario-form.js → scenario-create.js → scenario-edit.js → scenario-delete.js → scenario-list.js → app.js
### 2. Текущий редактор сценариев (НЕДАВНО ПЕРЕДЕЛАН — изучи ВЕСЬ файл)
`/home/naeel/nubes/autotest/app-autotest/site/static/js/scenario-form.js` (~170 строк)
- `showScenarioEditor(def)` — открывает модал, загружает /api/services и /api/instances/list в state
- `renderEditor()` — рендерит модал: название, шаги, кнопки Сохранить/Отмена
- `renderStepRow(idx, step)` — рендерит ОДИН шаг:
- Операция: `<select>` с create/delete/modify/suspend/resume/redeploy
- Если create: `<select>` сервисов + `<input>` output (имя для ссылок)
- Если не-create: `<select>` инстансов (🆕 output'ы предыдущих шагов + ☁ облачные)
- Параметры: key=value строки (ручной ввод)
- `collectFormSteps()` — собирает данные формы в массив шагов для POST/PUT
- `saveScenario()` — валидация + POST/PUT /api/scenario/definitions
- `addStep()`, `removeStep()`, `moveStep()`, `addParam()`, `removeParam()`
### 3. Рендер параметров (общий модуль)
`/home/naeel/nubes/autotest/app-autotest/site/static/js/params-render.js` (~80 строк)
- `renderParamRow(p, allInst)` — рендер ОДНОГО параметра с учётом типа (select для valueList, refSvcId, boolean; input для текста; map-fixed → renderMapFixedRow)
- `renderMapFixedRow(p, dfl)` — вложенные поля для map-fixed параметров
- `collectParams(containerSelector)` — сбор параметров из DOM
- **Эти функции НЕ используются в scenario-form.js** — там параметры вводятся вручную key=value
### 4. Список сценариев и кнопки
`/home/naeel/nubes/autotest/app-autotest/site/static/js/scenario-list.js` (~90 строк)
- `loadScenarios()` — список сценариев + последний запуск (фильтр по версии)
- Кнопки: ▶ Запустить | ✏ Редактировать | 📋 Копировать | 🗑 Удалить | + Создать
- `runScenario(defId)` — запуск + поллинг
### 5. Остальные JS (для контекста, глубоко не читай)
- `utils.js` — _esc(), validateJson(), relativeTime(), лог-панель
- `instances.js` — selectService(), toggleInstance(), renderInstances()
- `operations.js` — startCreate(), runOp(), showParams(), executeOp() — здесь showParams использует params-render.js
- `history.js` — история тестов
- `scenario-create.js` — createScenario(), cloneScenario()
- `scenario-edit.js` — editScenario(defId)
- `scenario-delete.js` — deleteScenario(defId, name)
### 6. API (для понимания что можно дёргать)
- `GET /api/services` → [{svcId, svc}]
- `GET /api/instances/list` → [{instanceUid, displayName, serviceId, svc, explainedStatus}]
- `GET /api/operations/{svcId}` → {operations: [{svcOperationId, operation}]}
- `GET /api/params/{svcOperationId}` → {params: [{svcOperationCfsParamId, name, dataType, isRequired, defaultValue, valueList, refSvcId, dataDescriptor}]}
- `GET/POST /api/scenario/definitions` — список/создать
- `GET/PUT/DELETE /api/scenario/definitions/<id>` — один/обновить/удалить
---
## Текущее состояние редактора
✅ Работает: модал, дропдауны сервисов/операций, output/ref, кнопки CRUD, сохранение
**Параметры — ручной ввод key=value.** Не используется params-render.js. Пользователь должен знать коды параметров (durationMs, failAtStart и т.д.)
❌ Нет автоподгрузки параметров при выборе операции
❌ Нет валидации параметров в редакторе
❌ Параметры в БД хранятся символическими именами (durationMs), резолвятся в numeric ID в runtime
## Что нужно спроектировать
**Полноценный редактор параметров в модале сценария.** Чтобы при выборе операции автоматически подгружались параметры из API и показывались с типами, дефолтами, valueList — как в ручном режиме (showParams в operations.js).
### Конкретные вопросы
1. **Как встроить params-render.js в редактор сценария?** Сейчас `showScenarioEditor` загружает сервисы. При выборе операции в шаге — нужно: (а) узнать svcOperationId (GET /api/operations/{svcId}), (б) загрузить параметры (GET /api/params/{svcOperationId}), (в) отрендерить их через `renderParamRow`. Где хранить загруженные параметры? В `scenarioEditorState`? В отдельном кеше?
2. **Как хранить параметры в состоянии шага?** Сейчас `step.params` — массив `[["key","val"],...]`. После загрузки из API там будут десятки параметров с дефолтами. Пользователь меняет некоторые. При сохранении — сохранять только изменённые или все? (Сейчас в БД — только изменённые, остальные берутся из дефолтов при запуске).
3. **Pre-fill параметров.** При смене операции: авто или по кнопке «Загрузить параметры»? При смене сервиса (create) — сбрасывать параметры?
4. **Отображение.** Где рендерить параметры в шаге: внутри карточки шага (может быть много) или в отдельной панели справа? Сейчас `operations.js` рендерит параметры в `#params-form` под списком инстансов — это отдельная область.
5. **Сбор параметров при сохранении.** `collectFormSteps()` сейчас собирает key=value. После перехода на params-render нужно будет использовать `collectParams()` с указанием контейнера шага. Как передать контейнер?
6. **Map-fixed параметры.** В operations.js они рендерятся с вложенными полями. В сценарном редакторе — нужен такой же рендер? Или упрощённый (JSON-строка)?
7. **Что делать с существующими сценариями?** У них параметры уже в БД как key=value. При редактировании — показывать только те поля, которые есть в steps? Или подгрузить все из API и смержить?
---
**ВАЖНО:** Пиши план прямо в чат текстом. Не сохраняй в session memory — я не смогу прочитать. Только в чат.
+45
View File
@@ -0,0 +1,45 @@
# Вопросы к Опусу — instance dropdown + RUNNING highlight
## Контекст
Проект: Nubes Autotest v1.2.5, Flask + vanilla JS + PostgreSQL.
Файл: `/home/naeel/nubes/autotest/app-autotest/site/static/js/scenario-form.js`
Для не-create операций (modify, delete, suspend, resume, redeploy) нужно выбрать инстанс.
**Что уже сделано (в рабочей копии, не закоммичено):**
- Дропдаун показывает ТОЛЬКО 🆕 output'ы предыдущих create-шагов
- Кнопка «📥 Из облака» — есть в разметке, функция `toggleCloudInstances(idx)` не написана
- Облачные инстансы загружены в `scenarioEditorState.cloudInstances`
## Вопросы
### 1. Фильтр облачных инстансов
Показывать только `displayName.startsWith('autotest-')`. Чужие инстансы — опасно.
### 2. Реализация кнопки «📥 Из облака»
При клике:
- Отфильтровать `st.cloudInstances`: `autotest-*` + `explainedStatus !== 'deleted'`
- Добавить `<option disabled>── облако ──</option>` в основной `<select id="step-{idx}-ref">`
- Затем добавить `<option>` для каждого: `☁ displayName — svc (status)`, value = instanceUid
- При повторном клике — убрать облачные option'ы (оставить output'ы)
Фильтр по `service_id` — не нужен, показывать все `autotest-*`.
### 3. Яркий фон для RUNNING
Файл: `/home/naeel/nubes/autotest/app-autotest/site/static/js/scenario-list.js`
В `loadScenarios()` строка:
```
html+=`<div style="...">Последний: ${icon} ${...} — ${last.status} ...</div>`;
```
Если `last.status === 'RUNNING'``background:#fef3c7;padding:2px 4px;border-radius:3px;`.
На кнопке `▶` — не надо.
---
Пиши ответ прямо в чат текстом.
+75
View File
@@ -0,0 +1,75 @@
# Prompt for Opus — Code Review v1.2.0
Проект: Nubes Autotest (Flask + vanilla JS + PostgreSQL)
План: `/home/naeel/nubes/autotest/DOCS/opus-plan-2026-07-31.md`
Вопросы/ответы: `/home/naeel/nubes/autotest/DOCS/opus-questions-2026-07-31.md`
## Что сделано
Реализованы Фазы 1-3 + начало Фазы 4. Модальный редактор сценариев НЕ сделан.
## Изменённые/новые файлы (для ревью)
### Новые файлы:
**1. `/home/naeel/nubes/autotest/app-autotest/site/api/utils.py`**
- `find_uid(resp)` — поиск UUID по верхнему уровню + вложенным dict
- `uid_from_location(loc)` — UUID из Location-заголовка
- Заменяет 2 разные реализации из api_test.py + scenario.py
**2. `/home/naeel/nubes/autotest/app-autotest/site/operations/executor.py`**
- `execute_operation(client, service_id, operation, instance_uid, params, svc_op_id=None, display_name=None)`
- Делает всё до /run: POST /instances → POST /instanceOperations → send_params_terraform → /run
- Ветвится по operation=="create" (свой payload, без svcOperationId)
- Возвращает dict {ok, error, failed_step, instance_uid, op_uid, display_name}
- НЕ поллит
**3. `/home/naeel/nubes/autotest/app-autotest/site/operations/poll.py`**
- `poll_until_done(client, op_uid, timeout=1800)` → {status, is_successful, error_log, stages, duration, svc}
- Общий цикл для async (_finish_op) и sync (run_scenario)
**4. `/home/naeel/nubes/autotest/app-autotest/site/static/js/params-render.js`**
- `renderParamRow(p, allInst)` — рендер параметра
- `renderMapFixedRow(p, dfl)` — рендер map-fixed с вложенными полями
- `collectParams(containerSelector)` — сбор параметров из DOM
- Вынесено из operations.js, используется обоими (ручной + сценарный)
### Изменённые файлы:
**5. `/home/naeel/nubes/autotest/app-autotest/site/operations/scenario.py`**
- Удалены _find_uid, _uid_from_location
- Добавлен import из executor, poll
- `_resolve_instance_uid(step, bindings, instance_map)` — приоритет: uid > ref > service_id
- `_update_bindings(scenario_run_id, bindings)` — персист в scenario_runs.instance_bindings
- `run_scenario` — create/non-create через executor, поллинг через poll_until_done, output→bindings
**6. `/home/naeel/nubes/autotest/app-autotest/site/routes/api_test.py`**
- Удалены _find_uid, _uid_from_location (импорт из api.utils)
- CREATE и non-CREATE флоу заменены на execute_operation
- _finish_op заменён на poll_until_done
- CMDB delete оставлен как предпроверка (не через executor)
**7. `/home/naeel/nubes/autotest/app-autotest/site/routes/api_scenario_defs.py`**
- `_validate_steps` расширен: output (уникальность, только create), instance_ref (ссылка на output), instance_uid
- Старый формат (без новых ключей) проходит валидацию (обратная совместимость)
**8. `/home/naeel/nubes/autotest/app-autotest/site/db/init_db.py`**
- Startup cleanup: `UPDATE scenario_runs SET status='TIMEOUT' WHERE status='RUNNING' AND created_at < NOW() - INTERVAL '1 hour'`
**9. `/home/naeel/nubes/autotest/app-autotest/site/static/js/operations.js`**
- Удалены renderParamRow, renderMapFixedRow, collectParams (теперь в params-render.js)
**10. `/home/naeel/nubes/autotest/app-autotest/site/templates/index.html`**
- Добавлен `<script src="js/params-render.js">` перед instances.js
**11. `/home/naeel/nubes/autotest/app-autotest/site/app.py`**
- VERSION = "1.2.0"
## Вопросы для ревью
1. **executor.py**: корректно ли обрабатываются все ошибки? Не потерялся ли tracker_add (в старом коде был ДО params/run, в executor его нет — он вызывается в api_test.py после executor)?
2. **scenario.py**: правильно ли резолвится instance_uid? Не сломается ли старый dummy_test без output/instance_ref?
3. **api_test.py**: CMDB delete остался как предпроверка — ок ли это?
4. **init_db.py**: startup cleanup — не затрёт ли легитимные долгоиграющие сценарии?
5. **params-render.js**: `collectParams` теперь с параметром `containerSelector` — не сломает ли это существующие вызовы без аргумента?
6. Общая архитектура: все ли зависимости корректны? Нет ли циклических импортов?