From aca15e8f698c5ff78a552ce976781d0d833f5c7b Mon Sep 17 00:00:00 2001 From: Repinoid Date: Tue, 22 Sep 2026 18:55:27 +0300 Subject: [PATCH] =?UTF-8?q?docs(opus):=20=D0=B7=D0=B0=D0=B4=D0=BE=D0=BA?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D1=80=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B3=D0=B0=20=D1=81=D0=B1=D1=80=D0=BE=D1=81=D0=B0=20cre?= =?UTF-8?q?ate-=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20modify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-09-22_modifier_null_reset_bug.md | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 HISTORY/OPUS/2026-09-22_modifier_null_reset_bug.md diff --git a/HISTORY/OPUS/2026-09-22_modifier_null_reset_bug.md b/HISTORY/OPUS/2026-09-22_modifier_null_reset_bug.md new file mode 100644 index 0000000..64591f0 --- /dev/null +++ b/HISTORY/OPUS/2026-09-22_modifier_null_reset_bug.md @@ -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` — досылка теперь происходит автоматически.