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. Общая архитектура: все ли зависимости корректны? Нет ли циклических импортов?
|
||||
Reference in New Issue
Block a user