140 lines
6.5 KiB
Markdown
140 lines
6.5 KiB
Markdown
# Консультация: интеграция polygon ↔ app-autotest
|
|
|
|
> Адресат: Claude Sonnet 4.6 (новый чат)
|
|
> Дата: 2026-07-31
|
|
> ⛔ ОТВЕТ — ТОЛЬКО В ЧАТ. Не редактировать файлы.
|
|
|
|
---
|
|
|
|
## Контекст
|
|
|
|
**Polygon** (v0.2.4) — эмулятор Nubes API. Задеплоен на `polygon.pythonk8s.dev.nubes.ru`,
|
|
17 эндпоинтов с префиксом `/api/v1/svc`, 37 сервисов, все в памяти.
|
|
Принимает те же запросы что реальный Nubes API: POST /instances → 201 + Location,
|
|
POST /instanceOperations → 201 + Location, GET /instanceOperations/default/{id} → cfsParams,
|
|
POST /run → sleep + apply_effect + dtFinish.
|
|
|
|
**app-autotest** (v1.2.23) — Flask-приложение для ручного/сценарного тестирования Nubes.
|
|
Делает реальные HTTP-запросы к Nubes API через `HttpClient` (обёртка над `requests.Session`).
|
|
Сейчас ходит только в реальные dev/test стенды.
|
|
|
|
**Задача:** сделать так чтобы app-autotest мог ходить в polygon вместо реального API.
|
|
|
|
## Как app-autotest подключается к API (сейчас)
|
|
|
|
Файл `api/auth.py`:
|
|
|
|
```python
|
|
def get_client():
|
|
token = get_token()
|
|
endpoint = detect_endpoint(token) or current_app.config["NUBES_API_ENDPOINT"]
|
|
return HttpClient(endpoint, token)
|
|
|
|
def get_stand():
|
|
token = get_token()
|
|
endpoint = detect_endpoint(token) or current_app.config["NUBES_API_ENDPOINT"]
|
|
return stand_name(endpoint)
|
|
```
|
|
|
|
`detect_endpoint(token)` — пробует dev/test стенды, возвращает URL первого ответившего.
|
|
Хардкод: `["https://lk-api-gateway-dev...", "https://lk-api-gateway-test..."]`.
|
|
|
|
`stand_name(endpoint)` — "dev" или "test" по URL.
|
|
|
|
`HttpClient(endpoint, token)` — обёртка `requests.Session`:
|
|
- `get(path)` — GET, `.json()`
|
|
- `post(path, body)` — POST, извлекает UUID из заголовка `Location`
|
|
|
|
## Проблема
|
|
|
|
`detect_endpoint(token)` ВСЕГДА находит реальный стенд (токен валиден).
|
|
До fallback на `NUBES_API_ENDPOINT` дело НЕ доходит.
|
|
Даже при `NUBES_API_ENDPOINT=http://localhost:5000` app-autotest долбится в облако.
|
|
|
|
## Предлагаемое решение
|
|
|
|
Добавить проверку localhost в `get_client()` и `get_stand()`:
|
|
|
|
```python
|
|
def _is_localhost(url):
|
|
return (url or "").startswith(("http://localhost", "http://127.0.0.1"))
|
|
|
|
def get_client():
|
|
token = get_token()
|
|
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
|
if not _is_localhost(endpoint):
|
|
endpoint = detect_endpoint(token) or endpoint
|
|
return HttpClient(endpoint, token)
|
|
|
|
def get_stand():
|
|
token = get_token()
|
|
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
|
if _is_localhost(endpoint):
|
|
return "mock"
|
|
endpoint = detect_endpoint(token) or endpoint
|
|
return stand_name(endpoint)
|
|
```
|
|
|
|
Логика:
|
|
- Если `NUBES_API_ENDPOINT` указывает на localhost → пропустить detect_endpoint, сразу использовать его
|
|
- `get_stand()` для localhost → "mock" (вместо "?" которое вернёт stand_name для неизвестного URL)
|
|
- Ноль новых env-переменных, `NUBES_API_ENDPOINT` уже есть в конфиге
|
|
|
|
## Вопросы к Соннету
|
|
|
|
### Q1. Достаточно ли проверки localhost?
|
|
|
|
Сейчас: `startswith(("http://localhost", "http://127.0.0.1"))`.
|
|
|
|
Что насчёт:
|
|
- `https://polygon.pythonk8s.dev.nubes.ru` — удалённый polygon, НЕ localhost. `detect_endpoint` попытается dev/test и упадёт (потому что polygon не вернёт реальный токен-челлендж). Нужна ли более широкая проверка — например «любой не-deck URL»?
|
|
- IPv6 localhost `[::1]`?
|
|
- Docker-сети `http://host.docker.internal`?
|
|
|
|
### Q2. stand_name для polygon
|
|
|
|
Сейчас `stand_name("http://localhost:5000")` вернёт `"?"` потому что там нет "dev"/"test".
|
|
Мы предлагаем "mock" для localhost. Но что насчёт:
|
|
- `https://polygon.pythonk8s.dev.nubes.ru` — stand_name вернёт `"?"` потому что в URL нет "dev"/"test". Нужно ли добавить "polygon" в stand_name?
|
|
- Трекер инстансов (`/tmp/instances-{clientId}-{stand}.json`) использует stand для имени файла. "?" или "mock" — ок, но для удалённого polygon тоже будет "?".
|
|
|
|
### Q3. HttpClient — нужны ли изменения?
|
|
|
|
Polygon отдаёт ровно те же форматы что реальный API:
|
|
- `Location: ./{uuid}` на POST /instances и POST /instanceOperations
|
|
- `{"results": [...]}` на GET /instances
|
|
- `{"svcOperation": {"cfsParams": [...]}}` на GET /instanceOperations/default/{id}
|
|
- Пустое тело 200 на validate-cfs
|
|
|
|
Нужно ли что-то менять в `HttpClient.post()` или `http_client.py`?
|
|
|
|
### Q4. Токен для polygon
|
|
|
|
Polygon НЕ проверяет токен (все `_mock/*` открыты, основные эндпоинты тоже без auth).
|
|
app-autotest ВСЕГДА шлёт `Authorization: Bearer <token>` через HttpClient.
|
|
|
|
Это ок? Или polygon должен проверять токен (хотя бы непустой)?
|
|
|
|
### Q5. Порядок запуска для тестов
|
|
|
|
При локальном тестировании:
|
|
```bash
|
|
# Терминал 1: polygon
|
|
cd polygon/site && python app.py # порт 5000
|
|
|
|
# Терминал 2: app-autotest → polygon
|
|
cd app-autotest/site && \
|
|
NUBES_API_ENDPOINT=http://localhost:5000/api/v1/svc \
|
|
python app.py # порт 5001 или другой
|
|
```
|
|
|
|
Нет ли коллизий портов? app-autotest по умолчанию на 5000, polygon тоже на 5000.
|
|
|
|
### Q6. Альтернативный подход
|
|
|
|
Вместо проверки localhost, может лучше:
|
|
- Новая env-переменная `NUBES_MOCK=1` — явное переключение в режим мока?
|
|
- Или `NUBES_API_ENDPOINT` как единственный источник, а detect_endpoint вызывать только если endpoint НЕ задан явно?
|
|
|
|
Какой подход надёжнее?
|