Files
autotest/TASKS/mock-architecture-prompt.md
T

136 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Задача: архитектура эмулятора 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
- Без БД, всё в памяти
- Без многопоточности (один процесс, один пользователь)
- Код должен быть ПРОСТЫМ — эмулятор не должен быть сложнее тестируемого приложения