# Ревью: модификаторы vc_nsxt / vc_org + досылка modify-params (Terraform Provider Nubes) Ты — ревьюер. Ничего не правь. Прочитай и выдай: 1) подтверждение/опровержение каждого утверждения ниже; 2) список багов/рисков, которые я НЕ заметил; 3) список проблем, которые я заметил ошибочно (ложные тревоги); 4) чёткую рекомендацию по каждому корректному фиксу (минимальную, без scope creep). ## Контекст системы Go Terraform provider `terraform-provider-nubes` (plugin-framework), сервис Nubes Cloud. Генератор ресурсов: `TOOLS/resource-generator` (шаблон `instance.go`, `modifier.go`). Ядро: `provider/internal/core/` (HTTP + операции), `provider/internal/resources_core/` (обёртки). Сервисы, о которых речь: - `vc_nsxt` (serviceId 22). Операции: create (10), delete (25), **modify (111, kind: modifier, modifier: network)**, reconcile. У resource НЕТ instance-modify. - `vc_org` (serviceId 19). Модификатор `ip_space` (modify 207). Модификатор = отдельный TF resource (`nubes_vc_nsxt_network`, `nubes_vc_org_ip_space`), который вызывает операцию `modify` с параметрами. ## Цель (FullPipe) — что должно работать 1. Создать VDC (vc_vdc). 2. Создать Edge (vc_nsxt) с ALB (`needEnableAVI=true`, `virtualServicesCount=3`). 3. Выделить IP организации (vc_org → modifier ip_space, `vIPConfigure`). 4. Применить SNAT для Edge (vc_nsxt → modifier network, `ipSpaceName` + `routedNetConfiguration`). ## Что УЖЕ сделано (факты, проверь корректность) ### Факт 1. `resource "nubes_vc_nsxt"` Update — no-op Шаблон `instance.go` генерирует `hasServiceParamChanges := false`, а цикл по `.ModifyParams` пуст (у vc_nsxt нет instance-modify). Поэтому `Update` всегда уходит в `if !hasServiceParamChanges { ...; return }` и НЕ вызывает `modify` (111). Изменение ALB/VS/qos через resource невозможно. Изменения Edge идут ТОЛЬКО через модификатор `nubes_vc_nsxt_network`. ### Факт 2. Досылка незаданных modify-params (мой свежий фикс, коммиты a011358) Раньше незаданные params операции `modify` досылались значением `paramValue` из `GET /instanceOperations/{opUid}?fields=cfsParams`. Это ОШИБОЧНО: `paramValue` — дефолт ФОРМЫ операции, а не состояние инстанса. Для `needEnableAVI` там `"false"`, хотя live-значение инстанса `true` (подтверждается HAR/edge_.har и HAR/ipSpace0.har). Из-за этого каждый `modify` через модификатор сбрасывал ALB в false. Фикс: в `operation_cfs.go` добавлены `instanceLiveParams()` (читает live из `GET /instances/{uid}` → `state.params`) и `lookupLiveParam(live, cfsParam)`. В `runInstanceOperationByCode` и `RunInstanceOperationUniversalWithDefaults` приоритет теперь: **live state.params → paramValue → defaultValue**. ### Факт 3. `ShouldRemoveFromState` (коммит 94c4c44) Раньше вызывал валидирующий `GetInstanceState`, который на статусе `deleted` кидал `instanceDeletedError` — и `Read` модификатора падал с "экземпляр … удалён" вместо тихого удаления из state. Переписан на `GetInstanceStateRaw` + различение 404/deleted (remove=true) vs сеть/5xx/403 (нужно `false, err`). ## ОШИБКА, которую наблюдаю СЕЙЧАС (главное) `terraform apply` падает: ``` Error: Provider returned invalid result object after apply After the apply operation, the provider still indicated an unknown value for nubes_vc_nsxt.edge.qos_profile. All values must be known after apply... ``` `qos_profile` у resource `nubes_vc_nsxt` = `Optional+Computed` БЕЗ Default (`ShouldBeOptionalComputed` → true, потому что param qosProfile: not required, RefSvcId=0, Default=""). В конфиге не задаётся → в плане unknown. А `Update` (`hasServiceParamChanges=false` → ранний return) копирует только `State*`/`Vault*` outputs, но НЕ вызывает `RefreshResourceState`, поэтому `qos_profile` остаётся unknown. ## МОИ ДИАГНОЗЫ (проверь каждый, а не только текущий) ### Диагноз A (текущая ошибка) Ранний return в `Update` (шаблон instance.go) не схлопывает unknown→null read-back-computed поля. Нужно в ветке `!hasServiceParamChanges` вызывать тот же `RefreshResourceState`, а не копировать `State*`/`Vault*` вручную. ### Диагноз B (вылезет после A) Тот же ранний return оставляет unknown для `need_enable_avi` и `virtual_services_count`, если их убрать из `edge.tf` (а их и должны убрать, раз ALB перенесён в модификатор). Один корень с A. ### Диагноз C (дублирование конфига — НЕ починен) `edge.tf` ДО СИХ ПОР задаёт `need_enable_avi` и `virtual_services_count` (create), а `edge_network.tf` — те же значения (modifier). Это двойное задание одного и того же → возможен дрейф. Нужно определить: где канонически задавать ALB? ### Диагноз D (ловушка destroy/delete) Модификатор имеет `delete_strategy: inverse`, override `needEnableAVI="false"`. При `terraform destroy` ALB выключится. Повторный `apply` через `resource "nubes_vc_nsxt"` (no-op Update) НЕ включит обратно, а включит только модификатор второй apply-волной. Нужно проверить порядок зависимостей. ### Диагноз E `FetchInstanceOutputs` глотает любую API-ошибку (5xx/404) и возвращает пустые outputs без diagnostic → молчаливый дрейф. Нужен warning. ## Конкретные вопросы 1. Подтверди/опровергни Диагноз A как корень текущей ошибки. 2. Есть ли проблема в моём фиксе досылки (Факт 2)? В частности: - верно ли, что `state.params` — единственный достоверный источник live? - не сломает ли `lookupLiveParam` (по Code/SvcOperationCfsParam/Name/Label) какие-то кейсы, где имя в state.params отличается регистром/форматом от этих ключей? - не создаёт ли `instanceLiveParams` лишний сетевой вызов на каждый modify (перф)? 3. Верна ли трактовка Факт 1 (resource Update — no-op)? Или правильнее ДОБАВИТЬ instance-modify в генератор? 4. Какое каноническое место для `need_enable_avi`/`virtual_services_count`/`qos_profile`: create (edge.tf) или modifier (edge_network.tf)? Что делать с текущим дублированием? 5. Что ещё я упустил в цепочке create→modify→read→destroy?