docs(HISTORY): сессия 2026-09-21 - фиксы генератора, refSvc, FullPipe (vDC+Edge)
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
# 2026-09-21 — FullPipe (vDC + Edge): серия фиксов генератора и провайдера
|
||||
|
||||
## Контекст
|
||||
|
||||
Поднимался полный стенд `DEV_STAND/FullPipe` (целевой пайплайн: Организация → vDC → Edge),
|
||||
заливался провайдер в реестр (`nubes-dev/nubes`). По ходу вылезла цепочка багов —
|
||||
в генераторе ресурсов, в сгенерированном коде и в docs-генераторе.
|
||||
|
||||
Версия на выходе: **2.0.5** (DEV, namespace `nubes-dev`).
|
||||
|
||||
---
|
||||
|
||||
## Баг 1. Непересобираемый генератор (stale binary) — устранён ранее в этот же день
|
||||
|
||||
**Симптом:** `kind: modifier` в YAML не поддерживался; генерация YAML падала.
|
||||
|
||||
**Причина:** `02_generate_resources_and_docs_v2.sh` пересобирал `resource-generator`
|
||||
только по `mtime`. Лежавший в `TOOLS/resource-generator/bin/resource-generator`
|
||||
устаревший бинарь затенял исходники.
|
||||
|
||||
**Фикс:**
|
||||
- генераторы (`resource-generator`, `docs-generator`) пересобираются **всегда** из исходников;
|
||||
- устаревший бинарник удалён; `TOOLS/resource-generator/bin/` добавлен в `.gitignore`;
|
||||
- обновлены `README.md`, `TOOLS/README.md`.
|
||||
- Коммит: `7ecd2aa Fix generator rebuild and release pipeline`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 2. `declared and not used: resolvedKafkaUid` — сборка падала
|
||||
|
||||
**Симптомы (сборка из сгенерированного кода):**
|
||||
```
|
||||
internal/resources_gen/119_akhq_resource.go:246:2: declared and not used: resolvedKafkaUid
|
||||
internal/resources_gen/111_dnsrecord_resource.go:248:2: declared and not used: resolvedZoneUid
|
||||
internal/resources_gen/21_vc_vdc_resource.go:244:2: declared and not used: resolvedOrganizationUid
|
||||
... (и ещё по всем ресурсам с refSvc в create)
|
||||
```
|
||||
|
||||
**Причина:** в шаблоне `TOOLS/resource-generator/internal/templates/instance.go`:
|
||||
- блок объявления резолва шёл по `{{range .SchemaParams}}` — т.е. объявлял `resolvedX`
|
||||
для **всех** refSvc-полей;
|
||||
- а мапа `params` в `Create` НЕ содержала refSvc-условия и писала сырое `data.X`.
|
||||
|
||||
Итог: `resolvedX` объявлен, но нигде не использован → ошибка компиляции.
|
||||
|
||||
**Фикс (шаблон `instance.go`, `subresource.go`):**
|
||||
- циклы резолва переведены на `{{range .CreateParams}}` / `{{range .ModifyParams}}`;
|
||||
- в мапу `params` в `Create` добавлено refSvc-условие:
|
||||
```
|
||||
{{.ID}}: resolved{{ToCamel .Code}}, // в API уходит UUID
|
||||
{{else}} data.X // сырое значение
|
||||
```
|
||||
- Коммит: `2286d34`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 3. `terraform destroy` падал: «РЕСУРС С ТАКИМ ИМЕНЕМ УЖЕ СУЩЕСТВУЕТ (RUNNING)»
|
||||
|
||||
**Симптом:**
|
||||
```
|
||||
terraform destroy
|
||||
nubes_vc_vdc.vdc: Refreshing state... [id=...]
|
||||
╷ Error: РЕСУРС С ТАКИМ ИМЕНЕМ УЖЕ СУЩЕСТВУЕТ (RUNNING)
|
||||
```
|
||||
|
||||
**Причина:** `ModifyPlan` сгенерированного ресурса на **destroy-плане** запускал
|
||||
create-time проверку существования/adopt (`PlanExistingResourceDiagnostics...` →
|
||||
`FindInstanceByDisplayName`). Гварды `config == nil` и
|
||||
`State.Raw.IsNull() && Plan.Raw.IsNull()` destroy не отсекали (config ненулевой —
|
||||
блок ресурса ещё в `.tf`; а в destroy-плане state есть, plan = null).
|
||||
|
||||
Debug-подтверждение: `/tmp/nubes_find_debug.log` →
|
||||
`PlanExistingResourceDiagnostics entered: serviceId=21 name="fullpipe-vdc" adopt=false`.
|
||||
|
||||
**Обходной путь (временный):** `adopt_existing_on_create=true` — но это «телега впереди
|
||||
лошади»: destroy не должен зависеть от adopt.
|
||||
|
||||
**Фикс (шаблон `instance.go`, `ModifyPlan`):** добавить destroy-guard
|
||||
```
|
||||
if req.Plan.Raw.IsNull() { return }
|
||||
```
|
||||
Теперь destroy-план не запускает create-time проверку и доходит до `Delete`,
|
||||
который по `suspend_on_destroy=true` отправляет `suspend`.
|
||||
|
||||
Логика suspend уже была в `Delete`: `deleteMode := "state_only"` → `"suspend"`.
|
||||
|
||||
- Коммит: `2286d34`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 4. `Provider produced inconsistent result after apply`: `.organization_uid` было `"kontora"`, стало UUID
|
||||
|
||||
**Симптом:**
|
||||
```
|
||||
.provider produced an unexpected new value: .organization_uid:
|
||||
was cty.StringVal("kontora"), but now cty.StringVal("ec4d3a6a-...")
|
||||
```
|
||||
|
||||
**Причина:** refSvc-поле резолвилось и **записывалось обратно в state**, из-за чего
|
||||
state (UUID) не совпадал с plan (user input).
|
||||
|
||||
**Фикс (универсальный, все сервисы):**
|
||||
- резолв идёт только в локальную переменную `resolvedX`; в state остаётся ровно то,
|
||||
что ввёл пользователь (имя ИЛИ UUID);
|
||||
- refresh исключает refSvc-поля (`{{if eq .RefSvcId 0}}`) — не перезаписывает ввод;
|
||||
- `ResolveRefSvcParamValue` принимает имя (→ UUID) и UUID (→ lowercase);
|
||||
обратный маппинг `ResolveRefSvcParamDisplayName` для refresh.
|
||||
- Коммит: `2286d34`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 5. `Provider returned invalid result object after apply`: `vdc_group_uid` остался unknown
|
||||
|
||||
**Симптом (создание Edge):**
|
||||
```
|
||||
Error: Provider returned invalid result object after apply
|
||||
After the apply operation, the provider still indicated an unknown value for
|
||||
nubes_vc_nsxt.edge.vdc_group_uid.
|
||||
```
|
||||
|
||||
**Причина:** в схеме refSvc-поля были `Optional: true, Computed: true` **без дефолта**
|
||||
(строка шаблона: `{{- else if or .IsJson (gt .RefSvcId 0) }}Computed: true,{{- end }}`).
|
||||
Если пользователь поле не задавал (например, `vdc_group_uid` при `vdc_type="vdc"`),
|
||||
Terraform планировал его как **unknown** и требовал от провайдера известное значение.
|
||||
Провайдер его не вычисляет (по дизайну хранит ввод юзера) → остаётся unknown → ошибка.
|
||||
|
||||
`Computed: true` — рудимент **старого** дизайна (когда провайдер писал резолвленный UUID
|
||||
в state). После перехода на «храним ввод юзера» он стал вредным.
|
||||
|
||||
**Фикс (оба шаблона: `instance.go`, `subresource.go`):**
|
||||
```
|
||||
- {{- else if or .IsJson (gt .RefSvcId 0) }}Computed: true,{{- end }}
|
||||
+ {{- else if .IsJson }}Computed: true,{{- end }}
|
||||
```
|
||||
Теперь незаданный refSvc = `null` (известное значение). `IsJson` оставлен Computed
|
||||
намеренно (нужно для нормализации JSON из API).
|
||||
|
||||
Проверено: в сгенерированном `22_vc_nsxt_resource.go` →
|
||||
`"vdc_group_uid": schema.StringAttribute{Optional: true, ...}` (без `Computed`).
|
||||
|
||||
- Коммит: `bffe3d9`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 6. docs-generator: вложенный `map-fixed` рендерится как блок (НЕ исправлено → TODO)
|
||||
|
||||
Пример в сгенерированной доке (`generated/dev/docs/vc_nsxt_example.md`) рисует
|
||||
`routed_net_configuration` **блоком**, но схема — `SingleNestedAttribute`, значит нужен
|
||||
аргумент `= { ... }`. Копирование примера → `terraform validate` падает:
|
||||
`Unsupported block type`.
|
||||
|
||||
Виноват `TOOLS/docs-generator/internal/writers/writers.go` → `formatParamOrBlock`
|
||||
(~стр. 715). Подробности — `docs/TODO/docs_generator_nested_attr_syntax.md`.
|
||||
Коммит: `92e04da`.
|
||||
|
||||
---
|
||||
|
||||
## Баг 7. FullPipe: дефолт `vdc_storage_config = "fast"`
|
||||
|
||||
**Симптом:** дефолт в `variables.tf` — `[{"name":"fast","size":200}]`.
|
||||
Имя политики берётся из ресурсного пула (`getKeyListFromStruct(...providerVdcs[...].storage)`),
|
||||
и `fast` в окружении не существует.
|
||||
|
||||
**История (по git):** `fast` появился в первом коммите стенда `7ff98f8` — причём их было
|
||||
**два**: `vdc_provider_vdc = "fast-2.8"` и `vdc_storage_config = "fast"`. Коммит
|
||||
`7d44697` («Fix FullPipe VDC example placeholders») поправил только `provider_vdc`
|
||||
(`"fast-2.8"` → `null`), а `storage_config` не тронул. Так что «опять fast» — это
|
||||
незакрытый второй хвост, а не откат.
|
||||
|
||||
**Фикс:** дефолт → `[{"name":"SATA","size":"200"}]` (совпадает с рабочим `terraform.tfvars`).
|
||||
Коммит: `d608fba`.
|
||||
|
||||
---
|
||||
|
||||
## Добавлено в стенд FullPipe
|
||||
|
||||
- `DEV_STAND/FullPipe/edge.tf` — ресурс `nubes_vc_nsxt.edge` (create),
|
||||
`vdc_uid = nubes_vc_vdc.vdc.id` (Edge создаётся после vDC),
|
||||
`routed_net_configuration = { ... }` (аргумент, не блок — см. Баг 6).
|
||||
- переменные `nsxt_*` в `variables.tf`, outputs `nsxt_*` в `outputs.tf`,
|
||||
пример в `terraform.tfvars.example`.
|
||||
- `versions.tf` → провайдер `2.0.4` (затем `2.0.5`).
|
||||
- Коммит: `d608fba`.
|
||||
|
||||
---
|
||||
|
||||
## Изменённые файлы (генератор)
|
||||
|
||||
| Файл | Что |
|
||||
|------|-----|
|
||||
| `TOOLS/resource-generator/internal/templates/instance.go` | destroy-guard в `ModifyPlan`; резолв refSvc по `.CreateParams`; refSvc-условие в мапе `params`; refSvc без `Computed` |
|
||||
| `TOOLS/resource-generator/internal/templates/subresource.go` | резолв по `.CreateParams`/`.ModifyParams`; refSvc без `Computed` |
|
||||
| `TOOLS/scripts/02_generate_resources_and_docs_v2.sh` | детерминированная пересборка генераторов |
|
||||
| `.gitignore`, `README.md`, `TOOLS/README.md` | игнор бинарника, доки |
|
||||
|
||||
## Версии
|
||||
|
||||
| Стенд | Namespace | Версия |
|
||||
|---|---|---|
|
||||
| DEV | `nubes-dev` | `2.0.5` |
|
||||
|
||||
## Коммиты сессии (master)
|
||||
|
||||
```
|
||||
bffe3d9 fix(generator): refSvc-поля без Computed (unset = null, а не unknown)
|
||||
92e04da docs(TODO): баг docs-generator - вложенный map-fixed как блок вместо = {}
|
||||
d608fba stand(FullPipe): vc_nsxt (edge.tf), storage_config fast->SATA, provider 2.0.4
|
||||
1401003 release(dev): 2.0.4
|
||||
2286d34 fix(generator): destroy-guard в ModifyPlan + универсальный refSvc (имя или UUID)
|
||||
7ecd2aa Fix generator rebuild and release pipeline
|
||||
```
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
- [ ] docs-generator: `map-fixed` → `= { ... }`, `array-map-fixed` → JSON/jsonencode
|
||||
(см. `docs/TODO/docs_generator_nested_attr_syntax.md`).
|
||||
- [ ] Проверить `IsJson`-поля без дефолта: тот же класс unknown-after-apply? (не воспроизводилось).
|
||||
- [ ] `fast` в тест-фикстуре `provider/internal/core/client_test.go:287` и спек-доке
|
||||
`docs/60_strategy/...:158` — не трогали.
|
||||
Reference in New Issue
Block a user