fix(provider): нормализация регистра UUID при отправке map-fixed JSON в API

- resources_core.BuildJSON оборачивает результат в jsonutil.LowercaseUUIDsInText:
  платформа сравнивает регистр UUID при create, а ресурсы отдают id в UPPERCASE
  (nsxtUid/vdcUid) -> без нормализации create Штурвала падал 'Edge не развёрнут
  в указанном vDC' (обнаружено на провайдере 2.0.23 из-под Windows).
- Одна точка покрывает все map-fixed-параметры (create/modify/redeploy),
  регенерация не требуется.
- Документация: HISTORY/2026-09-30, docs/60_strategy/terraform_case_sensitivity_fix.md §11,
  NOTES/30_analysis/ARCHITECTURE_NEW.md §6.5, docs/help/architecture-and-methods.md §7.

Не выпущено: версия не поднималась, релиз/регенерация не выполнялись.
This commit is contained in:
Repinoid
2026-09-30 08:34:04 +03:00
parent 09e38928d0
commit 9aed2dcdd9
5 changed files with 178 additions and 1 deletions
@@ -280,6 +280,8 @@ Error: required params mismatch for resource_name shturval-dev: startupConfigura
| 7 | `resources_core/ref_validation.go` (`ValidateRefParamsOnAdopt`) | ref-параметр, зашитый внутрь JSON, **не проверяется вообще** (открыто) |
| 8 | `core/operation_run*.go` (`lookupLiveParam`) | подстановка live-значений по ключам: при другом регистре ключа может молча не сработать (открыто, требует живой проверки) |
> **Дополнение 2026-09-30**: пункты 9–10 (регистр UUID на **отправке** в API) — см. §11.
**Фикс (провайдер `2.0.23`, dev).**
- `internal/core/jsonutil/jsonutil.go`: добавлен `LowercaseUUIDsInText` (UUID-подстрока → lowercase), и строковые
@@ -295,3 +297,57 @@ Error: required params mismatch for resource_name shturval-dev: startupConfigura
значения); смотрите `jsonutil.LowercaseUUIDsInText`.
8. Не «лечите» это нормализацией плана целиком (скаляры → строки, сортировка ключей): для атрибутов из config
допустимо менять только регистр UUID-подстрок, иначе Terraform ругнётся на несоответствие плана конфигу.
9. Разделяйте **сравнение** и **отправку**: фиксы §10 закрывали только сравнение (план/state/adopt). Если ресурс
падает на create без видимых расхождений плана — смотрите путь отправки, §11.
---
## 11. Обновление 2026-09-30: UUID внутри JSON на ОТПРАВКЕ в API (create/modify/redeploy)
**Что уточнилось.** Все фиксы §10 закрывали **сравнение** (план vs state, adopt-suspended,
modifier-compare, диагностика) и **не** трогали то, что реально уходит в API при создании.
На провайдере `2.0.23` (то есть уже после §10) `create` кластера Штурвала **без** `lower(...)`
в HCL падал с «Edge не развёрнут в указанном vDC». Обнаружено при запуске Terraform
**из-под Windows**.
**Где именно.**
- Все map-fixed JSON-параметры (`startupConfiguration`, `clusterConfiguration`, …) собираются
одной функцией `resources_core.BuildJSON` (`provider/internal/resources_core/helpers.go`) —
она берёт значения подполей (`ValueString()`) **как есть**.
- Вызывает её сгенерированный код через `NestedJSONExpr` (`TOOLS/resource-generator/internal/templates/instance.go`,
ветки **Create** ~строка 302, **Modify** ~488, **Redeploy** ~505).
- `nubes_vc_nsxt` отдаёт `id` в UPPERCASE (`2C37FED1-…`), платформа хранит UUID в lowercase
и **сравнивает регистр при create** → UPPERCASE `nsxtUid`/`vdcUid` внутри JSON отвергается.
- `resolveRefSvcParamValues` (`core/refsvc.go`, `core/refsvc_resolve.go`) тут не спасает: он
нормализует только **top-level** refSvc-параметры и `s3.*uid` **внутри** map-fixed;
`vdcUid`/`nsxtUid` — обычные строковые подполя JSON, refSvcId у них нет.
**Аудит (продолжение таблицы §10, проверено 30.09).**
| # | Место | Что ломает |
|---|---|---|
| 9 | `resources_core/helpers.go` (`BuildJSON`) — **отправка** map-fixed JSON в API (create/modify/redeploy) | create падает: «Edge не развёрнут в указанном vDC» — регистр `vdcUid`/`nsxtUid` внутри JSON |
| 10 | `core/params.go` (`normalizeUniversalValueV6`) — дефолты create (`instance_create.go`) и досылка modify (`operation_run.go`) | скалярный UUID к lowercase не приводится (открыто, вторично) |
**Фикс (не выпущен, только код).**
- `provider/internal/resources_core/helpers.go`: `BuildJSON` оборачивает результат в
`jsonutil.LowercaseUUIDsInText(...)` (+ импорт `core/jsonutil`). Одна точка → покрыты **все**
map-fixed-параметры всех ресурсов на create / modify / redeploy. Регенерация не нужна.
**Почему это безопасно.**
- `BuildJSON` используется **только для отправки**, не для построения state (проверено: вызовы
только в `resources_gen/*.go`).
- Regex `uuidAnywhereRegex` (`[0-9a-f]{8}-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) совпадает только с UUID;
пароли/имена/иные строки не задевает. Внутри map-fixed строковых секретных полей
(password/secret/token) в спеках нет — только `*Uid`-ссылки на ресурсы.
- Это **выравнивание** с правилом «регистр UUID незначим» (то же приведение уже делается на
сравнении), а не новое поведение.
**Костыль в HCL.** `tf_examples/fullpipe_chain/shturval.tf:139-140`
(`vdc_uid = lower(...)`, `nsxt_uid = lower(...)`) после релиза этого фикса станет не нужен.
В локальных стендах `lower()` не используется: `DEV_STAND/FPipeGmail/shturval.tf:125-126` и
`DEV_STAND/FullPipe/shturval.tf1:123` передают `nubes_vc_vdc.vdc.id` / `nubes_vc_nsxt.edge.id`
напрямую → на create у них тот же риск.