diff --git a/docs/CHAT_RESUME_2026-09-22.md b/docs/CHAT_RESUME_2026-09-22.md new file mode 100644 index 0000000..e06ab72 --- /dev/null +++ b/docs/CHAT_RESUME_2026-09-22.md @@ -0,0 +1,194 @@ +# Передача контекста: 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` не делался.