Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e57aa096 | ||
|
|
25b50ce59b | ||
|
|
2a9a7311ef | ||
|
|
d841ffcbac | ||
|
|
01e0245139 | ||
|
|
efa7c5e085 | ||
|
|
c235db00de | ||
|
|
24796f4b4f |
@@ -0,0 +1,168 @@
|
|||||||
|
# tf_registry — Архитектура и рабочий процесс
|
||||||
|
|
||||||
|
## Что такое этот реестр
|
||||||
|
|
||||||
|
Собственный реестр Terraform-провайдеров по протоколу HashiCorp Provider Registry Protocol.
|
||||||
|
Позволяет публиковать и распространять кастомные Terraform-провайдеры без HashiCorp Registry.
|
||||||
|
|
||||||
|
**Текущий URL:** `https://go-registry.containerk8s.dev.nubes.ru`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Как это работает
|
||||||
|
|
||||||
|
### Загрузка провайдера (пользователь)
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
nubes = {
|
||||||
|
source = "go-registry.containerk8s.dev.nubes.ru/nubes-test/nubes"
|
||||||
|
version = "5.1.16"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Terraform сам делает:
|
||||||
|
1. `GET /.well-known/terraform.json` → узнаёт API-путь
|
||||||
|
2. `GET /v1/providers/nubes-test/nubes/versions` → список версий и платформ
|
||||||
|
3. `GET /v1/providers/.../download/linux/amd64` → JSON с URL для скачивания
|
||||||
|
4. Скачивает zip, проверяет SHA256, проверяет GPG-подпись
|
||||||
|
5. Всё — провайдер установлен
|
||||||
|
|
||||||
|
Никакой аутентификации не нужно.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## S3-структура
|
||||||
|
|
||||||
|
Все данные хранятся в S3 (`terraform-registry`). Никакой БД нет.
|
||||||
|
|
||||||
|
```
|
||||||
|
{префикс}/{namespace}/{name}/{version}/
|
||||||
|
├── terraform-provider-{name}_{ver}_{os}_{arch}.zip — бинарник провайдера
|
||||||
|
├── terraform-provider-{name}_{ver}_SHA256SUMS — контрольные суммы
|
||||||
|
└── terraform-provider-{name}_{ver}_SHA256SUMS.sig — GPG-подпись сумм
|
||||||
|
|
||||||
|
docs/{namespace}/{name}/{version}/
|
||||||
|
├── index.html — документация провайдера
|
||||||
|
└── ... — любые статические файлы
|
||||||
|
```
|
||||||
|
|
||||||
|
**Важно:** префикс (первая часть пути в S3) сейчас — `registry.kube5s.ru` (временный хардкод).
|
||||||
|
Планируется либо сменить на свой домен, либо убрать префикс совсем.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GPG-подпись
|
||||||
|
|
||||||
|
### Зачем
|
||||||
|
Terraform требует, чтобы SHA256SUMS были подписаны GPG. Это гарантирует, что провайдер не подменён.
|
||||||
|
|
||||||
|
### Как работает
|
||||||
|
1. **Приватный ключ** — хранится у того, кто заливает провайдер (`secrets/private_key.asc`)
|
||||||
|
2. **Публичный ключ** — вшит в код реестра (`gpg_key.go` → `/v1/providers/.../download` отдаёт его)
|
||||||
|
3. Terraform при `init` сверяет подпись SHA256SUMS с публичным ключом
|
||||||
|
|
||||||
|
### Текущие ключи
|
||||||
|
| Key ID | Роль |
|
||||||
|
|---|---|
|
||||||
|
| `3EC4673EB798238A` | Основной (текущий) |
|
||||||
|
| `CB3A0DF161ECC416` | Legacy (старый) |
|
||||||
|
|
||||||
|
Оба отдаются в `signing_keys.gpg_public_keys` — Terraform пробует каждый.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Как залить новый провайдер
|
||||||
|
|
||||||
|
### Скрипт `build-provider.sh`
|
||||||
|
|
||||||
|
Находится в `server/build-provider.sh`. Делает:
|
||||||
|
1. Компилирует Go-провайдер под linux/windows/darwin × amd64
|
||||||
|
2. Упаковывает в zip
|
||||||
|
3. Генерирует SHA256SUMS
|
||||||
|
4. Импортирует приватный GPG-ключ из `secrets/private_key.asc`
|
||||||
|
5. Подписывает SHA256SUMS
|
||||||
|
6. Заливает zip + SHA256SUMS + .sig в S3
|
||||||
|
|
||||||
|
### Требования
|
||||||
|
```bash
|
||||||
|
# Переменные окружения
|
||||||
|
S3_ENDPOINT=s3.msk-1.ngcloud.ru
|
||||||
|
S3_ACCESS_KEY=...
|
||||||
|
S3_SECRET_KEY=...
|
||||||
|
S3_BUCKET=terraform-registry
|
||||||
|
|
||||||
|
# GPG
|
||||||
|
secrets/private_key.asc # приватный ключ для подписи
|
||||||
|
|
||||||
|
# Исходники провайдера
|
||||||
|
universal_rebuild/ # директория с Go-кодом провайдера
|
||||||
|
```
|
||||||
|
|
||||||
|
### Запуск
|
||||||
|
```bash
|
||||||
|
VERSION=5.1.17 ./server/build-provider.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Документация
|
||||||
|
|
||||||
|
Эндпоинт `/docs/{ns}/{name}/{ver}/...` отдаёт статику из S3:
|
||||||
|
```
|
||||||
|
docs/{ns}/{name}/{ver}/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Работает как статический веб-сервер: HTML, CSS, JS, изображения — всё, что положишь в `docs/` в S3.
|
||||||
|
Логика поиска (1:1 с Go-кодом):
|
||||||
|
1. Точный путь (`docs/ns/name/ver/style.css`)
|
||||||
|
2. Если нет расширения — `{путь}/index.html`
|
||||||
|
3. Fallback — `docs/ns/name/ver/index.html`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Эндпоинты
|
||||||
|
|
||||||
|
| Метод | URL | Ответ |
|
||||||
|
|---|---|---|
|
||||||
|
| GET | `/` | HTML с версией |
|
||||||
|
| GET | `/.well-known/terraform.json` | `{"providers.v1":"/v1/providers/"}` |
|
||||||
|
| GET | `/v1/providers/{ns}/{name}/versions` | JSON: id, versions[], warnings |
|
||||||
|
| GET | `/v1/providers/{ns}/{name}/{ver}/download/{os}/{arch}` | JSON: download_url, shasum, GPG ключи |
|
||||||
|
| GET | `/v1/proxy?bucket=...&key=...` | Стриминг файла из S3 |
|
||||||
|
| GET | `/docs/{ns}/{name}/{ver}/...` | Статика из S3 |
|
||||||
|
| GET | `/healthz`, `/readyz` | `"ok"` 200 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Сборка образа
|
||||||
|
docker build -t gitea.services.ngcloud.ru/nail/tf_registry:latest .
|
||||||
|
|
||||||
|
# Пуш в Gitea Docker Registry
|
||||||
|
docker push gitea.services.ngcloud.ru/nail/tf_registry:latest
|
||||||
|
|
||||||
|
# Редеплой — через UI modify (меняет только CPU/memory/replicas, подхватывает :latest)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Платформы
|
||||||
|
|
||||||
|
Детектятся по имени zip-файла:
|
||||||
|
- `_darwin_amd64.zip` → macOS Intel
|
||||||
|
- `_linux_amd64.zip` → Linux
|
||||||
|
- `_windows_amd64.zip` → Windows
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Текущие проблемы
|
||||||
|
|
||||||
|
1. **S3_PREFIX** — хардкод `registry.kube5s.ru` (TODO в коде)
|
||||||
|
2. **modify** — нельзя менять `jsonEnv` в UI (надо просить devops)
|
||||||
|
3. **Домен** — `go-registry` вместо `registry` (можно пересоздать)
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
# tf_registry — ПОЛНАЯ история (2026-08-06)
|
||||||
|
|
||||||
|
## Итог: что работает сейчас
|
||||||
|
|
||||||
|
| Сервис | Тип | Домен | Статус |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `registry` | pythonk8s | `registry.pythonk8s.dev.nubes.ru` | Flask (не обновлён, висит старая версия) |
|
||||||
|
| `go-registry` | containerk8s | `go-registry.containerk8s.dev.nubes.ru` | Go ✅ (полностью работает) |
|
||||||
|
|
||||||
|
### Что проверено на Go:
|
||||||
|
- `GET /` — HTML с версией v1.0.0 ✅
|
||||||
|
- `GET /.well-known/terraform.json` ✅
|
||||||
|
- `GET /v1/providers/nubes-test/nubes/versions` — 17 версий ✅
|
||||||
|
- `GET /v1/providers/.../download/linux/amd64` — shasum + 2 GPG ключа ✅
|
||||||
|
- Платформы: darwin, linux, windows ✅
|
||||||
|
- GPG: `3EC4673EB798238A` (основной) + `CB3A0DF161ECC416` (legacy) ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Хронология
|
||||||
|
|
||||||
|
### Этап 1: Flask (pythonk8s)
|
||||||
|
1. Создан `site/app.py` — 7 роутов, структура `site/` (требование Nubes)
|
||||||
|
2. `requirements.txt`: flask, boto3
|
||||||
|
3. Первый деплой — ошибка `Init:Error` (gitea приватный)
|
||||||
|
4. Репо сделан публичным → деплой успешен
|
||||||
|
5. API не работал: `versions: []`, `shasum: ""`
|
||||||
|
6. **Причина:** S3-ключи под `registry.kube5s.ru`, а Flask ищет под `registry.pythonk8s.dev.nubes.ru`
|
||||||
|
7. Добавлен `S3_PREFIX` в код Flask
|
||||||
|
8. GPG — в исходниках 1 ключ, живой деплой отдаёт 2 → заменён на 2 ключа
|
||||||
|
9. Добавлен darwin в платформы
|
||||||
|
|
||||||
|
### Этап 2: Go-контейнер (containerk8s)
|
||||||
|
1. Обнаружен тип сервиса `containerk8s` — generic HTTP контейнер
|
||||||
|
2. Создана ветка `go-container`
|
||||||
|
3. Правки Go: порт `:5000` (вместо `:8080`), `PORT` из ENV
|
||||||
|
4. GPG: 2 ключа в `gpg_key.go` (без импорта registrykeys)
|
||||||
|
5. Платформы: добавлен darwin
|
||||||
|
6. Dockerfile: multi-stage (golang:1.24-alpine → alpine:3.21)
|
||||||
|
7. Gitea Docker registry: `docker login gitea.services.ngcloud.ru -u Nail` ✅
|
||||||
|
8. Образ: `gitea.services.ngcloud.ru/nail/tf_registry:latest`
|
||||||
|
9. S3_PREFIX: хардкод `registry.kube5s.ru` (с TODO-комментарием)
|
||||||
|
10. VERSION: `const VERSION = "1.0.0"`, на главной странице
|
||||||
|
|
||||||
|
### Ошибки при деплое containerk8s
|
||||||
|
1. `docker build` — `repository name must be lowercase` → `nail/tf_registry`
|
||||||
|
2. `minio-go/v7` требует Go >= 1.25 → `GOTOOLCHAIN=auto`
|
||||||
|
3. modify не даёт менять `jsonEnv` → пришлось хардкодить `S3_PREFIX`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Проблема S3_PREFIX
|
||||||
|
|
||||||
|
**Суть:** S3-объекты хранятся с префиксом `registry.kube5s.ru/...` (старый Go-реестр).
|
||||||
|
Новый реестр имеет домен `go-registry.containerk8s.dev.nubes.ru` — не совпадает.
|
||||||
|
|
||||||
|
**Текущее решение (временное):** хардкод `s3Prefix = "registry.kube5s.ru"` в `main.go`.
|
||||||
|
```go
|
||||||
|
// ── TEMPORARY HARDCODE ──────────────────────────────────────────────────
|
||||||
|
// TODO: REMOVE after devops adds jsonEnv editing to containerk8s "modify".
|
||||||
|
// Then read from ENV: s3Prefix = os.Getenv("S3_PREFIX")
|
||||||
|
// And set in UI jsonEnv: "S3_PREFIX": "registry.kube5s.ru"
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
```
|
||||||
|
|
||||||
|
**Правильные решения (на будущее):**
|
||||||
|
|
||||||
|
Путь 1 — скопировать S3-объекты под новый домен:
|
||||||
|
```
|
||||||
|
mc cp s3/.../registry.kube5s.ru/ s3/.../go-registry.containerk8s.dev.nubes.ru/ --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
Путь 2 — убрать домен из S3-путей вообще:
|
||||||
|
```
|
||||||
|
Вместо: {hostname}/{ns}/{name}/{ver}/...
|
||||||
|
Сделать: {ns}/{name}/{ver}/...
|
||||||
|
```
|
||||||
|
|
||||||
|
После любого из путей — `s3Prefix = hostname`, хардкод не нужен.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Структура репозитория
|
||||||
|
|
||||||
|
### Ветка `master`
|
||||||
|
```
|
||||||
|
tf_registry/
|
||||||
|
├── site/ # Flask (НЕ ИСПОЛЬЗУЕТСЯ, мёртвый код)
|
||||||
|
│ └── app.py
|
||||||
|
├── requirements.txt # Для Flask (НЕ ИСПОЛЬЗУЕТСЯ)
|
||||||
|
├── server/ # Go-код (LEGACY, без правок)
|
||||||
|
├── operator/ # Go operator (LEGACY)
|
||||||
|
├── k8s/ # Манифесты (LEGACY)
|
||||||
|
├── charts/ # Helm (LEGACY)
|
||||||
|
├── registrykeys/ # Старый GPG (LEGACY)
|
||||||
|
├── secrets/
|
||||||
|
│ ├── env.txt # S3-креды + jsonEnv (в .gitignore)
|
||||||
|
│ └── llm.key # Токены (Gitea, LLM)
|
||||||
|
├── HISTORY/ # Документация
|
||||||
|
│ ├── README-NEW-CHAT.md
|
||||||
|
│ ├── plan-sonnet-full.md
|
||||||
|
│ ├── 2026-08-06-plan-review.md
|
||||||
|
│ └── 2026-08-06-first-deploy.md
|
||||||
|
├── Dockerfile # Для Go-контейнера
|
||||||
|
└── .gitignore # secrets/, __pycache__/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ветка `go-container` (АКТУАЛЬНАЯ)
|
||||||
|
```
|
||||||
|
server/
|
||||||
|
├── main.go # Порт 5000, S3_PREFIX hardcode, VERSION, darwin
|
||||||
|
├── gpg_key.go # 2 GPG ключа (primary + legacy)
|
||||||
|
├── docs.go # Без изменений
|
||||||
|
└── gpg/ # Без изменений
|
||||||
|
Dockerfile # golang:1.24-alpine → alpine:3.21
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
### Сборка и пуш образа
|
||||||
|
```bash
|
||||||
|
docker build -t gitea.services.ngcloud.ru/nail/tf_registry:latest .
|
||||||
|
docker push gitea.services.ngcloud.ru/nail/tf_registry:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Деплой
|
||||||
|
- Тип: `containerk8s` (Простой HTTP контейнер)
|
||||||
|
- `registryPath`: `gitea.services.ngcloud.ru/nail/tf_registry:latest`
|
||||||
|
- `resourceRealm`: `iot-naeel`
|
||||||
|
- `jsonEnv`: в UI, креды в `secrets/env.txt`
|
||||||
|
|
||||||
|
### Что можно менять в modify
|
||||||
|
- ТОЛЬКО: CPU, Memory, количество узлов
|
||||||
|
- jsonEnv и registryPath — НЕЛЬЗЯ (надо просить devops добавить)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Что дальше
|
||||||
|
|
||||||
|
1. **Devops** — добавить редактирование `jsonEnv` в modify для containerk8s
|
||||||
|
2. **S3** — решить что делать с префиксом (копировать или убрать домен)
|
||||||
|
3. **Убрать хардкод** — `s3Prefix` из ENV `S3_PREFIX`
|
||||||
|
4. **Домен** — пересоздать с именем `registry` (вместо `go-registry`)
|
||||||
|
5. **Удалить Flask** — `site/app.py`, `requirements.txt` из master (мёртвый код)
|
||||||
|
6. **Удалить старые Go-файлы** — `operator/`, `k8s/`, `charts/`, `registrykeys/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Креды и доступы
|
||||||
|
|
||||||
|
| Что | Где |
|
||||||
|
|---|---|
|
||||||
|
| S3 креды | `secrets/env.txt`, K8s Secret `s3-credentials` |
|
||||||
|
| Gitea токен | `secrets/llm.key` (строка `gitea`) |
|
||||||
|
| Docker login | `gitea.services.ngcloud.ru`, user `Nail`, токен `1999993c...` |
|
||||||
|
| ВМ | `ssh naeel@5.172.178.213` |
|
||||||
|
| Кубер | только через ВМ |
|
||||||
|
| Go-реестр (старый) | `https://registry.kube5s.ru` |
|
||||||
|
| Flask-реестр | `https://registry.pythonk8s.dev.nubes.ru` |
|
||||||
|
| Go-реестр (новый) | `https://go-registry.containerk8s.dev.nubes.ru` |
|
||||||
|
| Gitea репо | `https://gitea.services.ngcloud.ru/Nail/tf_registry.git` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
- После каждого коммита → сразу push
|
||||||
|
- Перед деплоем → `docker build && docker push`
|
||||||
|
- `containerk8s` берёт образ из `registryPath`, НЕ клонирует git
|
||||||
|
- Gitea Docker registry требует lowercase-имён: `nail/tf_registry`, не `Nail/...`
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
# Инструкция: как опубликовать провайдер в реестре
|
||||||
|
|
||||||
|
Реестр: `https://go-registry.containerk8s.dev.nubes.ru`
|
||||||
|
|
||||||
|
## 1. Структура S3
|
||||||
|
|
||||||
|
```
|
||||||
|
{prefix}/{namespace}/{name}/{version}/
|
||||||
|
├── terraform-provider-{name}_{version}_{os}_{arch}.zip ← бинарник
|
||||||
|
├── terraform-provider-{name}_{version}_SHA256SUMS ← контрольные суммы
|
||||||
|
└── terraform-provider-{name}_{version}_SHA256SUMS.sig ← GPG-подпись
|
||||||
|
```
|
||||||
|
|
||||||
|
Где:
|
||||||
|
- `{prefix}` — сейчас `registry.kube5s.ru` (будет сменён)
|
||||||
|
- `{namespace}` — `nubes-test`, `nubes-dev`, `nubes` (PROD)
|
||||||
|
- `{name}` — `nubes`
|
||||||
|
- `{os}_{arch}` — `linux_amd64`, `windows_amd64`, `darwin_amd64`
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
```
|
||||||
|
registry.kube5s.ru/nubes-test/nubes/5.1.17/terraform-provider-nubes_5.1.17_linux_amd64.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Как загрузить в S3
|
||||||
|
|
||||||
|
### Нужны креды
|
||||||
|
```
|
||||||
|
S3_ENDPOINT=s3.msk-1.ngcloud.ru
|
||||||
|
S3_ACCESS_KEY=...
|
||||||
|
S3_SECRET_KEY=...
|
||||||
|
S3_BUCKET=terraform-registry
|
||||||
|
```
|
||||||
|
|
||||||
|
### Утилита `mc` (MinIO Client)
|
||||||
|
```bash
|
||||||
|
mc alias set nubes-s3 https://s3.msk-1.ngcloud.ru $S3_ACCESS_KEY $S3_SECRET_KEY
|
||||||
|
|
||||||
|
# Загрузка
|
||||||
|
mc cp ./terraform-provider-nubes_5.1.17_linux_amd64.zip \
|
||||||
|
nubes-s3/terraform-registry/registry.kube5s.ru/nubes-test/nubes/5.1.17/
|
||||||
|
mc cp ./SHA256SUMS nubes-s3/terraform-registry/registry.kube5s.ru/nubes-test/nubes/5.1.17/
|
||||||
|
mc cp ./SHA256SUMS.sig nubes-s3/terraform-registry/registry.kube5s.ru/nubes-test/nubes/5.1.17/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Или `awscli`
|
||||||
|
```bash
|
||||||
|
aws s3 cp ... s3://terraform-registry/registry.kube5s.ru/nubes-test/nubes/5.1.17/ \
|
||||||
|
--endpoint-url https://s3.msk-1.ngcloud.ru
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. GPG-подпись (обязательно)
|
||||||
|
|
||||||
|
Terraform требует подпись SHA256SUMS.
|
||||||
|
|
||||||
|
### Приватный ключ
|
||||||
|
Хранится в `secrets/private_key.asc`. Публичный ключ (KEY ID: `3EC4673EB798238A`) вшит в реестр.
|
||||||
|
|
||||||
|
### Подписать
|
||||||
|
```bash
|
||||||
|
gpg --import secrets/private_key.asc
|
||||||
|
gpg --detach-sign --armor SHA256SUMS
|
||||||
|
# → SHA256SUMS.asc (переименовать в SHA256SUMS.sig)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Документация
|
||||||
|
|
||||||
|
```
|
||||||
|
docs/{namespace}/{name}/{version}/index.html
|
||||||
|
docs/{namespace}/{name}/{version}/...любые файлы...
|
||||||
|
```
|
||||||
|
|
||||||
|
Заливаешь в S3 — автоматом доступна по:
|
||||||
|
```
|
||||||
|
https://go-registry.containerk8s.dev.nubes.ru/docs/{ns}/{name}/{ver}/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Использование пользователем
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
nubes = {
|
||||||
|
source = "go-registry.containerk8s.dev.nubes.ru/nubes-test/nubes"
|
||||||
|
version = "5.1.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Terraform сам найдёт реестр, скачает провайдер, проверит SHA256 и GPG-подпись.
|
||||||
|
|
||||||
|
## 6. Скрипт автоматизации
|
||||||
|
|
||||||
|
В репозитории `tf_registry` есть скрипт `server/build-provider.sh` — он делает всё сам:
|
||||||
|
- Компилирует провайдер под linux/windows/darwin × amd64
|
||||||
|
- Упаковывает в zip
|
||||||
|
- Генерирует SHA256SUMS
|
||||||
|
- Подписывает GPG
|
||||||
|
- Заливает в S3
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VERSION=5.1.17 NAMESPACE=nubes-test ./server/build-provider.sh
|
||||||
|
```
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# Как залить провайдер в реестр
|
||||||
|
|
||||||
|
## Конфигурация
|
||||||
|
|
||||||
|
### Реестр
|
||||||
|
- URL: `https://registry.containerk8s.dev.nubes.ru`
|
||||||
|
- S3: Ceph `http://ceph.tst.nubes.ru`
|
||||||
|
- Бакет: `terraform-registry`
|
||||||
|
- S3-префикс: `registry.containerk8s.dev.nubes.ru`
|
||||||
|
|
||||||
|
### Креды
|
||||||
|
|
||||||
|
| Subuser | Назначение | Права |
|
||||||
|
|---|---|---|
|
||||||
|
| `3709:reader` | Реестр (только читает) | read + list |
|
||||||
|
| `3709:super` | Заливка провайдеров | write |
|
||||||
|
|
||||||
|
```
|
||||||
|
Reader: AAYTNYSZIM08DDWV3TK1 / xQVd9CeGXACPIXTBTH4KV6DIHEAyySOFSTrS17Lc
|
||||||
|
Super: 63A90SRCBP51XQ5TX8OB / euEJDZkueh0JHGP1B5jlAnAKriB8kYBR0t466GQ9
|
||||||
|
```
|
||||||
|
|
||||||
|
## Структура S3
|
||||||
|
|
||||||
|
```
|
||||||
|
terraform-registry/
|
||||||
|
└── registry.containerk8s.dev.nubes.ru/
|
||||||
|
└── {namespace}/
|
||||||
|
└── {provider}/
|
||||||
|
└── {version}/
|
||||||
|
├── terraform-provider-{name}_{ver}_linux_amd64.zip
|
||||||
|
├── terraform-provider-{name}_{ver}_windows_amd64.zip
|
||||||
|
├── terraform-provider-{name}_{ver}_darwin_amd64.zip
|
||||||
|
├── terraform-provider-{name}_{ver}_SHA256SUMS
|
||||||
|
└── terraform-provider-{name}_{ver}_SHA256SUMS.sig
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заливка (build-provider.sh)
|
||||||
|
|
||||||
|
### ⚠️ Важно: S3_ENDPOINT с http://
|
||||||
|
Ceph тестовый — HTTP, не HTTPS. Если задать `S3_ENDPOINT=ceph.tst.nubes.ru`, скрипт добавит `https://` → упадёт.
|
||||||
|
**Всегда:** `S3_ENDPOINT=http://ceph.tst.nubes.ru` (с префиксом `http://`).
|
||||||
|
|
||||||
|
### Команды
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Настроить mc (один раз, креды SUPER)
|
||||||
|
mc alias set ceph http://ceph.tst.nubes.ru \
|
||||||
|
63A90SRCBP51XQ5TX8OB \
|
||||||
|
euEJDZkueh0JHGP1B5jlAnAKriB8kYBR0t466GQ9
|
||||||
|
|
||||||
|
# 2. Создать бакет (если ещё нет)
|
||||||
|
mc mb ceph/terraform-registry
|
||||||
|
|
||||||
|
# 3. Переменные для сборки
|
||||||
|
export ROOT_DIR=~/tf_provider
|
||||||
|
export PROVIDER_DIR=~/tf_provider/provider
|
||||||
|
export REGISTRY_HOSTNAME=registry.containerk8s.dev.nubes.ru
|
||||||
|
export NAMESPACE=nubes-test # nubes-test | nubes-dev | nubes
|
||||||
|
export PROVIDER_NAME=nubes
|
||||||
|
export S3_ENDPOINT=http://ceph.tst.nubes.ru # ← http:// обязательно!
|
||||||
|
export S3_ACCESS_KEY=63A90SRCBP51XQ5TX8OB # super
|
||||||
|
export S3_SECRET_KEY=euEJDZkueh0JHGP1B5jlAnAKriB8kYBR0t466GQ9 # super
|
||||||
|
export S3_BUCKET=terraform-registry
|
||||||
|
|
||||||
|
# 4. Запуск
|
||||||
|
cd ~/tf_provider
|
||||||
|
bash ~/tf_registry/server/build-provider.sh 5.1.17
|
||||||
|
```
|
||||||
|
|
||||||
|
### Что делает скрипт
|
||||||
|
1. Компилирует Go → linux/windows/darwin × amd64
|
||||||
|
2. Упаковывает в zip
|
||||||
|
3. Генерирует SHA256SUMS
|
||||||
|
4. Подписывает GPG (ключ `secrets/private_key.asc`)
|
||||||
|
5. Заливает в S3
|
||||||
|
|
||||||
|
### Требования
|
||||||
|
- `~/tf_provider/secrets/private_key.asc` — приватный GPG-ключ
|
||||||
|
- `~/tf_provider/provider/` — исходники Go-провайдера
|
||||||
|
- `mc` (MinIO Client) установлен
|
||||||
|
- `go` установлен
|
||||||
|
|
||||||
|
## Проверка после заливки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# API
|
||||||
|
curl https://registry.containerk8s.dev.nubes.ru/v1/providers/nubes-test/nubes/versions
|
||||||
|
|
||||||
|
# Полный тест
|
||||||
|
bash ~/tf_registry/tests/smoke.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Namespace'ы
|
||||||
|
|
||||||
|
| Namespace | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `nubes-test` | Тестовый стенд |
|
||||||
|
| `nubes-dev` | Dev-стенд |
|
||||||
|
| `nubes` | Прод |
|
||||||
|
|
||||||
|
Terraform-конфиг пользователя:
|
||||||
|
```hcl
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
nubes = {
|
||||||
|
source = "registry.containerk8s.dev.nubes.ru/nubes-test/nubes"
|
||||||
|
version = "5.1.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Уроки из диалога с чатом сборки
|
||||||
|
|
||||||
|
1. **S3_ENDPOINT** — всегда с протоколом (`http://` или `https://`). Без протокола скрипт форсит `https://`.
|
||||||
|
2. **Бакет** — может не существовать на новом Ceph. Создать через `mc mb`.
|
||||||
|
3. **Префикс** — должен совпадать с `REGISTRY_HOSTNAME`. Если домен поменялся — обновить и в скрипте, и в Dockerfile реестра.
|
||||||
|
4. **Креды** — для заливки нужны super (write), для реестра — reader (read+list).
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Ceph S3 — конфигурация для реестра
|
||||||
|
|
||||||
|
## Инстанс S3
|
||||||
|
|
||||||
|
| Поле | Значение |
|
||||||
|
|---|---|
|
||||||
|
| userName | `naeels3` |
|
||||||
|
| instanceUid | `332cdb0d-34bf-43bf-864d-4adcc3b556fb` |
|
||||||
|
| urlConnect | `http://ceph.tst.nubes.ru/` |
|
||||||
|
| resourceRealm | `ceph.tst.nubes.ru` |
|
||||||
|
|
||||||
|
## Пользователи (users)
|
||||||
|
|
||||||
|
| user_id | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `3709` | Основной владелец |
|
||||||
|
| `3709:super` | Subuser с повышенными правами |
|
||||||
|
| `3709:technicalS3Backup` | Subuser для бэкапов |
|
||||||
|
| `3709:reader` | **(планируется)** Subuser для реестра — только read+list |
|
||||||
|
|
||||||
|
## Subuser `3709:reader` для реестра
|
||||||
|
|
||||||
|
### Права
|
||||||
|
- `read` — чтение объектов
|
||||||
|
- `list` — список объектов (нужно для `listVersions`)
|
||||||
|
- **Без** `write` и `delete` — реестр не может менять данные
|
||||||
|
|
||||||
|
### Креды (после создания)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"S3_ACCESS_KEY": "...",
|
||||||
|
"S3_SECRET_KEY": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Вставить в `jsonEnv` инстанса реестра.
|
||||||
|
|
||||||
|
### Конфигурация реестра под Ceph
|
||||||
|
|
||||||
|
Dockerfile ENV:
|
||||||
|
```dockerfile
|
||||||
|
ENV S3_ENDPOINT=ceph.tst.nubes.ru \
|
||||||
|
S3_BUCKET=terraform-registry \
|
||||||
|
S3_PREFIX=go-registry.containerk8s.dev.nubes.ru \
|
||||||
|
REGISTRY_HOSTNAME=go-registry.containerk8s.dev.nubes.ru \
|
||||||
|
PORT=5000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Различия с текущим S3 (MinIO)
|
||||||
|
|
||||||
|
| | Старый (MinIO) | Новый (Ceph) |
|
||||||
|
|---|---|---|
|
||||||
|
| ENDPOINT | `s3.msk-1.ngcloud.ru` | `ceph.tst.nubes.ru` |
|
||||||
|
| Креды | Статические | Subuser `3709:reader` |
|
||||||
|
| Протокол | HTTPS | HTTP (судя по `urlConnect`) |
|
||||||
|
| Безопасность | Приватный MinIO | Ceph с разделением прав |
|
||||||
|
|
||||||
|
### ⚠️ Если HTTP
|
||||||
|
В Go-коде сейчас `Secure: true` — для HTTP надо поменять на `Secure: false`.
|
||||||
|
Лучше через ENV: `S3_USE_SSL=true/false` (сейчас захардкожено).
|
||||||
@@ -8,10 +8,10 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- terr.kube5s.ru
|
- registry.containerk8s.dev.nubes.ru
|
||||||
secretName: terr-kube5s-ru-tls
|
secretName: registry-containerk8s-tls
|
||||||
rules:
|
rules:
|
||||||
- host: terr.kube5s.ru
|
- host: registry.containerk8s.dev.nubes.ru
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -13,7 +13,7 @@ from botocore.config import Config
|
|||||||
# Config (from ENV, matching Go defaults)
|
# Config (from ENV, matching Go defaults)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
HOSTNAME = os.getenv("REGISTRY_HOSTNAME", "localhost:8080")
|
HOSTNAME = os.getenv("REGISTRY_HOSTNAME", "localhost:8080")
|
||||||
S3_PREFIX = "registry.kube5s.ru" # S3 keys stored under old Go hostname
|
S3_PREFIX = os.getenv("S3_PREFIX", "registry.containerk8s.dev.nubes.ru")
|
||||||
S3_ENDPOINT = os.getenv("S3_ENDPOINT", "")
|
S3_ENDPOINT = os.getenv("S3_ENDPOINT", "")
|
||||||
S3_ACCESS_KEY = os.getenv("S3_ACCESS_KEY", "")
|
S3_ACCESS_KEY = os.getenv("S3_ACCESS_KEY", "")
|
||||||
S3_SECRET_KEY = os.getenv("S3_SECRET_KEY", "")
|
S3_SECRET_KEY = os.getenv("S3_SECRET_KEY", "")
|
||||||
|
|||||||
Executable
+87
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Smoke tests for Terraform Registry
|
||||||
|
# Usage: bash tests/smoke.sh [DOMAIN]
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DOMAIN="${1:-https://registry.containerk8s.dev.nubes.ru}"
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local name="$1"
|
||||||
|
if eval "$2" &>/dev/null; then
|
||||||
|
echo "✅ $name"
|
||||||
|
((PASS++))
|
||||||
|
else
|
||||||
|
echo "❌ $name"
|
||||||
|
((FAIL++))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=== Registry Smoke Tests: $DOMAIN ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# 1. Root page
|
||||||
|
check "GET /" \
|
||||||
|
"curl -s --max-time 5 '$DOMAIN/' | grep -q ONLINE"
|
||||||
|
|
||||||
|
# 2. Healthz
|
||||||
|
check "GET /healthz → ok" \
|
||||||
|
"test 'ok' = \"\$(curl -s --max-time 5 '$DOMAIN/healthz')\""
|
||||||
|
|
||||||
|
# 3. Readyz
|
||||||
|
check "GET /readyz → ok" \
|
||||||
|
"test 'ok' = \"\$(curl -s --max-time 5 '$DOMAIN/readyz')\""
|
||||||
|
|
||||||
|
# 4. Discovery
|
||||||
|
check "GET /.well-known/terraform.json" \
|
||||||
|
"curl -s --max-time 5 '$DOMAIN/.well-known/terraform.json' | grep -q '/v1/providers/'"
|
||||||
|
|
||||||
|
# 5. Versions
|
||||||
|
check "GET /v1/providers/nubes-test/nubes/versions" \
|
||||||
|
"curl -s --max-time 10 '$DOMAIN/v1/providers/nubes-test/nubes/versions' | \
|
||||||
|
python3 -c \"
|
||||||
|
import sys,json
|
||||||
|
d=json.load(sys.stdin)
|
||||||
|
vs=[v['version'] for v in d['versions']]
|
||||||
|
assert d['id']=='nubes-test/nubes'
|
||||||
|
assert len(vs)>=1
|
||||||
|
assert vs==sorted(vs), 'not sorted'
|
||||||
|
for v in d['versions']:
|
||||||
|
p=[x['os'] for x in v['platforms']]
|
||||||
|
assert 'linux' in p and 'darwin' in p and 'windows' in p
|
||||||
|
print('OK')
|
||||||
|
\""
|
||||||
|
|
||||||
|
# 6. Download metadata
|
||||||
|
check "GET /v1/providers/.../5.1.17/download/linux/amd64" \
|
||||||
|
"curl -s --max-time 10 '$DOMAIN/v1/providers/nubes-test/nubes/5.1.17/download/linux/amd64' | \
|
||||||
|
python3 -c \"
|
||||||
|
import sys,json
|
||||||
|
d=json.load(sys.stdin)
|
||||||
|
assert d['os']=='linux' and d['arch']=='amd64'
|
||||||
|
assert len(d['shasum'])==64
|
||||||
|
assert 'download_url' in d
|
||||||
|
keys=d['signing_keys']['gpg_public_keys']
|
||||||
|
assert len(keys)==2
|
||||||
|
assert keys[0]['key_id']=='3EC4673EB798238A'
|
||||||
|
assert keys[1]['key_id']=='CB3A0DF161ECC416'
|
||||||
|
print('OK')
|
||||||
|
\""
|
||||||
|
|
||||||
|
# 7. Proxy download
|
||||||
|
check "GET /v1/proxy — download zip" \
|
||||||
|
"url=\$(curl -s --max-time 5 '$DOMAIN/v1/providers/nubes-test/nubes/5.1.17/download/linux/amd64' | python3 -c \"import sys,json; print(json.load(sys.stdin)['download_url'])\") && \
|
||||||
|
test '200' = \"\$(curl -s --max-time 15 -o /dev/null -w '%{http_code}' \"\$url\")\""
|
||||||
|
|
||||||
|
# 8. 404 for unknown provider
|
||||||
|
check "GET unknown → 404" \
|
||||||
|
"test '404' = \"\$(curl -s --max-time 5 -o /dev/null -w '%{http_code}' '$DOMAIN/v1/providers/nosuch/noversion/versions')\""
|
||||||
|
|
||||||
|
# 9. Missing key param → 400
|
||||||
|
check "GET /v1/proxy без key → 400" \
|
||||||
|
"test '400' = \"\$(curl -s --max-time 5 -o /dev/null -w '%{http_code}' '$DOMAIN/v1/proxy')\""
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== $PASS PASS, $FAIL FAIL ==="
|
||||||
|
exit $FAIL
|
||||||
Reference in New Issue
Block a user