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:
@@ -0,0 +1,87 @@
|
||||
# 2026-09-30 — Регистр UUID: нормализация на ОТПРАВКЕ в API (create/modify/redeploy)
|
||||
|
||||
> Разбор: `docs/60_strategy/terraform_case_sensitivity_fix.md` §11 (главный документ по теме),
|
||||
> `NOTES/30_analysis/ARCHITECTURE_NEW.md` §6.5.
|
||||
|
||||
## Что обнаружилось
|
||||
|
||||
Костыль `lower(...)` в конфиге стенда Штурвала — **не «просто проще», а обязателен**.
|
||||
Без него `terraform apply` (create кластера) падает: платформа отвечает
|
||||
«Edge не развёрнут в указанном vDC».
|
||||
|
||||
Обнаружено при запуске Terraform **из-под Windows**, на провайдере **2.0.23**
|
||||
(то есть после всех «фиксов регистра», выпущенных 24.09).
|
||||
|
||||
Костыль живёт в примере (и в gitea `Nail/tf_examples`):
|
||||
|
||||
```hcl
|
||||
# tf_examples/fullpipe_chain/shturval.tf:139-140
|
||||
vdc_uid = lower(nubes_vc_vdc.vdc.id)
|
||||
nsxt_uid = lower(nubes_vc_nsxt.edge.id)
|
||||
```
|
||||
|
||||
## Почему прошлые фиксы не помогли (главная мысль)
|
||||
|
||||
Провайдер `2.0.23` нормализует регистр UUID **только при СРАВНЕНИИ**:
|
||||
план vs state, adopt/suspend/resume, modifier-compare, диагностика
|
||||
(`jsonutil.LowercaseUUIDsInText` → `JSONStringsEquivalent`, `JsonNormalize()`,
|
||||
`ParamsMatchForResume`, `normalizeCompareValue`).
|
||||
|
||||
**Путь ОТПРАВКИ в API остался без нормализации.** Все map-fixed JSON-параметры
|
||||
собираются одной функцией `resources_core.BuildJSON`
|
||||
(`provider/internal/resources_core/helpers.go`), а её вызывает сгенерированный код
|
||||
(`NestedJSONExpr`, шаблон `TOOLS/resource-generator/internal/templates/instance.go`,
|
||||
ветки Create / Modify / Redeploy). `BuildJSON` берёт `ValueString()` подполей **как есть**.
|
||||
|
||||
Ресурс `nubes_vc_nsxt` отдаёт `id` в UPPERCASE (`2C37FED1-…`), платформа хранит
|
||||
UUID в lowercase и **сравнивает регистр при create** → `startupConfiguration.nsxtUid`
|
||||
в верхнем регистре отвергается.
|
||||
|
||||
Почему не спас `resolveRefSvcParamValues` (`core/refsvc.go`,
|
||||
`core/refsvc_resolve.go`): он нормализует только **top-level** refSvc-параметры и
|
||||
`s3.*uid` **внутри** map-fixed. `vdcUid`/`nsxtUid` — обычные строковые подполя
|
||||
JSON, refSvcId у них нет, под шаблон `s3.*uid` они не подпадают.
|
||||
|
||||
## Что сделано
|
||||
|
||||
| Файл | Изменение |
|
||||
|---|---|
|
||||
| `provider/internal/resources_core/helpers.go` | `BuildJSON` оборачивает результат в `jsonutil.LowercaseUUIDsInText(...)` (+ импорт `core/jsonutil`, комментарий-обоснование) |
|
||||
|
||||
Одна точка → покрыты **все** map-fixed-параметры всех ресурсов на
|
||||
create / modify / redeploy (19 сгенерированных ресурсов, `resources_gen/`).
|
||||
Регенерация не требуется (логика сериализации одна).
|
||||
|
||||
## Оценка риска (почему это безопасно)
|
||||
|
||||
- `BuildJSON` используется **только для отправки** в API, не для построения state.
|
||||
- Regex `uuidAnywhereRegex` = `[0-9a-f]{8}-xxxx-xxxx-xxxx-xxxxxxxxxxxx` — совпадает
|
||||
только с UUID; пароли/имена/произвольные строки не задевает.
|
||||
- Проверено по спекам: внутри map-fixed **нет** строковых секретных полей
|
||||
(password/secret/token) — только `*Uid`-ссылки на ресурсы.
|
||||
- Это **выравнивание** с уже принятым в провайдере правилом «регистр UUID незначим»
|
||||
(то же приведение уже делается на сравнении), а не новое поведение.
|
||||
|
||||
Остаточный риск: если в map-fixed когда-нибудь появится строковое поле, где
|
||||
пользователь хранит **свой** UUID, и регистр там семантически важен (не ссылка на
|
||||
ресурс) — он будет приведён к lowercase. Сейчас таких полей нет.
|
||||
|
||||
## Следствия
|
||||
|
||||
- `lower(...)` в HCL становится **не нужен** — убирать в конфигах и в примере
|
||||
(отдельной командой, после релиза провайдера).
|
||||
- **Не выпущено**: версия не поднималась, релиз/заливка в реестр не выполнялись,
|
||||
регенерация не запускалась.
|
||||
- В локальных стендах костыля нет: `DEV_STAND/FPipeGmail/shturval.tf:125-126` и
|
||||
`DEV_STAND/FullPipe/shturval.tf1:123` передают `nubes_vc_vdc.vdc.id` /
|
||||
`nubes_vc_nsxt.edge.id` напрямую → на create у них тот же риск.
|
||||
|
||||
## Открытые вопросы (не закрыты)
|
||||
|
||||
1. Проверить на живом стенде: create кластера Штурвала **без** `lower(...)` на сборке
|
||||
с этим фиксом — `apply` запускает только пользователь.
|
||||
2. `core/params.go` → `normalizeUniversalValueV6`: скалярные UUID, попадающие в
|
||||
дефолты create (`instance_create.go`) и в досылку modify (`operation_run.go`),
|
||||
к lowercase не приводятся (вторично, нужен замер).
|
||||
3. `resources_core/ref_validation.go` (`ValidateRefParamsOnAdopt`): ref-параметр
|
||||
внутри JSON не валидируется при adopt (открыто с 24.09).
|
||||
Reference in New Issue
Block a user