DOCS: architecture-next update + opus frontend/instance/review prompts
This commit is contained in:
+23
-27
@@ -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
|
||||
- [↑][↓] перестановка шагов
|
||||
|
||||
@@ -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 — я не смогу прочитать. Только в чат.
|
||||
@@ -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;`.
|
||||
На кнопке `▶` — не надо.
|
||||
|
||||
---
|
||||
|
||||
Пиши ответ прямо в чат текстом.
|
||||
@@ -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. Общая архитектура: все ли зависимости корректны? Нет ли циклических импортов?
|
||||
@@ -1,4 +1,4 @@
|
||||
# 2026-07-31 — Сессия (v1.1.57 → ...)
|
||||
# 2026-07-31 — Сессия (v1.1.57 → v1.2.1)
|
||||
|
||||
## Контекст
|
||||
Обсуждение архитектуры: унификация ручного и сценарного режимов, гибкие ссылки на инстансы, новый UI редактора сценариев.
|
||||
@@ -69,3 +69,68 @@
|
||||
- E17. lock_check оставить
|
||||
- E18. _op_results не в scope
|
||||
- E19. Порядок: executor → формат → api_test/scenario → UI
|
||||
|
||||
### Финальный план (Опус, утверждён)
|
||||
|
||||
Сохранён в `DOCS/opus-plan-2026-07-31.md`. Ветка: `opus-architecture-2026-07-31`.
|
||||
|
||||
**4 фазы, 13 шагов:**
|
||||
|
||||
**Фаза 1 — Общие модули:**
|
||||
- `api/utils.py` (NEW) — find_uid(), uid_from_location()
|
||||
- `operations/poll.py` (NEW) — poll_until_done()
|
||||
- `operations/executor.py` (NEW) — execute_operation() до /run, без поллинга
|
||||
|
||||
**Фаза 2 — Формат шагов:**
|
||||
- `routes/api_scenario_defs.py` — _validate_steps с output/instance_ref/instance_uid
|
||||
- `operations/scenario.py` — резолвинг instance_uid > instance_ref > service_id
|
||||
|
||||
**Фаза 3 — Миграция вызывающих:**
|
||||
- `routes/api_test.py` — CMDB delete early return, остальное через executor
|
||||
- `operations/scenario.py` — через executor + poll_until_done
|
||||
- `db/init_db.py` — startup cleanup зависших scenario_runs
|
||||
|
||||
**Фаза 4 — UI редактора:**
|
||||
- `static/js/params-render.js` (NEW) — общий рендер параметров
|
||||
- `static/js/operations.js` — использовать params-render.js
|
||||
- `static/js/scenario-form.js` — модальный редактор
|
||||
- `templates/index.html` — разметка модала
|
||||
|
||||
### CMDB delete
|
||||
Жёсткое удаление через `DELETE cmdb-api.deck.nubes.ru/instances/{uid}` (без авторизации).
|
||||
Нужно для недосозданных инстансов (not created). Остаётся в api_test.py, не в executor.
|
||||
Добавлено после переписки с Георгием Родионовым 29.07.2026.
|
||||
|
||||
## Реализация (v1.2.0 — v1.2.1)
|
||||
|
||||
### v1.2.0 — Unified executor + flexible refs
|
||||
**Новые файлы:** api/utils.py, operations/poll.py, operations/executor.py, static/js/params-render.js
|
||||
**Изменено:** api_test.py (через executor + poll), scenario.py (output/ref/bindings), api_scenario_defs.py (_validate_steps), init_db.py (cleanup), operations.js (→ params-render), index.html (load order)
|
||||
- Дублирование CREATE-флоу устранено: ручной и сценарный → один executor
|
||||
- instance_uid > instance_ref > service_id (гибкие ссылки)
|
||||
- Общий поллинг poll_until_done()
|
||||
- +254 / −277 строк (меньше кода)
|
||||
|
||||
### v1.2.1 — Opus review fixes
|
||||
**Критическое:** tracker_add внутрь executor (защита от сирот, A3)
|
||||
**Исправлено:** labelCls в renderMapFixedRow, descr с контекстом, порядок скриптов
|
||||
**5 файлов:** executor.py, api_test.py, scenario.py, params-render.js, app.py
|
||||
|
||||
### Проверка в поде (v1.2.1)
|
||||
- Все 4 новых файла на месте
|
||||
- 11 JS → 200, порядок правильный
|
||||
- Schema OK, seed OK, API отвечает
|
||||
|
||||
## Что дальше
|
||||
|
||||
**Фаза 4 — модальный редактор сценариев (✅ v1.2.2-v1.2.4):**
|
||||
- ✅ Модал с дропдаунами сервисов/операций
|
||||
- ✅ output/instance_ref с облачными инстансами
|
||||
- ✅ Кнопки CRUD крупнее, справка «📖 Как заполнять»
|
||||
|
||||
**Фаза 5 — редактор параметров (план от Опус, НЕ РЕАЛИЗОВАНО):**
|
||||
- Заменить ручной key=value на автоподгрузку через params-render.js
|
||||
- Параметры в свёрнутом `<details>` внутри карточки шага
|
||||
- Хранение: символические имена в БД, обратный маппинг numeric→name при сохранении
|
||||
- Снапшот параметров перед ре-рендером (защита от потери правок)
|
||||
- 3 развилки решены: без ссылок на output в параметрах, всегда шаблон, полный сброс при смене операции
|
||||
|
||||
Reference in New Issue
Block a user