diff --git a/HISTORY/README-NEW-CHAT.md b/HISTORY/README-NEW-CHAT.md new file mode 100644 index 0000000..67d42fd --- /dev/null +++ b/HISTORY/README-NEW-CHAT.md @@ -0,0 +1,205 @@ +# tf_registry — Полная история (для нового чата) + +> **Дата**: 2026-08-06 +> **Проект**: Переписываем Go-реестр Terraform-провайдеров на Python/Flask (managed-сервис Nubes) +> **Репозиторий**: `https://gitea.services.ngcloud.ru/Nail/tf_registry.git` (master) +> **Управляемый сервис**: `registry` (instanceUid: `309fdf08-8544-407f-96bd-91c8ae70baf8`) +> **URL**: `https://registry.pythonk8s.dev.nubes.ru` + +--- + +## 1. Контекст + +### Что такое реестр +Свой реестр Terraform-провайдеров для `nubes` (кастомный провайдер NGCloud). Работает по HashiCorp Provider Registry Protocol. + +### Как было (Go) +- Go-сервер в K8s (личный кластер `iot-naeel`, ВМ `5.172.178.213`) +- Домен: `registry.kube5s.ru` +- S3: `s3.msk-1.ngcloud.ru`, бакет `terraform-registry` +- Креды S3: Secret `s3-credentials` в namespace `terra` + +### Как стало/становится (Flask) +- Managed-сервис Nubes `pythonk8s` +- Домен: `registry.pythonk8s.dev.nubes.ru` +- Тот же S3 + +--- + +## 2. Структура проекта (как сейчас в master) + +``` +tf_registry/ +├── site/ +│ └── app.py # Flask-приложение (7 роутов) +├── requirements.txt # flask, boto3 +├── secrets/ +│ └── env.txt # S3-креды + jsonEnv (в .gitignore) +├── HISTORY/ # Документация +│ ├── plan-sonnet-full.md +│ ├── 2026-08-06-plan-review.md +│ └── 2026-08-06-first-deploy.md +├── .gitignore # secrets/, __pycache__/ +├── server/ # [LEGACY] Go-код (оставлен для справки) +├── operator/ # [LEGACY] +├── k8s/ # [LEGACY] +├── charts/ # [LEGACY] +├── registrykeys/ # [LEGACY] GPG-ключ (устарел!) +└── scripts/ # [LEGACY] +``` + +### Ключевое правило Nubes для Flask +``` +repo/ +├── requirements.txt +└── site/ + └── app.py ← точка входа, `app.run(host="0.0.0.0", port=5000)` +``` +- **НЕЛЬЗЯ** `site/__init__.py` — конфликтует со stdlib +- **НЕЛЬЗЯ** factory pattern — платформа ждёт `app` на уровне модуля +- **НЕЛЬЗЯ** `from site.xxx import` — импорт без префикса + +--- + +## 3. Эндпоинты (все реализованы) + +| # | Маршрут | Что делает | +|---|---|---| +| 1 | `GET /.well-known/terraform.json` | `{"providers.v1": "/v1/providers/"}` | +| 2 | `GET /v1/providers/{ns}/{name}/versions` | Список версий + платформы из S3 | +| 3 | `GET /v1/providers/{ns}/{name}/{ver}/download/{os}/{arch}` | JSON: download_url, shasums, сигнатуры, GPG | +| 4 | `GET /v1/proxy?bucket=...&key=...` | Стриминг файла из S3 | +| 5 | `GET /docs/{ns}/{name}/{ver}/...` | Статика из S3 (кандидаты ключей) | +| 6 | `GET /healthz`, `GET /readyz` | `"ok"` 200 | +| 7 | `GET /` | HTML с версией | + +--- + +## 4. Конфигурация (jsonEnv в UI) + +```json +{ + "REGISTRY_HOSTNAME": "registry.pythonk8s.dev.nubes.ru", + "S3_ENDPOINT": "s3.msk-1.ngcloud.ru", + "S3_ACCESS_KEY": "0GLQRD38H4I6RBDB0EWJ", + "S3_SECRET_KEY": "eTFibiHmBd96IApj9PYsboTR6OBoD7osxoarHykw", + "S3_BUCKET": "terraform-registry" +} +``` + +### Параметры managed-сервиса (appConfiguration) +```json +{ + "gitPath": "https://gitea.services.ngcloud.ru/Nail/tf_registry.git", + "version": "3.12", + "healthPath": "" +} +``` + +--- + +## 5. Ключевые детали реализации + +### S3_PREFIX vs HOSTNAME +```python +HOSTNAME = os.getenv("REGISTRY_HOSTNAME", "localhost:8080") # для URL +S3_PREFIX = "registry.kube5s.ru" # для S3-ключей (старый Go-хостнейм!) +``` +S3-ключи лежат под `registry.kube5s.ru/...`, а managed-домен — `registry.pythonk8s.dev.nubes.ru`. Поэтому S3-префикс жёстко `registry.kube5s.ru`. + +### S3-клиент (boto3 + MinIO) +```python +s3 = boto3.client( + "s3", + endpoint_url=f"https://{S3_ENDPOINT}", + config=Config(signature_version="s3v4"), # важно для MinIO + use_ssl=True, +) +``` + +### Пагинация S3 +Используется `get_paginator("list_objects_v2")` — не `list_objects_v2` напрямую (макс 1000). + +### Платформы +Обнаруживаются по имени файла: `_darwin_amd64.zip`, `_linux_amd64.zip`, `_windows_amd64.zip`. + +### GPG-ключи (ДВА — из живого Go-деплоя!) +```python +GPG_PRIMARY_KEY_ID = "3EC4673EB798238A" # основной (живой деплой) +GPG_LEGACY_KEY_ID = "CB3A0DF161ECC416" # старый (из исходников) +``` +Оба возвращаются в `signing_keys.gpg_public_keys`. + +### Docs-кандидаты (1:1 с Go) +``` +/docs/{ns}/{name}/{ver}/style.css + 1) docs/{ns}/{name}/{ver}/style.css (exact) + 2) НЕ пробует style.css/index.html (есть расширение .css) + 3) docs/{ns}/{name}/{ver}/index.html (fallback) + +/docs/{ns}/{name}/{ver}/folder/ + 1) docs/{ns}/{name}/{ver}/folder/ (exact) + 2) docs/{ns}/{name}/{ver}/folder/index.html (заканчивается на /) + 3) docs/{ns}/{name}/{ver}/index.html (fallback) +``` + +### Content-Length при стриминге +`head_object` → `ContentLength` → выставляется в заголовках. + +### Порядок роутов +`/` — ПОСЛЕДНИЙ, иначе перехватит `/docs/`. + +--- + +## 6. История деплоев + +| # | Коммит | Что | Результат | +|---|---|---|---| +| 1 | `7c2b030` | Минимальный Flask (только `/`) | ❌ Init:Error — gitea приватный | +| 2 | — | Репо сделан публичным, редеплой | ✅ `tf_registry v1.0.0` | +| 3 | `3fa15cd` | Полный Flask (7 роутов) | ✅ Страница ONLINE, API — пустые versions | +| 4 | `a89b1f1` | Fix: S3_PREFIX, GPG, darwin | ⏳ Ожидает редеплоя | +| 5 | `f8f6343` | Версия на главной | ⏳ | +| 6 | `5ed2948` | HISTORY-документация | ✅ | + +--- + +## 7. Текущий статус (последний пуш: `5ed2948`) + +- app.py: написан, проверен `py_compile`, все 7 роутов ✅ +- S3_PREFIX: `registry.kube5s.ru` ✅ +- GPG: 2 ключа из живого Go ✅ +- Платформы: darwin + linux + windows ✅ +- Версия на главной: `v1.0.0` ✅ +- **НУЖЕН РЕДЕПЛОЙ** через UI → проверить `versions` и `download` + +--- + +## 8. Что дальше + +1. Редеплой через UI +2. Проверить `curl /.well-known/terraform.json` +3. Проверить `curl /v1/providers/nubes-test/nubes/versions` — должны быть версии +4. Проверить `curl /v1/providers/nubes-test/nubes/5.1.16/download/linux/amd64` — shasum не пустой +5. `terraform init` с `source = "registry.pythonk8s.dev.nubes.ru/nubes-test/nubes"` + +--- + +## 9. Как продолжить в новом чате + +1. Открыть workspace `~/tf_registry` +2. Прочитать этот файл +3. `git pull` (на всякий случай) +4. Сказать: «Продолжаем tf_registry Flask-реестр. Контекст в HISTORY/README-NEW-CHAT.md» + +--- + +## 10. Правила проекта + +- После каждого коммита → сразу push +- Перед каждым коммитом → `python3 -m py_compile site/app.py` +- `gitPath` в UI: `https://gitea.services.ngcloud.ru/Nail/tf_registry.git` +- Репо должен быть публичным (или вшить токен в gitPath) +- Кубер — только через ВМ: `ssh naeel@5.172.178.213` +- Не удалять Go-файлы — оставлены для справки +- S3_PREFIX = `registry.kube5s.ru` (НЕ managed-домен!)