doc: полная хронология реализации polygon v0.2.0 (4 этапа)
This commit is contained in:
@@ -551,3 +551,163 @@ polygon/
|
|||||||
- YAML не руками — через `from_stands.py` из STANDS (37 сервисов)
|
- YAML не руками — через `from_stands.py` из STANDS (37 сервисов)
|
||||||
- `site/__init__.py` ⛔ нельзя
|
- `site/__init__.py` ⛔ нельзя
|
||||||
- Импорты без префикса `site.`
|
- Импорты без префикса `site.`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Полигон — реализация (2026-07-31, DeepSeek Pro 4)
|
||||||
|
|
||||||
|
### Архитектура утверждена (Sonnet 4.6)
|
||||||
|
|
||||||
|
Промпт Соннету в `polygon-docs/sonnet-polygon-prompt.md`, ответ в `polygon-docs/sonnet-response.md`.
|
||||||
|
Ссылки на генератор YAML: `polygon-docs/tf-provider-refs.md`.
|
||||||
|
|
||||||
|
Ключевые решения Соннета (отличия от Опуса):
|
||||||
|
- subresources: `kind == "subresource"` из STANDS YAML
|
||||||
|
- dtFinish: синхронный в `/run` (sleep → apply → dtFinish)
|
||||||
|
- Лишние операции (restart, recovery): включать все, no-op
|
||||||
|
- stateOut: авто-генерация из subresource-операций
|
||||||
|
- map с sub_params → dataDescriptor для всех типов
|
||||||
|
- 11 тестов (против 5 у Опуса)
|
||||||
|
- UUID: `uuid.uuid4()`
|
||||||
|
- Mock-эндпоинты: +`/_mock/state`, `/_mock/services`, `/_mock/delay`
|
||||||
|
|
||||||
|
Уточнения:
|
||||||
|
- Синхронный dtFinish (блокирует воркер, но MOCK_OP_DELAY ≤ 0.5s)
|
||||||
|
- Вариант Б: сгенерированные YAML коммитятся в репу (НЕ генерить на лету)
|
||||||
|
- `from_stands.py <STANDS_DIR>` — без хардкода, читает все .yaml из директории
|
||||||
|
|
||||||
|
### Сервис запущен на Nubes
|
||||||
|
|
||||||
|
- URL: `https://polygon.pythonk8s.dev.nubes.ru/`
|
||||||
|
- Репа: `https://gitea.services.ngcloud.ru/forcloud/polygon.git`
|
||||||
|
- InstanceUid: `db9d7835-1ef8-4fee-b42f-c91e1c0783cb`
|
||||||
|
- Мониторинг: Grafana (namespace db9d7835...)
|
||||||
|
|
||||||
|
### Этап 1 — from_stands.py (`77f12d2`)
|
||||||
|
|
||||||
|
Создан универсальный конвертер STANDS YAML → polygon config:
|
||||||
|
- `html.unescape()` для всех строк (`>` → `>`, `"` → `"`)
|
||||||
|
- Рекурсивный `dataDescriptor` из `sub_params` (для map, map-fixed, array-map-fixed)
|
||||||
|
- Авто-генерация `state_out_template` из subresource-операций
|
||||||
|
- `stateParams` из create-операции с JSON-генерацией для map-fixed
|
||||||
|
- `cfsParamsByOp` — связка opId → список paramId
|
||||||
|
- 210 строк, 37 YAML сгенерировано, 0 ошибок
|
||||||
|
- Все YAML валидны, HTML entities раскодированы
|
||||||
|
|
||||||
|
### Этап 2 — config_loader + mock_state + state_machine (`1956fb7`)
|
||||||
|
|
||||||
|
**config_loader.py** (50 строк):
|
||||||
|
- Загружает все YAML из `services/`, строит `{svcId: def}` + `{opId: def}`
|
||||||
|
- 37 сервисов, 245 операций в индексе
|
||||||
|
|
||||||
|
**mock_state.py** (150 строк):
|
||||||
|
- `MockState` синглтон: instances, operations, op_params
|
||||||
|
- `create_instance()` → UUID v4, статус "creating"
|
||||||
|
- `create_operation()` → UUID v4, dtFinish=None
|
||||||
|
- `list_instances()` с пагинацией (pageSize≤200, стоп по len<pageSize)
|
||||||
|
- `set_param()`, `get_params()`, `reset()`
|
||||||
|
|
||||||
|
**state_machine.py** (140 строк):
|
||||||
|
- `apply_effect()` — мутирует MockState по kind/action:
|
||||||
|
- instance+create → статус running, stateParams из шаблона, stateOut из шаблона
|
||||||
|
- instance+modify → мерж params через cfsParamsByOp
|
||||||
|
- instance+delete → удалить инстанс
|
||||||
|
- instance+suspend/resume/redeploy → статус
|
||||||
|
- subresource+create → state.out[plural][name] = {}
|
||||||
|
- subresource+delete → del state.out[plural][name]
|
||||||
|
- `_extract_subresource_name()` — ищет имя в op_params, fallback на subresource_name
|
||||||
|
|
||||||
|
### Этап 3 — app.py: 17 эндпоинтов (`d4c2a26`)
|
||||||
|
|
||||||
|
| # | Метод | Путь | Детали |
|
||||||
|
|---|-------|------|--------|
|
||||||
|
| 1 | GET | `/health` | "OK" |
|
||||||
|
| 2 | GET | `/` | HTML: версия, счётчики, delay |
|
||||||
|
| 3 | GET | `/api/v1/svc/services` | список всех сервисов |
|
||||||
|
| 4 | GET | `/api/v1/svc/services/<id>` | операции сервиса |
|
||||||
|
| 5 | GET | `/api/v1/svc/instances` | пагинация (pageSize, page) |
|
||||||
|
| 6 | GET | `/api/v1/svc/instances/<uid>` | полный instance+state |
|
||||||
|
| 7 | POST | `/api/v1/svc/instances` | 201 + Location: ./{uid} |
|
||||||
|
| 8 | GET | `/api/v1/svc/instanceOperations/default/<id>` | cfsParams с dataDescriptor |
|
||||||
|
| 9 | POST | `/api/v1/svc/instanceOperations` | 201 + Location, auto-find create opId |
|
||||||
|
| 10 | GET | `/api/v1/svc/instanceOperations/<uid>` | +cfsParams если ?fields=... |
|
||||||
|
| 11 | POST | `/api/v1/svc/instanceOperationCfsParams` | paramId → value |
|
||||||
|
| 12 | GET | `/api/v1/svc/instanceOperations/<uid>/validate-cfs` | **пустое тело**, 200 |
|
||||||
|
| 13 | POST | `/api/v1/svc/instanceOperations/<uid>/run` | sleep(delay) → apply_effect → dtFinish |
|
||||||
|
| 14 | POST | `/api/v1/svc/_mock/reset` | сброс состояния |
|
||||||
|
| 15 | GET | `/api/v1/svc/_mock/state` | отладка: instances + operations |
|
||||||
|
| 16 | GET | `/api/v1/svc/_mock/services` | отладка: все сервисы |
|
||||||
|
| 17 | POST | `/api/v1/svc/_mock/delay/<s>` | изменить MOCK_OP_DELAY |
|
||||||
|
|
||||||
|
Критические детали:
|
||||||
|
- `default/<int:op_id>` строго ДО `<uid>` в маршрутах Flask
|
||||||
|
- `validate-cfs`: `return "", 200` (НЕ jsonify)
|
||||||
|
- `_now()`: ISO-формат с 'Z'
|
||||||
|
|
||||||
|
### v0.1.0 → v0.2.0 (`4e136cd`)
|
||||||
|
|
||||||
|
Bump версии после трёх этапов изменений.
|
||||||
|
|
||||||
|
### Этап 4 — тесты (`760d16e`)
|
||||||
|
|
||||||
|
**test_converter.py** (10 тестов):
|
||||||
|
- basic_fields, lifecycle, operations_count
|
||||||
|
- html_unescape, value_list, state_params_from_create
|
||||||
|
- data_descriptor_from_sub_params, state_out_subresources
|
||||||
|
- cfs_params_by_op, roundtrip (запись/чтение YAML)
|
||||||
|
|
||||||
|
**test_state_machine.py** (9 тестов):
|
||||||
|
- create → running + params + state.out
|
||||||
|
- delete → инстанс удалён
|
||||||
|
- suspend → suspended
|
||||||
|
- resume → running
|
||||||
|
- modify → params мержатся
|
||||||
|
- create_user → state.out.users[name]
|
||||||
|
- delete_user → users[name] удалён
|
||||||
|
- reset → всё пусто
|
||||||
|
|
||||||
|
**Все 19 тестов PASS.**
|
||||||
|
|
||||||
|
### Проверка в кубере
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh naeel@5.172.178.213 kubectl -n db9d7835... logs deploy/pythonk8s --tail=20
|
||||||
|
```
|
||||||
|
- Под: `1/1 Running`, перезапущен
|
||||||
|
- Логи: все curl-запросы (201, 200), ни одной ошибки
|
||||||
|
|
||||||
|
### Проверка curl (deployed)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://polygon.pythonk8s.dev.nubes.ru/health → OK
|
||||||
|
37 services, create flow: 201+Location → run → status=running, params=12
|
||||||
|
```
|
||||||
|
|
||||||
|
### Файлы polygon-docs/ (в корне autotest)
|
||||||
|
|
||||||
|
- `sonnet-polygon-prompt.md` — промпт для Claude Sonnet 4.6
|
||||||
|
- `sonnet-response.md` — полный ответ Соннета (архитектура + план)
|
||||||
|
- `tf-provider-refs.md` — ссылки на генератор YAML в `~/tf_provider`
|
||||||
|
|
||||||
|
### Итоговая структура polygon
|
||||||
|
|
||||||
|
```
|
||||||
|
polygon/
|
||||||
|
├── requirements.txt
|
||||||
|
├── README.md
|
||||||
|
├── .gitignore
|
||||||
|
├── tests/
|
||||||
|
│ ├── test_converter.py # 10 тестов
|
||||||
|
│ └── test_state_machine.py # 9 тестов
|
||||||
|
└── site/
|
||||||
|
├── app.py # 17 эндпоинтов
|
||||||
|
├── mock_state.py # MockState (in-memory)
|
||||||
|
├── state_machine.py # apply_effect()
|
||||||
|
├── config_loader.py # загрузка YAML
|
||||||
|
├── from_stands.py # конвертер STANDS → polygon
|
||||||
|
└── services/ # 37 сгенерированных YAML
|
||||||
|
```
|
||||||
|
|
||||||
|
~900 строк Python, 37 YAML-конфигов, 19 тестов PASS.
|
||||||
|
Задеплоено, проверено через curl и kubectl.
|
||||||
|
Готово к интеграции с app-autotest.
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
| `2026-07-24-session-6.md` | 24.07.2026 | Сессия 6 |
|
| `2026-07-24-session-6.md` | 24.07.2026 | Сессия 6 |
|
||||||
| `2026-07-29-session.md` | 29.07.2026 | Сессия: CMDB delete, переписка с Георгием |
|
| `2026-07-29-session.md` | 29.07.2026 | Сессия: CMDB delete, переписка с Георгием |
|
||||||
| `2026-07-30-session.md` | 30.07.2026 | Сессия |
|
| `2026-07-30-session.md` | 30.07.2026 | Сессия |
|
||||||
| `2026-07-31-session.md` | 31.07.2026 | **Текущая.** Аудит Codex (3 раунда), полигон (план + отдельная репа), v1.2.16→v1.2.23 |
|
| `2026-07-31-session.md` | 31.07.2026 | **Текущая.** Основная сессия: унификация executor (v1.2.0-v1.2.16), аудит Codex (3 раунда, v1.2.19-v1.2.23), архитектура полигона (Опус + Соннет), **реализация polygon v0.2.0** (4 этапа, 17 эндпоинтов, 19 тестов PASS) |
|
||||||
|
|
||||||
## Формат
|
## Формат
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user