195 lines
12 KiB
Markdown
195 lines
12 KiB
Markdown
# Передача контекста: Terraform-провайдер Nubes
|
||
|
||
Дата: 2026-09-22 | Версия DEV: 2.0.8 | HEAD: 13beb9c (`release(dev): 2.0.8`)
|
||
|
||
Документ для старта новой сессии. Прочитать целиком перед любыми действиями.
|
||
|
||
---
|
||
|
||
## 1. Правила работы (соблюдать строго)
|
||
|
||
- **Никаких действий без прямого разрешения.** Правки, сборки, заливки, коммиты, запуск
|
||
terraform, запросы в API — только по явной команде оператора.
|
||
- **Вопрос в любой форме = только ответ.** Не выполнять действий, не предлагать «а ещё могу».
|
||
- **Коммитить после каждой правки**, разбивая по смыслу. Не копить в рабочем дереве.
|
||
- **Не расширять область работ.** Формулировка «сделай актуальным везде» не даёт права
|
||
на дополнительные шаги.
|
||
- **Не догадываться.** Не уверен — сказать прямо и спросить. Причину бага доказывать
|
||
фактами (логи, трассировки, содержимое файлов), а не гипотезами.
|
||
- Язык ответов — русский.
|
||
|
||
---
|
||
|
||
## 2. Проект
|
||
|
||
- Репозиторий: `/home/naeel/TF/tf_provider`
|
||
- Провайдер: `terraform-provider-nubes`, Go, `terraform-plugin-framework v1.8.0`
|
||
- **Go-модуль провайдера лежит в `provider/`** (не в корне). `go build ./...` из корня
|
||
падает с «directory prefix . does not contain main module».
|
||
- Генераторы в `TOOLS/`:
|
||
- `yaml-generator` — из API в YAML-спеки;
|
||
- `resource-generator` — из YAML в Go (шаблоны `text/template` в
|
||
`TOOLS/resource-generator/internal/templates/`);
|
||
- `docs-generator` — из YAML в Markdown.
|
||
- Пайплайн: `TOOLS/scripts/01_generate_yamls.sh` → `02_generate_resources_and_docs_v2.sh`
|
||
→ `03_build_and_upload_provider.sh` (скрипт `03` сам прогоняет `01` и `02`).
|
||
|
||
---
|
||
|
||
## 3. Состояние на 2026-09-21 (конец сессии)
|
||
|
||
- Ветка `master`, **рабочее дерево чистое**, HEAD = `13beb9c` (`release(dev): 2.0.8`).
|
||
- Локальные коммиты **в origin не пушились**.
|
||
- **DEV-версия: 2.0.8**, залита в
|
||
`tf-registry.containerk8s.services.ngcloud.ru/nubes-dev/nubes`,
|
||
подпись GPG `CB3A0DF161ECC416` (`tazet@narod.ru`, ключ `secrets/private_key.asc`).
|
||
- S3: `prod-s3/nubes-terraform-registry/...`, endpoint `https://s3.msk-1.ngcloud.ru`.
|
||
- Namespace: `nubes-dev`, провайдер `nubes`.
|
||
- Terraform v1.9.5 локально.
|
||
|
||
---
|
||
|
||
## 4. Что починено в этой сессии
|
||
|
||
| Коммит | Что |
|
||
|---|---|
|
||
| `7ecd2aa` | детерминированная пересборка генераторов (удалён устаревший бинарь) |
|
||
| `2286d34` | destroy-guard в `ModifyPlan` + универсальный refSvc (имя или UUID) |
|
||
| `1401003` | release 2.0.4 |
|
||
| `d608fba` | FullPipe: `edge.tf`, `storage_config` fast→SATA |
|
||
| `92e04da` | TODO-документ по багу docs-generator |
|
||
| `bffe3d9` | refSvc-поля без `Computed` (unset = null, а не unknown) |
|
||
| `61c7e20` | HISTORY сессии |
|
||
| `54b0baa` | release 2.0.5 |
|
||
| `af2e10b` | docs-generator: `map-fixed` → `= { ... }` (аргумент, не блок) |
|
||
| `7c2cc67` | docs-generator: `array-map-fixed` → `jsonencode([...])` |
|
||
| `3ca0752` | docs-generator: строковые дефолты в кавычках |
|
||
| `8d405ba` | core: lifecycle-aware подсказки + `supportsSuspend` в сигнатурах |
|
||
| `c6715e8` | генератор: `supportsSuspend` в diagnostics; нет `suspend_on_destroy` без suspend |
|
||
| `69808bd` | release 2.0.6 |
|
||
| `67c4d2f` | `TOOLS/scripts/validate_docs_examples.sh` |
|
||
| `14ada09` | ТЗ для Flash по tainted-replace |
|
||
| `724f5f7` | **убрана create-time проверка существования из `ModifyPlan`** (ломал tainted-replace и `destroy`) |
|
||
| `25080b7` | release 2.0.7 |
|
||
| `3c0157a` | **`ShouldBeOptionalComputed`**: read-back параметры без Default → `Optional+Computed` |
|
||
| `4b34cc7` | **core: гарантия known** — `unknown → null` для read-back полей |
|
||
| `13beb9c` | release 2.0.8 |
|
||
|
||
---
|
||
|
||
## 5. Ключевые архитектурные факты (не переоткрывать заново)
|
||
|
||
1. **Две копии сгенерированного кода.**
|
||
- `provider/internal/resources_gen/` — в `.gitignore`, локальный артефакт;
|
||
- `generated/dev/go/` — актуальный вывод генератора; именно его компилирует релиз
|
||
(скрипт `03` копирует его в temp-копию `provider`).
|
||
Проверять надо **`generated/dev/go`**, не `resources_gen`. Проверка не той копии
|
||
уже приводила к ложным выводам.
|
||
|
||
2. **Рецепт проверки сборки без релиза:**
|
||
```bash
|
||
TMP=$(mktemp -d) && cp -R provider "$TMP/provider" && \
|
||
find "$TMP/provider/internal/resources_gen" -maxdepth 1 -type f -name '*.go' -delete && \
|
||
cp generated/dev/go/*.go "$TMP/provider/internal/resources_gen/" && \
|
||
(cd "$TMP/provider" && go build ./...) && echo BUILD_OK && rm -rf "$TMP"
|
||
```
|
||
|
||
3. **Версия правится в 3 файлах:** `TOOLS/config/dev/profile.env` (`VERSION`),
|
||
`DEV_STAND/FullPipe/versions.tf`, `VERSIONS.md`.
|
||
Затем коммит `release(dev): X.Y.Z` и
|
||
`./TOOLS/scripts/03_build_and_upload_provider.sh --profile TOOLS/config/dev X.Y.Z`.
|
||
|
||
4. **Перезаливка той же версии бесполезна** — Terraform не перекачает провайдер.
|
||
Всегда бампать версию.
|
||
|
||
5. `*.tfvars` в `.gitignore` (реальный токен в `terraform.tfvars` безопасен от коммита).
|
||
|
||
6. **Read-back инвариант.** Провайдер читает параметр обратно из `state_params` инстанса
|
||
(`RefreshResourceState` + `InputField`). Такой параметр обязан быть `Optional+Computed`,
|
||
если он не `Required` и без `Default` — правило `helpers.ShouldBeOptionalComputed`.
|
||
Иначе `plan=null` vs `state=значение` → «Provider produced inconsistent result after
|
||
apply».
|
||
|
||
7. `RefreshResourceState` при отсутствии кода в `state_params` схлопывает `unknown → null`
|
||
(иначе «Provider produced invalid result object after apply: ... was unknown»).
|
||
|
||
8. **`terraform destroy` при tainted-ресурсе** выполняет внутренний обычный plan, который
|
||
планирует замену (destroy+create); create-узел замены приходит в `ModifyPlan` с prior
|
||
state = null — отличить замену от создания невозможно. Поэтому create-time проверка
|
||
существования из `ModifyPlan` убрана (коммит `724f5f7`), проверка осталась в `Create`.
|
||
|
||
9. У сервиса без операции `suspend` в YAML: `SupportsSuspendDestroy=false` →
|
||
`deleteMode := "delete"`, атрибут `suspend_on_destroy` не генерируется, а подсказки в
|
||
diagnostics не предлагают adopt (он невозможен).
|
||
|
||
10. Вложенные параметры (`map-fixed`) — `schema.SingleNestedAttribute`; в HCL это
|
||
**аргумент** `= { ... }`, не блок. `array-map-fixed` — `schema.StringAttribute`
|
||
(JSON-строка).
|
||
|
||
11. Логи и артефакты отладки: `/tmp/nubes_find_debug.log` (пишет только Plan-диагностика),
|
||
`/tmp/plan_trace.txt`, `/tmp/plan_destroy.txt`, `/tmp/plan_norefresh.txt`.
|
||
|
||
12. Секреты: `secrets/private_key.asc`, `secrets/public_key.asc`, `secrets/dev.token`.
|
||
Не выводить содержимое в чат.
|
||
|
||
---
|
||
|
||
## 6. Файлы, которые нужно прочесть
|
||
|
||
**Обязательно:**
|
||
|
||
1. `.github/copilot-instructions.md` — жёсткие правила оператора.
|
||
2. `VERSIONS.md` — что и когда залито.
|
||
3. `HISTORY/2026-09-21_fullpipe_vdc_nsxt_and_refsvc_fixes.md` — журнал предыдущей сессии.
|
||
4. `TOOLS/resource-generator/internal/templates/instance.go` — главный шаблон ресурса
|
||
инстанса (ModifyPlan / Create / Read / Update / Delete / Schema).
|
||
5. `TOOLS/resource-generator/internal/helpers/helpers.go` — `ShouldBeOptionalComputed`,
|
||
`ParamDefaultExpr`, `IsNested`, nested-хелперы.
|
||
6. `provider/internal/resources_core/state_refresh.go` — read-back и инвариант known.
|
||
7. `provider/internal/resources_core/resource_diagnostics_required.go` — create-time
|
||
проверки существования/усыновления, `runningConflictHint` / `suspendConflictHint`.
|
||
8. `TOOLS/scripts/03_build_and_upload_provider.sh` и `TOOLS/scripts/build-provider.sh` —
|
||
релизный пайплайн.
|
||
9. `DEV_STAND/FullPipe/` — `versions.tf`, `vdc.tf`, `edge.tf`, `variables.tf`, `outputs.tf`.
|
||
10. `docs/TODO/docs_generator_nested_attr_syntax.md` — описание бага docs-generator
|
||
(уже исправлен, см. раздел 8).
|
||
|
||
**По необходимости:**
|
||
|
||
- `TOOLS/resource-generator/internal/templates/{subresource,modifier,action}.go`
|
||
- `TOOLS/docs-generator/internal/writers/writers.go` — `formatParamOrBlock`, `sampleValue`,
|
||
`isNestedListParam`
|
||
- `provider/internal/resources_core/crud.go` — adopt / suspend / delete
|
||
- `docs/prompt_for_flash_fix_tainted_replace.md` — разбор tainted-replace
|
||
(реализован в `724f5f7`)
|
||
- `TOOLS/scripts/validate_docs_examples.sh` — прогон `terraform validate` по примерам из доков
|
||
- Память репозитория: `/memories/repo/registry-versions.md`
|
||
|
||
---
|
||
|
||
## 7. Стенд FullPipe (Organization → vDC → Edge)
|
||
|
||
- Каталог `DEV_STAND/FullPipe`, провайдер берётся из `versions.tf` (сейчас 2.0.8).
|
||
- `nubes_vc_vdc.vdc` — `suspend_on_destroy = true`, `adopt_existing_on_create = true`.
|
||
- `nubes_vc_nsxt.edge` — `routed_net_configuration` задаётся **через `=`** (объект), не блоком.
|
||
- Подхватить новую версию: `terraform init -upgrade`.
|
||
- На 2026-09-21 `nubes_vc_nsxt.edge` был **tainted** в state (последствие прошлых
|
||
неудачных apply). Убирается `terraform untaint nubes_vc_nsxt.edge`.
|
||
|
||
---
|
||
|
||
## 8. Открытые вопросы
|
||
|
||
1. **`docs/TODO/docs_generator_nested_attr_syntax.md` устарел** — баг исправлен
|
||
(`af2e10b`, `7c2cc67`, `3ca0752`), но в файле статус «не исправлено».
|
||
2. **Стенд FullPipe не проверен end-to-end на 2.0.8** — нет подтверждённого успешного
|
||
`apply` (Organization → vDC → Edge) и `destroy` после фиксов.
|
||
3. Полный прогон `terraform validate` по всем примерам из доков (63 сервиса) не делался —
|
||
проверен только `vc_nsxt`. Скрипт для прогона готов:
|
||
`TOOLS/scripts/validate_docs_examples.sh`.
|
||
4. `TOOLS/resource-generator/internal/templates/modifier.go:65` — та же схема `Computed`
|
||
без ветки read-back. Для бага «inconsistent result after apply» не критично
|
||
(Create/Update модификаторов не читают обратно в state), но при работе с `kind: modifier`
|
||
держать в голове.
|
||
5. Пуш локальных коммитов в `origin/master` не делался.
|