fix: code review Sonnet — 2 крит. фикса + README v0.2.0
This commit is contained in:
@@ -1,41 +1,80 @@
|
||||
# polygon v0.1.0
|
||||
# polygon v0.2.0
|
||||
|
||||
Mock-эмулятор Nubes API для интеграционных тестов app-autotest.
|
||||
Эмулятор REST API облачной платформы Nubes для интеграционных тестов app-autotest.
|
||||
|
||||
Отдельный Flask-процесс (порт 5001), притворяющийся Nubes REST API.
|
||||
Data-driven: сервисы генерируются из STANDS YAML через `from_stands.py`.
|
||||
Отдельный managed-сервис на Nubes pythonk8s: `polygon.pythonk8s.dev.nubes.ru`.
|
||||
Притворяется реальным Nubes API (префикс `/api/v1/svc`).
|
||||
|
||||
## Архитектура
|
||||
|
||||
```
|
||||
polygon/
|
||||
├── server.py # Flask-приложение, префикс /api/v1/svc
|
||||
├── state.py # MockState — состояние в памяти
|
||||
├── config_loader.py # загрузка YAML + достройка defaults
|
||||
├── defaults.py # default_for(dataType)
|
||||
├── from_stands.py # конвертер STANDS YAML → polygon/services/*.yaml
|
||||
└── services/ # сгенерированные конфиги (37 сервисов)
|
||||
├── requirements.txt # Flask>=3.0, gunicorn>=21.2, PyYAML>=6.0
|
||||
├── tests/
|
||||
│ ├── test_converter.py # 10 юнит-тестов from_stands.py
|
||||
│ └── test_state_machine.py # 9 юнит-тестов state_machine.py
|
||||
└── site/
|
||||
├── app.py # Flask (17 эндпоинтов)
|
||||
├── mock_state.py # MockState: instances, operations, op_params
|
||||
├── state_machine.py # apply_effect() — мутация состояния
|
||||
├── config_loader.py # загрузка services/*.yaml
|
||||
├── from_stands.py # конвертер STANDS YAML → polygon config
|
||||
└── services/ # 37 YAML-конфигов (сгенерированы)
|
||||
```
|
||||
|
||||
⛔ **Ровно 1 gunicorn-воркер.** Состояние в памяти, не shared.
|
||||
|
||||
## Запуск
|
||||
|
||||
```bash
|
||||
STANDS_DIR=../STANDS/test/resources_yaml python server.py
|
||||
# Локально
|
||||
cd site && python app.py # порт 5000
|
||||
|
||||
# Тесты
|
||||
pytest tests/ -v # 19 тестов
|
||||
|
||||
# Генерация конфигов из STANDS YAML
|
||||
cd site && python from_stands.py <STANDS_DIR> services/
|
||||
```
|
||||
|
||||
## Тесты
|
||||
## API (17 эндпоинтов)
|
||||
|
||||
```bash
|
||||
NUBES_API_ENDPOINT=http://localhost:5001/api/v1/svc pytest ../app-autotest/tests/ -v
|
||||
```
|
||||
| Метод | Путь | Назначение |
|
||||
|-------|------|------------|
|
||||
| GET | `/health` | Healthcheck |
|
||||
| GET | `/` | HTML с версией |
|
||||
| GET | `/api/v1/svc/services` | Список сервисов |
|
||||
| GET | `/api/v1/svc/services/<id>` | Операции сервиса |
|
||||
| GET | `/api/v1/svc/instances` | Пагинация |
|
||||
| GET | `/api/v1/svc/instances/<uid>` | Инстанс + state |
|
||||
| POST | `/api/v1/svc/instances` | Создать → 201 + Location |
|
||||
| GET | `/api/v1/svc/instanceOperations/default/<id>` | cfsParams |
|
||||
| POST | `/api/v1/svc/instanceOperations` | Создать операцию → 201 + Location |
|
||||
| GET | `/api/v1/svc/instanceOperations/<uid>` | Статус + cfsParams |
|
||||
| POST | `/api/v1/svc/instanceOperationCfsParams` | param → value |
|
||||
| GET | `/api/v1/svc/instanceOperations/<uid>/validate-cfs` | 200, пустое тело |
|
||||
| POST | `/api/v1/svc/instanceOperations/<uid>/run` | Выполнить |
|
||||
| POST | `/api/v1/svc/_mock/reset` | Сброс |
|
||||
| GET | `/api/v1/svc/_mock/state` | Отладка: состояние |
|
||||
| GET | `/api/v1/svc/_mock/services` | Отладка: сервисы |
|
||||
| POST | `/api/v1/svc/_mock/delay/<s>` | MOCK_OP_DELAY |
|
||||
|
||||
## Сброс состояния
|
||||
## Переменные окружения
|
||||
|
||||
```http
|
||||
POST /_mock/reset
|
||||
```
|
||||
| Переменная | По умолчанию | Описание |
|
||||
|------------|-------------|----------|
|
||||
| `MOCK_OP_DELAY` | `0.1` | Задержка операции в секундах |
|
||||
| `WEB_CONCURRENCY` | `1` | ⛔ Не менять — ровно 1 воркер |
|
||||
|
||||
## Деплой
|
||||
|
||||
- Репозиторий: `https://gitea.services.ngcloud.ru/forcloud/polygon.git`
|
||||
- URL: `https://polygon.pythonk8s.dev.nubes.ru/`
|
||||
- Nubes pythonk8s managed service
|
||||
|
||||
## Связанные документы
|
||||
|
||||
- [DOCS/polygon-plan.md](../DOCS/polygon-plan.md) — полный план реализации
|
||||
- [AGENT_BRIEFING.md](../AGENT_BRIEFING.md) — контекст проекта app-autotest
|
||||
- [DOCS/polygon-plan.md](../DOCS/polygon-plan.md) — план реализации
|
||||
- [polygon-docs/sonnet-code-review-prompt.md](../polygon-docs/sonnet-code-review-prompt.md) — промпт code review
|
||||
- [polygon-docs/tf-provider-refs.md](../polygon-docs/tf-provider-refs.md) — ссылки на генератор YAML
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
polygon v0.1.0 — Mock Nubes API.
|
||||
polygon v0.2.0 — Mock Nubes API.
|
||||
Эмулятор REST API облачной платформы Nubes для интеграционных тестов.
|
||||
|
||||
Все эндпоинты с префиксом /api/v1/svc притворяются реальным Nubes API.
|
||||
@@ -7,10 +7,12 @@ polygon v0.1.0 — Mock Nubes API.
|
||||
Конфиги сервисов — из services/*.yaml (сгенерированы from_stands.py).
|
||||
|
||||
Деплой: Nubes pythonk8s (managed service) с gunicorn:
|
||||
gunicorn app:app --workers 2 --bind 0.0.0.0:8000
|
||||
gunicorn app:app --workers 1 --bind 0.0.0.0:8000
|
||||
⛔ РОВНО 1 ВОРКЕР — состояние в памяти, не shared между процессами.
|
||||
|
||||
Переменные окружения:
|
||||
MOCK_OP_DELAY — задержка операции в секундах (по умолчанию 0.1)
|
||||
WEB_CONCURRENCY — число gunicorn-воркеров (принудительно 1)
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -19,6 +21,10 @@ from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, jsonify, make_response, request
|
||||
|
||||
# ⛔ Принудительно 1 воркер — состояние в памяти, иначе инстансы теряются.
|
||||
# setdefault не перезапишет если Nubes/Procfile уже выставил WEB_CONCURRENCY=1.
|
||||
os.environ.setdefault("WEB_CONCURRENCY", "1")
|
||||
|
||||
import config_loader
|
||||
import mock_state
|
||||
import state_machine
|
||||
|
||||
@@ -138,8 +138,9 @@ def _merge_params(inst, op_params, svc_operation_id, services):
|
||||
|
||||
for pid in param_ids_for_op:
|
||||
if pid in op_params:
|
||||
code = cfs_params[pid]["svcOperationCfsParam"]
|
||||
inst["state"]["params"][code] = op_params[pid]
|
||||
p = cfs_params.get(pid)
|
||||
if p:
|
||||
inst["state"]["params"][p["svcOperationCfsParam"]] = op_params[pid]
|
||||
|
||||
|
||||
def _extract_subresource_name(op_params, subresource_name):
|
||||
|
||||
Reference in New Issue
Block a user