diff --git a/TASKS/mock-architecture-prompt.md b/TASKS/mock-architecture-prompt.md new file mode 100644 index 0000000..0bde292 --- /dev/null +++ b/TASKS/mock-architecture-prompt.md @@ -0,0 +1,135 @@ +# Задача: архитектура эмулятора Nubes API для интеграционных тестов + +## Контекст + +**app-autotest** — Flask-приложение для тестирования сервисов облачной платформы Nubes. Позволяет вручную и через сценарии запускать операции (create/modify/delete/suspend/resume/redeploy) над сервисами через REST API. + +**Проблема:** реальные тесты идут 2-30 минут на операцию, жрут ресурсы облака, недетерминированы. Нужен эмулятор Nubes API чтобы гонять интеграционные тесты мгновенно и бесплатно. + +**Цель:** спроектировать архитектуру эмулятора, который притворяется Nubes API для ЛЮБОГО сервиса, описанного в YAML-конфиге. Не хардкод под каждый сервис, а data-driven подход. + +## Что почитать Опусу (обязательно) + +1. **`DOCS/ARCHITECTURE.md`** — полная архитектура приложения (раздел 8 про безопасность пропустить) +2. **`app-autotest/site/api/http_client.py`** — как приложение общается с Nubes API (GET/POST, Location, автостенд) +3. **`app-autotest/site/operations/terraform.py`** — логика параметров: cfsParams, normalize_value, resolve_ref_svc, send_params_terraform +4. **`app-autotest/site/operations/get_params.py`** — как достаются state.params и state.out из инстанса +5. **`app-autotest/site/operations/executor.py`** — единый шлюз запуска операций (это то что будет вызывать эмулятор) +6. **`app-autotest/site/operations/poll.py`** — поллинг до dtFinish (эмулятор должен отдавать dtFinish) + +**НЕ читать:** HISTORY, DOCS/* кроме ARCHITECTURE.md, JS-файлы, routes, db. Только backend-ядро. + +## Что должен делать эмулятор + +Принимать те же HTTP-запросы что и реальный Nubes API и отдавать валидные ответы. Ниже — обязательные эндпоинты. + +### 1. Сервисы +``` +GET /services → {results: [{svcId, svc, svcExtendedName, operations}]} +GET /services/{id} → {svc: {svc, svcShort, operations: [{svcOperationId, operation, isCreate}]}} +``` + +### 2. Инстансы +``` +POST /instances → 201 + Location: ./uuid + body: {serviceId, displayName, descr} + ответ: {instanceUid} + +GET /instances?pageSize=N&page=P → {results: [{instanceUid, displayName, serviceId, svc, explainedStatus, ...}]} + пагинация: pageSize=200 макс, остановка по len(batch) < pageSize + +GET /instances/{uid} → {instance: {instanceUid, displayName, serviceId, svc, explainedStatus, state: {params: {...}, out: {...}}}} + state.params — ТЕКУЩИЕ значения параметров (ключ = код, напр. "durationMs": "0") + state.out — доп. данные: {users: {pgadmin: {}}, databases: {mydb: {}}} +``` + +### 3. Операции +``` +POST /instanceOperations → {instanceOperationUid} + body: {instanceUid, svcOperationId, operation} + +POST /instanceOperationCfsParams → {} + body: {instanceOperationUid, svcOperationCfsParamId, paramValue} + +GET /instanceOperations/{uid}?fields=dtFinish,isSuccessful,errorLog,duration,stages,svc + → {instanceOperation: {dtFinish, isSuccessful, errorLog, duration, stages, svc}} + dtFinish — ключевое: если есть → операция завершена + stages: [{stage, dtStart, dtFinish, isSuccessful, duration}, ...] + +POST /instanceOperations/{uid}/run → {} + После этого операция считается запущенной, через N секунд появляется dtFinish + +GET /instanceOperations/default/{id} → {svcOperation: {cfsParams: [{svcOperationCfsParamId, svcOperationCfsParam, dataType, isRequired, defaultValue, valueList, refSvcId, dataDescriptor}]}} + +GET /instanceOperations/{uid}/validate-cfs → {} (200 OK, пустое тело = успех) +``` + +## Что эмулятор НЕ должен делать + +- Реально выполнять операции (не Terraform, не Ansible, не K8s) +- Проверять валидность параметров (всегда validate-cfs = OK) +- Хранить данные в БД (всё в памяти процесса) +- Работать с реальными токенами (принимать любой) + +## Ключевые вопросы для проектирования + +### Q1. Конфигурация сервисов + +Формат YAML для описания сервиса должен покрывать: +- Базовые поля: svcId, svc (имя), svcExtendedName +- Операции: create, modify, delete, suspend, resume, redeploy (у каждого свой svcOperationId) +- cfsParams: для КАЖДОГО параметра — id, код, тип, default, valueList, isRequired, refSvcId, dataDescriptor +- stateParams: значения по умолчанию после create +- stateOut: структура для users/databases (PG) и подобного + +Вопрос: как компактно описать cfsParams для сервисов с 20+ параметрами? Может ли эмулятор сам сгенерировать разумные defaults по типам? + +### Q2. Состояние инстансов + +Эмулятор должен отслеживать: +- Какие инстансы созданы (instanceUid → {serviceId, displayName, params, status}) +- Статус: creating → running (после create), suspending → suspended, modifying → running, deleting → deleted +- После delete — инстанс исчезает из GET /instances + +Вопрос: как моделировать explainedStatus? Простая машина состояний или хардкод? + +### Q3. Поллинг и время + +После POST /run операция должна «выполняться» N секунд, потом появляется dtFinish. N можно настраивать (для тестов — 0.1с, для демо — 2с). + +Вопрос: как эмулятор понимает что операция «завершена»? Таймер? Или сразу при запросе проверять время? + +### Q4. Интеграция с app-autotest + +Приложение сейчас использует `NUBES_API_ENDPOINT` из env. При `NUBES_MOCK=1` подставляется `http://localhost:5001/api/v1/svc`. + +Вопрос: нужно ли чтобы эмулятор запускался как отдельный процесс (порт 5001), или можно встроить как Flask blueprint в то же приложение? + +### Q5. Тестовые сценарии + +После создания эмулятора — интеграционные тесты. Минимальный набор: +1. create Болванку → проверить instanceUid +2. modify параметр → проверить изменение state.params +3. delete → проверить исчезновение из GET /instances +4. Сценарий: create→modify→delete через run_scenario +5. Для PG: create → проверить state.out.users и state.out.databases + +Вопрос: должны ли тесты использовать реальный `app_client` (Flask test client) или напрямую дёргать эмулятор? + +## Ожидаемый ответ + +Структурированный план: +1. Архитектура эмулятора (файлы, классы, модули) +2. Формат services.yaml с примерами для Болванки и PostgreSQL +3. Машина состояний инстансов +4. Механизм поллинга (как эмулировать dtFinish) +5. Точки интеграции с app-autotest +6. План тестов +7. Порядок реализации (MVP → полная версия) + +## Ограничения + +- Только Python (Flask), никаких новых зависимостей кроме PyYAML +- Без БД, всё в памяти +- Без многопоточности (один процесс, один пользователь) +- Код должен быть ПРОСТЫМ — эмулятор не должен быть сложнее тестируемого приложения