Files
tf_provider/docs/howitwasdone.md
T

269 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- ⛔⛔⛔ LEGACY: deck-api.ngcloud.ru ЗАКРЫВАЕТСЯ! Все примеры ниже — ИСТОРИЧЕСКИЕ. -->
<!-- Актуальный API: https://lk-api-gateway.ngcloud.ru/api/v1/svc -->
# How It Was Done — Developer Guide (закрытая страница)
**Filename & Versioning:** howitwasdone.md / 20260204 / Draft v1
Этот документ — единый технический мануал. Он доступен только по прямой ссылке и не включён в публичную навигацию.
## Оглавление
1. Архитектура и методы (CRUD)
2. База знаний ошибок
3. Глоссарий (со ссылками на места употребления)
4. Билд и публикация провайдера и документации
---
## 1. Архитектура и методы (CRUD)
### 1.1 Архитектура универсального rebuild
- Ядро: universal_rebuild/internal/core (универсальный клиент API и общий flow операций).
- Провайдер: universal_rebuild/internal/provider (schema, конфигурация, подключение ресурсов).
- YAML-спеки: universal_rebuild/resources_yaml (источник истины).
- Генератор: universal_rebuild/tools/gen (генерация Go-ресурсов и registry).
Ключевое правило: новая логика — только новые функции/файлы. Существующий Go‑код не менять без согласования.
<a id="discovery"></a>
### 1.2 Источник параметров (discovery)
Параметры извлекаются через proxy endpoint API:
- /index.cfm?endpoint=/services/{svcId}
- /index.cfm?endpoint=/serviceOperation/{svcOperationId}
- (опц.) /index.cfm?endpoint=/param-value-list/{svcOperationCfsParamId}
Схема: сервис → операции → CFS параметры → YAML → генерация Go.
<a id="create-universal"></a>
### 1.3 Create (универсальный 7‑шаговый паттерн)
1) POST /instances → instanceUid
2) POST /instanceOperations (create) → instanceOperationUid
3) GET /instanceOperations/{uid}?fields=cfsParams
4) POST /instanceOperationCfsParams для каждого параметра
5) GET /instanceOperations/{uid}/validate-cfs
6) POST /instanceOperations/{uid}/run с payload {}
7) Polling до завершения операции
Критично: параметры отправляются все, включая дефолты.
<a id="read-adopt"></a>
### 1.4 Read / Adopt
- При isDeleted или explainedStatus=deleted — state очищается.
- При совпадении display_name и resume_if_exists=true — adopt/resume.
- Предупреждения показываются только на create и не мешают managed ресурсам.
<a id="update-modify"></a>
### 1.5 Update / Modify
- IDs параметров на modify отличаются от create.
- Нельзя хардкодить ID: нужно получать manifest операции и строить маппинг.
- Если modify отсутствует в availableOperations — выдаётся ясная ошибка.
<a id="polling-rules"></a>
### 1.6 Polling (железные правила)
- Завершение операции определяется только по dtFinish.
- После dtFinish результат определяется isSuccessful.
- Для VM применяется двойной контроль: статус операции + статус инстанса (ERROR/STOPPED).
### 1.7 Нормализация типов
- map/json → "{}"
- list/array → "[]"
- Пустые строки в JSON‑параметрах запрещены (валидаторы на plan).
<a id="soft-delete"></a>
### 1.8 Soft Delete
- Для тяжёлых ресурсов delete заменяется на suspend (карантин/retention).
- Повторный apply при suspend может выполнять resume.
---
## 2. База знаний ошибок
### A. Аутентификация и токены
**Токены лежат в `secrets/{dev,test,prod}.token`. Срок действия — до декабря 2026.**
Проверить дату JWT:
```bash
python3 -c "import json,base64; t=open('secrets/test.token').read().split('.'); d=json.loads(base64.urlsafe_b64decode(t[1]+'==')); from datetime import datetime,timezone; print(datetime.fromtimestamp(d['exp'],tz=timezone.utc))"
```
**Симптом:** 403 Forbidden (НЕ 401!)
**Причина (старый API index.cfm):** DDoS-Guard блокирует — нет Referer или нет User-Agent.
**Решение для curl (старый API):**
```bash
curl -s --max-time 10 \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36" \
-H "Referer: https://deck-test.ngcloud.ru/" \
"https://deck-api-test.ngcloud.ru/api/v1/index.cfm?endpoint=/services/90"
```
Referer должен совпадать со стендом (test/dev/prod). Новый Gateway (lk-api-gateway) требует только Authorization.
**Симптом:** 401 Unauthorized / Authorization header expected
**Причина:** токен истёк или не передан в окружение
**Решение:** обновить access_token и сохранить в файле HH‑MM‑SS.token; убедиться, что Terraform читает токен
### B. Поллинг зависает
**Симптом:** apply «висит», операция не завершается
**Причина:** ожидание по статусу инстанса/операции без dtFinish
**Решение:** критерий завершения — dtFinish; далее isSuccessful
### C. Modify: Invalid CFS parameter (400)
**Причина:** отправлены create IDs для modify
**Решение:** получать manifest операции и динамически маппить IDs
### D. Modify недоступен
**Симптом:** action modify not available
**Причина:** modify нет в availableOperations
**Решение:** проверять доступные операции и выдавать явную ошибку
### E. Map/JSON/List: Invalid format
**Симптом:** 400 Invalid format map/array/json
**Причина:** пустые строки вместо {} или []
**Решение:** нормализация по типу, trim, отправка {} или []
### F. VM: зависание на FW / 500 String[]→GUID
**Симптом:** зависание на стадии FW, 500 checkParam
**Причина:** пустые/невалидные JSON‑массивы, ошибки backend
**Решение:** валидация JSON массивов, дефолт ["0.0.0.0/0"], фильтрация пустых значений; при повторении — эскалация на поддержку
### G. VM modify: checkParam instanceOperationCfsParamUid
**Симптом:** 500 Invalid call of function checkParam
**Причина:** дублирование параметров при POST/PUT
**Решение:** гибридный PUT/POST по наличию instanceOperationCfsParamUid; проверить формат эндпойнта
### H. Postgres: split() on null
**Симптом:** Cannot invoke method split() on null object
**Причина:** передан UUID конкретного S3‑бакета
**Решение:** использовать UUID сервиса S3 (svcId 12), а не бакета
### I. GPG/Registry
**Симптом:** authentication signature from unknown issuer
**Причина:** ключ подписи не совпадает с ключом в registry
**Решение:** обновить signing_keys на сервере или пересобрать/подменить бинарник
**Симптом:** openpgp invalid data
**Причина:** ASCIIarmor для .sig
**Решение:** бинарная detached подпись без --armor
### J. Registry/S3
**Симптом:** presigned URL не работает через Ingress
**Причина:** Host заголовок ломает подпись
**Решение:** proxy‑режим download на сервере registry
### K. Документация: 404
**Причина:** неверный S3‑ключ (hostname в префиксе)
**Решение:** фиксированный префикс docs/<ns>/<name>/<version>/
### L. Версии Terraform Plugin Framework
**Симптом:** ошибки сборки при апгрейде
**Причина:** несовместимость framework и plugingo
**Решение:** использовать совместимые версии
### M. TLS handshake timeout
**Причина:** сетевые условия/VPN
**Решение:** повторить apply
---
## 3. Глоссарий (с ссылками на места употребления)
Каждый термин содержит ссылки на разделы этого же документа, где он используется.
- **instance** — экземпляр сервиса в Nubes Cloud.
- Ссылки: [Create](#create-universal)
- **instanceOperation** — асинхронная операция над instance (create/modify/delete/suspend/resume).
- Ссылки: [Create](#create-universal), [Polling](#polling-rules)
- **cfsParams** — список параметров операции, получаемый через manifest операции.
- Ссылки: [Create](#create-universal), [Discovery](#discovery)
- **svcOperationCfsParamId** — ID параметра операции, различается для create и modify.
- Ссылки: [Update / Modify](#update-modify)
- **dtFinish** — единственный надёжный индикатор завершения операции.
- Ссылки: [Polling](#polling-rules)
- **isSuccessful** — результат операции после dtFinish.
- Ссылки: [Polling](#polling-rules)
- **resourceRealm** — окружение/realm; иногда обязателен и задаётся пользователем.
- Ссылки: [Read / Adopt](#read-adopt)
- **display_name** — человекочитаемое имя; используется для adopt/resume.
- Ссылки: [Read / Adopt](#read-adopt)
- **resume_if_exists** — включение adopt/resume по display_name.
- Ссылки: [Read / Adopt](#read-adopt)
- **delete_mode** — режим удаления (delete/suspend/state_only).
- Ссылки: [Soft Delete](#soft-delete)
- **suspend** — мягкое удаление (карантин/retention).
- Ссылки: [Soft Delete](#soft-delete)
- **validate-cfs** — проверка параметров операции до run.
- Ссылки: [Create](#create-universal)
- **state.out** — выходные данные API; при отсутствии задаются null.
- Ссылки: [Read / Adopt](#read-adopt)
- **computed** — вычисляемые поля, должны быть известны после apply.
- Ссылки: [Read / Adopt](#read-adopt)
- **registry protocol** — API Terraform Registry (discovery + versions + download).
- Ссылки: [Публикация](#publish-registry)
- **signing_keys** — публичные GPG ключи, выдаваемые registry.
- Ссылки: [Публикация](#publish-registry)
- **NLI** — Natural Language Infrastructure (AI‑парсинг инструкций).
- Ссылки: [AI‑интеграция](#ai-nli)
---
## 4. Билд и публикация провайдера и документации
### 4.1 Сборка провайдера (universal_rebuild)
Общий цикл:
1) Генерация YAML параметров сервисов.
2) Генерация Go‑ресурсов.
3) Сборка бинарника go build.
Ключевые каталоги:
- universal_rebuild/resources_yaml
- universal_rebuild/internal/resources_gen
- universal_rebuild/tools/gen
<a id="publish-registry"></a>
### 4.2 Публикация провайдера в Registry
- Артефакты: zip, SHA256SUMS, SHA256SUMS.sig
- Подпись: для .sig использовать бинарную detached подпись
- Хранилище: S3 bucket terraformregistry
- Префикс — по правилам registry‑сервера
### 4.3 Документация (MkDocs)
- Сборка: Docker образ squidfunk/mkdocs-material
- Результат: директория site/
- Публикация: scripts/publish-docs.sh
- Путь: docs/<namespace>/<name>/<version>/
### 4.4 Важные нюансы
- При смене домена обновлять registry и ключи подписи.
- Presigned URL через Ingress может ломаться — использовать proxy mode.
- Технические папки исключаются из публикации.
### 4.5 Рекомендованный порядок работ
1) Discovery параметров сервиса
2) Генерация YAML
3) Генерация Go‑ресурсов
4) Build
5) Тесты create/modify/suspend/resume
6) Документация и публикация
<a id="ai-nli"></a>
### 4.6 AI‑интеграция (NLI)
Кратко: реализована для ресурса Tubulus через ModifyPlan + askGemini, с защитой от двойного вызова AI.
### 4.7 Прямая ссылка
https://registry.kube5s.ru/docs/nubes/nubes/2.0.0/howitwasdone/