diff --git a/NOTES/20_prompts/prompt_for_opus_review_modify_resources_2026-09-24.md b/NOTES/20_prompts/prompt_for_opus_review_modify_resources_2026-09-24.md index 2c2bc9e..803a484 100644 --- a/NOTES/20_prompts/prompt_for_opus_review_modify_resources_2026-09-24.md +++ b/NOTES/20_prompts/prompt_for_opus_review_modify_resources_2026-09-24.md @@ -775,3 +775,48 @@ func (m jsonNormalizePlanModifier) PlanModifyString(_ context.Context, req planm 6. **Имена live-ключей** (`vIPConfigure`, `ipSpaceName`): где проверить, чтобы не полагаться на HAR? 7. **Что ещё в этом коде сломается**, чего я не вижу? Особенно: имена/семантика диагностик, поведение `void`-возвратов, `RemoveResource` vs `RemoveResource`-в-Delete, импорт. + +--- + +# 6. Ответ Opus на ревью (2026-09-24) + +**Вердикт:** главный блокер — **баг порядка ключей + `Required` с `null`**. Оба чинятся +канонизирующим plan-modifier'ом. Всё остальное (Configure/Import/Lock/diagnostics) — корректно. + +**По вопросам:** + +1. **Баг порядка ключей → вариант (б):** plan-modifier, прогоняющий значение через + `parseVipConfigure → formatVipConfigure`. Сортировка ключей (а) не спасает: `jsonencode` юзера даст + `count,name`, а `formatVipConfigure` — `name,count`; минус только nested (в). Чинить и тест + `TestFormatVipConfigure_Canonical` (ожидание в нём неверное). +2. **`Required` + `null` в `Read` = источник `Provider produced inconsistent result`.** После apply + state обязан совпасть с планом. Правильно: **не писать `null`**, хранить конфиг-значение; либо делать + атрибут `Optional`, а не `Required`. +3. **Read-back не обязателен**, но **канонизация ввода обязательна** — иначе inconsistent-result при первом + `refresh` (там и всплывёт баг п.1). +4. **Delete:** последовательность `ShouldRemoveFromState → Lock → ByCode` корректна. Но ошибки API при destroy + должны быть **error, а не warning**: иначе реальный сбой обнуления квоты замалчивается, ресурс уходит из + state, квота висит. Warning — только для «родителя уже нет». +5. **Идемпотентность:** `ByCode` выбран правильно (`ByIdempotent` сравнивает с `paramValue` формы, ложно + пропустит modify). +6. **Имена live-ключей:** в коде провайдера их нет — только HAR; сверить можно исключительно живым + `GetInstanceStateParams` (прогон). Пока это риск, а не факт. +7. **Дополнительно:** + - `setSnat`: тихая подмена `""` → `no-needed` — заменить на валидацию (ошибку). + - `nsxt_snat.Read`: `no-needed` пишется в state как реальное значение — согласовать с решением п.2. + - `applyAllocation` при пустом массиве → error, значит «снять всё» через `vip_configure` нельзя + (только destroy) — **задокументировать** в описании атрибута. + - Раздел 3 (риски живой платформы) без прогона не закрывается — остаётся открытым. + +## Требуется сделать (по итогам ревью) — ЖДЁТ КОМАНДЫ + +1. Заменить `JsonNormalize()` на канонизирующий plan-modifier (`parse → formatVipConfigure`) — закрывает + баг порядка ключей (в т.ч. для `jsonencode`). +2. Убрать запись `null` в `Required`-атрибуты (`vip_configure`, `ip_space_name`) — хранить конфиг-значение + либо сменить на `Optional`. +3. `Delete`: ошибки API → `AddError`; warning оставить только для отсутствующего родителя. +4. `setSnat`: вместо тихой подмены — валидация пустой строки. +5. Документировать: «снять всё» через `vip_configure` нельзя, только `destroy`. +6. Поправить `TestFormatVipConfigure_Canonical` (и добавить тест на канонизацию `jsonencode`-формы + `count,name`). +7. Требуется новый релиз провайдера (2.0.19) с повторной заливкой в `nubes-dev`.