docs(opus): задокументировать разбор бага сброса create-полей modify
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
# Opus-разбор: modify-модификатор сбрасывает create-поля в дефолт — 2026-09-22
|
||||||
|
|
||||||
|
Источник: ответ Opus на `prompt_for_opus_modifier_null_bug.md`.
|
||||||
|
|
||||||
|
## Симптом
|
||||||
|
|
||||||
|
`nubes_vc_nsxt_network` (modifier vc_nsxt.network, modify 111) после create Edge с
|
||||||
|
`needEnableAVI=true`, `virtualServicesCount=3` сбрасывал `needEnableAVI` на платформе
|
||||||
|
обратно в `false`.
|
||||||
|
|
||||||
|
## Корень бага (подтверждено cfsParams операций)
|
||||||
|
|
||||||
|
Два пути отправки modify ведут себя по-разному:
|
||||||
|
|
||||||
|
- **Generic modify** (`UpdateResource` → `RunInstanceOperationUniversalWithDefaults`,
|
||||||
|
`client.go:493`) — в цикле дозаполнения шлёт **все** незаданные cfsParams их текущим
|
||||||
|
`ParamValue` (или `DefaultValue`) — безусловно.
|
||||||
|
- **Модификатор** (`RunOperationByCodeWithTimeout` → `RunInstanceOperationUniversalByCode`,
|
||||||
|
`client.go:1518`) — в аналогичном цикле стоял guard `if !param.IsRequired { continue }`,
|
||||||
|
который пропускал опциональные параметры.
|
||||||
|
|
||||||
|
`needEnableAVI` — опциональный параметр modify 111 и не входит в `SchemaParams` модификатора
|
||||||
|
`vc_nsxt.network` (там только SNAT/routedNetConfiguration). Итог:
|
||||||
|
1. модификатор его не шлёт (не его поле);
|
||||||
|
2. back-fill его пропускает (`IsRequired == false`);
|
||||||
|
3. бэкенд видит отсутствующий параметр → трактует как reset-to-default → `false`.
|
||||||
|
|
||||||
|
`CompactParams` тут ни при чём для `needEnableAVI` — параметр вообще не был в payload модификатора.
|
||||||
|
|
||||||
|
## Ответы Opus
|
||||||
|
|
||||||
|
1. **Полный или частичный payload?** Канон — полный: все параметры операции, незаданные
|
||||||
|
дозаполняются текущим live-значением (`ParamValue`). Бэкенд для modify трактует
|
||||||
|
пропущенный/null как reset-to-default, поэтому частичный payload обязан затирать create-поля.
|
||||||
|
2. **Где чинить?** В `RunInstanceOperationUniversalByCode` — убрать `IsRequired`-guard в цикле
|
||||||
|
дозаполнения (стало: слать ВСЕ незаданные params их live-значением, как в `WithDefaults`).
|
||||||
|
- НЕ в `CompactParams` (он не видит полный набор cfsParams, только поля модификатора).
|
||||||
|
- НЕ в шаблоне генератора (шаблон тоже не знает полного набора).
|
||||||
|
3. **Риск для vc_org.ip_space:** основной live-путь безопасен (досылка идёт **текущим** значением,
|
||||||
|
не хардкод-дефолтом). На fallback-пути `/instanceOperations/default/{opId}` `ParamValue` пуст —
|
||||||
|
есть только `DefaultValue`; но тот же риск уже несёт `WithDefaults`, новой регрессии нет.
|
||||||
|
|
||||||
|
## Внесённый фикс
|
||||||
|
|
||||||
|
`provider/internal/core/client.go` — `RunInstanceOperationUniversalByCode`, цикл дозаполнения:
|
||||||
|
убраны `if !param.IsRequired { continue }` и `if !param.IsRequired && val == "" { continue }`.
|
||||||
|
Теперь все незаданные параметры modify досылаются их live-значением (или default).
|
||||||
|
|
||||||
|
Коммит: `c420ea0`.
|
||||||
|
|
||||||
|
## Примечание
|
||||||
|
|
||||||
|
Костыль в `DEV_STAND/FullPipe/edge_network.tf` (явная передача ALB/VS/qos в модификаторе)
|
||||||
|
после фикса ядра становится избыточным, но не вреден. После пересборки провайдера можно
|
||||||
|
убрать эти три поля из `edge_network.tf` — досылка теперь происходит автоматически.
|
||||||
Reference in New Issue
Block a user