Files
tf_registry/HISTORY/README-NEW-CHAT.md
T

8.1 KiB
Raw Blame History

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)

{
  "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)

{
  "gitPath": "https://gitea.services.ngcloud.ru/Nail/tf_registry.git",
  "version": "3.12",
  "healthPath": ""
}

5. Ключевые детали реализации

S3_PREFIX vs HOSTNAME

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)

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-деплоя!)

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_objectContentLength → выставляется в заголовках.

Порядок роутов

/ — ПОСЛЕДНИЙ, иначе перехватит /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-домен!)