290 lines
20 KiB
Markdown
290 lines
20 KiB
Markdown
# Промпт для Opus 4.8: Анализ Terraform Provider для Nubes Cloud
|
||
|
||
> **Цель:** глубокий анализ архитектуры, генерационного пайплайна, API-взаимодействия и проблем проекта. Не просто описать, а найти слабые места, предложить улучшения, оценить риски.
|
||
> **Инструкция:** читай файлы по мере необходимости, не пытайся прочитать всё сразу. Ниже — карта проекта с указанием что где лежит и на что обратить внимание.
|
||
|
||
---
|
||
|
||
## 1. Общая архитектура — два провайдера в одном репозитории
|
||
|
||
| Компонент | Путь | Версия | Registry | Характер |
|
||
|-----------|------|--------|----------|----------|
|
||
| **Legacy** | `/main.go`, `internal/provider/` | 5.0.52 | `registry.terraform.io/nubes/nubes` | Ручной код, 13 ресурсов |
|
||
| **Universal Rebuild** | `universal_rebuild/main.go`, `universal_rebuild/...` | 5.0.51 | `terra.k8c.ru/nubes/nubes` | Полностью генерируемый, ~50 ресурсов |
|
||
|
||
Оба используют `terraform-plugin-framework`. Legacy — ручной, Universal — продукт генерационного конвейера. Legacy всё ещё жив, Universal — целевой.
|
||
|
||
### Ключевые файлы для понимания архитектуры:
|
||
- `/home/naeel/tf_provider/devops/ARCHITECTURE.md` — архитектурные принципы (YAML как source of truth, никаких ручных правок сгенерированного кода)
|
||
- `/home/naeel/tf_provider/docs/CODEBASE_ANALYSIS_AND_ROADMAP.md` — полный анализ кодовой базы от 13.03.2026
|
||
- `/home/naeel/tf_provider/docs/MIGRATION_PLAN_FOR_AGENT.md` — план миграции в Managed K8s
|
||
|
||
**Вопросы к Opus:**
|
||
- Насколько оправдано существование двух провайдеров? Когда и как Legacy должен быть выведен?
|
||
- Есть ли архитектурные проблемы в разделении `internal/` vs `universal_rebuild/internal/`?
|
||
|
||
---
|
||
|
||
## 2. Генерационный конвейер (CRITICAL PATH)
|
||
|
||
### Полный пайплайн:
|
||
|
||
```
|
||
API Nubes (deck-api.ngcloud.ru)
|
||
│
|
||
▼
|
||
[Шаг 1] devops/01_generate_yamls.sh
|
||
│ └─ запускает: universal_rebuild/tools/service_spec_gen/generate_service_spec.go
|
||
│ └─ читает: devops/config/services_list.txt (30+ сервисов)
|
||
│ └─ для каждого сервиса: GET /services/{id} → получает операции → GET детали каждой операции → cfsParams
|
||
│ └─ пишет: {id}_{name}.yaml в resources_yaml/
|
||
│
|
||
▼
|
||
[Шаг 2] devops/02_generate_resources_and_docs_v2.sh
|
||
│ ├─ Go-генератор: universal_rebuild/tools/gen_v2/generate_resources_v2.go
|
||
│ │ └─ читает YAML → классифицирует операции (instance/subresource/action) → генерирует .go файлы
|
||
│ │ └─ пишет: internal/resources_gen/*.go (50+ файлов) + registry.go
|
||
│ │
|
||
│ └─ Доку-генератор: universal_rebuild/tools/docs_template_gen_v2/
|
||
│ └─ читает YAML → генерирует .md документацию
|
||
│
|
||
▼
|
||
[Шаг 3] devops/03_build_and_upload_provider.sh
|
||
│ └─ сборка под linux/windows/darwin → GPG-подпись → S3
|
||
│
|
||
▼
|
||
[Шаг 4] devops/04_build_and_publish_docs.sh
|
||
└─ mkdocs build → S3
|
||
```
|
||
|
||
### Ключевые файлы генераторов:
|
||
- **service_spec_gen** (API→YAML): `/home/naeel/tf_provider/universal_rebuild/tools/service_spec_gen/generate_service_spec.go`
|
||
- **gen_v2** (YAML→Go): `/home/naeel/tf_provider/universal_rebuild/tools/gen_v2/generate_resources_v2.go`
|
||
- **services_list.txt**: `/home/naeel/tf_provider/devops/config/services_list.txt` — 30+ сервисов (dummy, s3, postgres, kafka, clickhouse, k8s, ...)
|
||
- **operation_timeouts.json**: `/home/naeel/tf_provider/devops/config/operation_timeouts.json`
|
||
|
||
### Профили (стенды):
|
||
- `/home/naeel/tf_provider/devops/profiles/test/`, `prod/`, `dev/`
|
||
- Каждый профиль содержит: `profile.env`, `services_list.txt`, `operation_timeouts.json`, `generated/`
|
||
|
||
**Вопросы к Opus:**
|
||
- Насколько надёжен конвейер? Что произойдёт если API изменит формат ответа?
|
||
- Достаточно ли валидации на каждом шаге? Нет ли риска генерации битого кода?
|
||
- Почему генераторы на Go, а не на Python (учитывая что скрипты на bash)?
|
||
- Как обрабатываются ошибки API (retry, rate limiting)? См. `service_spec_gen` — есть `ATTEMPTS=3`, `REQUEST_DELAY=0.5`
|
||
- Комментирование сервисов в `services_list.txt` — это единственный способ исключить сервис? Не приведёт ли к рассинхрону?
|
||
|
||
---
|
||
|
||
## 3. Core: UniversalClient и API-взаимодействие
|
||
|
||
### Файл: `/home/naeel/tf_provider/universal_rebuild/internal/core/client.go`
|
||
|
||
**API Flow V6 (create):**
|
||
1. `POST /instances` → получаем instanceUid
|
||
2. `POST /instanceOperations` (operation="create") → получаем instanceOperationUid
|
||
3. `GET /instanceOperations/{uid}?fields=cfsParams` → получаем параметры с дефолтами
|
||
4. `resolveRefSvcParamValues` — разрешение ref-параметров (UUID других сервисов)
|
||
5. Для каждого параметра: `POST /instanceOperationCfsParams`
|
||
6. Валидация + запуск операции
|
||
|
||
**Методы:**
|
||
- `CreateGenericInstanceUniversalV6` — полный create flow
|
||
- `FindInstanceByDisplayName` — поиск по displayName с фильтрацией deleted/дубликатов
|
||
- `GetInstanceState` / `GetInstanceStateRaw` — чтение состояния
|
||
- `RunInstanceOperationUniversal` / `RunInstanceOperationUniversalWithDefaults` — modify/suspend/resume/delete
|
||
- `RunInstanceOperationUniversalByCode` — операции по коду (для action/subresource)
|
||
|
||
### HTTP-транспорт: `/home/naeel/tf_provider/universal_rebuild/internal/provider/provider.go`
|
||
- Force HTTP/1.1 (API не поддерживает HTTP/2)
|
||
- InsecureSkipVerify опционально (для dev-стендов)
|
||
- Timeout 300s
|
||
- TLS 1.2 minimum
|
||
|
||
### Поддержка core:
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/core/instance_params.go` — маппинг параметров
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/core/instance_outputs.go` — чтение outputs
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/core/refsvc_resolve.go` — разрешение ref_svc_id
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/core/operation_timeouts.go` — таймауты операций
|
||
|
||
**Вопросы к Opus:**
|
||
- API Flow V6 — есть ли проблемы с идемпотентностью? Что при обрыве на шаге 4 или 5?
|
||
- `doRequest` внутри — есть ли retry logic? Как обрабатываются 429/503?
|
||
- Почему HTTP/1.1 принудительно? Это ограничение API или обход бага?
|
||
- 300s timeout на всём HTTP-клиенте — не мало ли для длинных операций (создание VM может идти 10+ минут)?
|
||
|
||
---
|
||
|
||
## 4. CRUD-логика и Lifecycle
|
||
|
||
### Файл: `/home/naeel/tf_provider/universal_rebuild/internal/resources_core/crud.go`
|
||
|
||
**CreateResource:**
|
||
1. `FindInstanceByDisplayName` — поиск существующего
|
||
2. Если найден → `adoptExistingInstanceOnCreate`:
|
||
- Проверка `operation_in_progress`/`operation_pending`
|
||
- Если `adopt_existing_on_create=false` → ошибка
|
||
- Статус `not_created` → ошибка
|
||
- Статус `running` → валидация ref-параметров → adopt (возврат UUID)
|
||
- Статус `suspended` → проверка required-params → resume → валидация ref → adopt
|
||
3. Если не найден → `CreateGenericInstanceUniversalV6`
|
||
|
||
**DeleteResource:**
|
||
- `suspend` → вызов suspend
|
||
- `state_only`/`detach` → только удаление из state
|
||
|
||
**UpdateResource:**
|
||
- `RunInstanceOperationUniversalWithDefaults("modify")`
|
||
|
||
### Поддерживающие файлы в `resources_core/` (все в `/home/naeel/tf_provider/universal_rebuild/internal/resources_core/`):
|
||
- `ref_validation.go` — валидация ref-параметров при adopt
|
||
- `required_params.go` + `required_params_compare.go` — проверка обязательных параметров
|
||
- `params_compare.go` — сравнение параметров для detect changes
|
||
- `params_mapping.go` + `params_ref_mapping.go` — маппинг параметров из/в API
|
||
- `params_validation_mapping.go` — маппинг для plan validation
|
||
- `state_refresh.go` — RefreshResourceState (чтение state после apply)
|
||
- `outputs.go` — FetchInstanceOutputs
|
||
- `operation_ids.go` — маппинг operation ID → имя
|
||
- `json_normalize.go` + `json_planmodifier.go` — нормализация JSON-параметров
|
||
- `uuid_planmodifier.go` — план-модификатор для UUID
|
||
- `domain_collision.go` — проверка коллизий доменов
|
||
- `resource_diagnostics.go` + `resource_diagnostics_required.go` — форматирование диагностик
|
||
- `subresource_guard.go` — защита подресурсов
|
||
- `crud_test.go` — тесты
|
||
|
||
**Вопросы к Opus:**
|
||
- `adoptExistingInstanceOnCreate` — не слишком ли сложная логика? 100+ строк, много ветвлений. Есть ли риск не покрытых кейсов?
|
||
- Что происходит при concurrent apply из двух разных Terraform-окружений?
|
||
- `state_only` destroy — не остаются ли orphaned ресурсы в облаке?
|
||
- Как определяется `suspend_on_destroy` по умолчанию? Где логика `hasSuspend → suspendOnDestroyDefault`?
|
||
|
||
---
|
||
|
||
## 5. Генерация Go-кода из YAML — КРИТИЧЕСКИ
|
||
|
||
### Файл: `/home/naeel/tf_provider/universal_rebuild/tools/gen_v2/generate_resources_v2.go`
|
||
|
||
**На входе:** YAML-спек каждого сервиса
|
||
**На выходе:** 3 типа Go-ресурсов:
|
||
- **Instance** (kind=instance) — CRUD + lifecycle (suspend/resume)
|
||
- **Subresource** (kind=subresource) — CRUD для подобъектов (users, databases, topics)
|
||
- **Action** (kind=action) — одноразовые операции (restart, redeploy, reconcile)
|
||
|
||
**Логика генератора:**
|
||
1. Парсит все YAML → `ServiceSpec` (name, service_id, outputs, lifecycle, operations)
|
||
2. Для instance: собирает create/modify params → computeCreateOnly → mergeParams → генерирует `.go`
|
||
3. Для subresource: группирует по subresource name → create/modify/delete params
|
||
4. Для action: каждый action → отдельный ресурс с trigger-полем
|
||
5. Генерирует `registry.go` — `AllResources()` со всеми New* функциями
|
||
|
||
### Пример сгенерированного файла: `/home/naeel/tf_provider/universal_rebuild/internal/resources_gen/90_postgres_resource.go`
|
||
|
||
**Вопросы к Opus:**
|
||
- Шаблоны генерятся через `text/template` — где сами шаблоны? Они вшиты в `gen_v2` как константы? Насколько они поддерживаемы?
|
||
- Что произойдёт если в YAML появится новый kind операции, не известный генератору?
|
||
- `createOnly` параметры — как определяется что параметр immutable? Из API или эвристика?
|
||
- JSON-параметры (`data_type: json`) — как обрабатываются? Есть `IsJson` + `JsonNormalize` план-модификатор. Это надёжно?
|
||
- Для subresource — как определяется identity (какие параметры идентифицируют ресурс)?
|
||
|
||
---
|
||
|
||
## 6. Известные проблемы (из 23 файлов истории)
|
||
|
||
Архив: `/home/naeel/tf_provider/docs/50_history/` (23 файла, от `00_system_mechanics.md` до `23_vapp_uid_inconsistency_displayname_resolve_bug.md`)
|
||
|
||
### Ключевые баги (прочитай эти файлы):
|
||
- **23** — `vapp_uid_inconsistency`: `FindInstanceByDisplayName` возвращает deleted инстанс (нет фильтра isDeleted)
|
||
- **22** — `adopt_ref_validation`: ref-параметры не валидировались при adopt → ссылки на deleted ресурсы
|
||
- **21** — `plan_validation_ref_svc_filter`: план показывал deleted/suspended инстансы в ref-списках
|
||
- **16** — `create_only_params`: create-only параметры не блокировались при modify
|
||
- **13** — `universal_flow_param_normalization`: нормализация параметров между API и Terraform
|
||
- **06** — `postgres_update_immutable_params`: immutable параметры при модификации
|
||
- **05** — `polling_fixes`: проблемы с поллингом длительных операций
|
||
- **04** — `vm_hang_fix_and_500_error`: 500 ошибка при модификации VM (см. также DEBUG_REPORT_VM_FIX.md)
|
||
|
||
### Другие важные документы:
|
||
- `/home/naeel/tf_provider/docs/INSTANCE_STATES.md` — полная матрица состояний инстансов
|
||
- `/home/naeel/tf_provider/docs/STATE_TRANSITIONS.md` — все переходы состояний (NOT_CREATED, CREATING, RUNNING, SUSPENDED, DELETED, ...)
|
||
- `/home/naeel/tf_provider/docs/DEBUG_REPORT_VM_FIX.md` — отчёт о попытке исправить 500 при modify VM
|
||
|
||
**Вопросы к Opus:**
|
||
- Какие баги из истории до сих пор актуальны (не исправлены)?
|
||
- Есть ли системные проблемы, которые порождают целые классы багов (например, отсутствие фильтрации deleted инстансов)?
|
||
- Насколько полна матрица состояний? Все ли переходы обрабатываются?
|
||
- 500 ошибка при modify VM — правильно ли был сделан анализ? Может быть проблема в API, а не в провайдере?
|
||
|
||
---
|
||
|
||
## 7. HAR-трассировки — источник правды об API
|
||
|
||
Файлы в `/home/naeel/tf_provider/HAR/`:
|
||
- `OK.har`, `goodmodify.har`, `baddelete.har` — реальные HTTP-трассировки
|
||
- `deck.ngcloud.ru.har`, `deck.ngcloud1.ru.har` — полные сессии
|
||
- `keycloak.nubes.ru.har`, `lucee.har`, `pguser.har` — специфичные сервисы
|
||
|
||
**Вопросы к Opus:**
|
||
- HAR-файлы — ценный источник для верификации API-контракта. Используются ли они в тестах?
|
||
- Можно ли автоматизировать проверку что провайдер соответствует реальному API на основе HAR?
|
||
|
||
---
|
||
|
||
## 8. Тестирование
|
||
|
||
### Где тесты:
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/resources_core/crud_test.go`
|
||
- `/home/naeel/tf_provider/universal_rebuild/internal/core/client_test.go`
|
||
|
||
**Вопросы к Opus:**
|
||
- Достаточно ли тестов? Какие пробелы?
|
||
- Как тестировать сгенерированные ресурсы без реального API?
|
||
- Нужны ли integration-тесты против реального API (с мок-сервером или тестовым стендом)?
|
||
|
||
---
|
||
|
||
## 9. Безопасность
|
||
|
||
- Токен аутентификации: env `NUBES_API_TOKEN`, файл `~/.nubes_token`, или в HCL (`api_token` — sensitive)
|
||
- GPG-ключ для подписи провайдера: `/home/naeel/tf_provider/secrets/private_key.asc`
|
||
- Токены: `/home/naeel/tf_provider/secrets/dev.token`, `prod.token`, `test.token`
|
||
- InsecureSkipVerify для dev-стендов
|
||
|
||
**Вопросы к Opus:**
|
||
- Есть ли риск утечки токена через логи/диагностики?
|
||
- `Sensitive: true` на api_token — достаточно ли этого?
|
||
- GPG-ключ в репозитории — это нормально? (в `.gitignore` ли он?)
|
||
|
||
---
|
||
|
||
## 10. Что нужно оценить Opus (итоговый список)
|
||
|
||
1. **Архитектура:** два провайдера → стратегия перехода на Universal
|
||
2. **Конвейер:** надёжность, валидация, обработка ошибок API
|
||
3. **Генератор кода:** поддерживаемость шаблонов, расширяемость
|
||
4. **Core/API:** retry logic, таймауты, идемпотентность, HTTP/1.1 vs HTTP/2
|
||
5. **Lifecycle:** полнота coverage состояний, краевые кейзы adopt/resume
|
||
6. **Баги:** какие системные, какие ещё не исправлены
|
||
7. **Тесты:** пробелы в покрытии
|
||
8. **Безопасность:** токены, GPG, secrets management
|
||
9. **Производительность:** поллинг, параллельные запросы, кэширование
|
||
10. **Документация:** насколько генерируемые доки соответствуют реальности
|
||
|
||
### На что обратить ОСОБОЕ внимание:
|
||
- `adoptExistingInstanceOnCreate` в `crud.go` — самая сложная функция, много ветвлений
|
||
- `FindInstanceByDisplayName` — была переписана, но всё ещё есть риск не найти/найти не тот
|
||
- Генератор `gen_v2` — если сломается, сломается ВЕСЬ провайдер
|
||
- Immutable параметры — как определяется неизменяемость? Из API или из YAML?
|
||
- Конкурентный доступ — что если два `terraform apply` одновременно?
|
||
|
||
---
|
||
|
||
## Инструкция Opus
|
||
|
||
1. Начни с чтения `devops/ARCHITECTURE.md` и `docs/CODEBASE_ANALYSIS_AND_ROADMAP.md`
|
||
2. Затем прочитай ключевые файлы конвейера: `service_spec_gen/generate_service_spec.go` и `gen_v2/generate_resources_v2.go`
|
||
3. Затем core: `client.go` и `crud.go`
|
||
4. Затем историю проблем: выборочно 2-3 последних файла из `docs/50_history/`
|
||
5. После этого — дай развёрнутый анализ по ВСЕМ 10 пунктам выше
|
||
6. В анализе на каждый пункт: текущее состояние → что хорошо → что плохо → конкретные предложения → риски
|
||
|
||
**НЕ читай все 50+ сгенерированных файлов подряд — они генерируются и не содержат уникальной логики.**
|