# Резюме сессии: VDC create-flow, диалог с Opus и правка fallback (2026-09-21) ## 1. Контекст задачи - Цель: довести до рабочего состояния создание `nubes_vc_vdc` в `FullPipe`. - Симптом: при создании VDC провайдер падал на `GET /instanceOperations/{opUid}?fields=cfsParams` с HTTP 500. - В ходе разбора было подтверждено, что обычные сервисы через тот же провайдер работали, а VDC попадал в отдельную проблемную ветку backend-обработки. --- ## 2. Диагностика проблемы ### 2.1. Что ломалось - В `provider/internal/core/client.go` create-flow делал `GET /instanceOperations/{opUid}?fields=cfsParams` сразу после создания операции. - Для VDC этот запрос приводил к ошибке backend’а: - `Invalid call of the function [getResourceRealmConfig]` - `Cannot cast Object type [Struct] to a value of type [string]` - источник ошибки: `/app/api/v1/resources/instance_operation_cfs_param.cfc` - Причина по отчету: для `vc_vdc` вычислялся динамический `descr` у `storageConfig.name`, и backend падал на `resourceRealm`, который в DEV хранится как `Struct`, а не `string`. ### 2.2. Почему обычные сервисы не ломались - На обычных сервисах этот `GET` либо не попадал в проблемный backend-код, либо не требовал вычисления `resourceRealm`. - Для VDC в YAML есть специфическая зависимость: - `generated/dev/resources_yaml/21_vc_vdc.yaml` - `storageConfig.name` содержит вычисляемый `descr` с `getResourceRealmConfig(...resourceRealm...)`. - Для обычных сервисов, например `vapp` и `postgres`, такого вычисляемого `resourceRealm`-контекста нет. ### 2.3. Почему `hasUnresolvedParams` мешал - Эвристика проверяла **все** строковые параметры, а не только параметры с `ref_svc_id`. - Для VDC это ломало fallback на обычных литералах вроде: - `providerVdc = fast-2.8` - `networkProvider = default` - Эти значения не UUID и не JSON, но и резолвить их не нужно. - В результате при падении GET провайдер вместо продолжения переходил в ошибку. --- ## 3. Диалог с Opus ### 3.1. Что просили у Opus - Проверить только: - `provider/internal/core/client.go` - `docs/DEBUG_REPORT_VC_VDC_500.md` - `generated/dev/resources_yaml/21_vc_vdc.yaml` - `generated/dev/resources_yaml/26_vapp.yaml` - `generated/dev/resources_yaml/90_postgres.yaml` - Вопросы к Opus были узкими: 1. почему обычные сервисы работали, а VDC начал падать на `GET ?fields=cfsParams` 2. есть ли в VDC специфическая структура или зависимость, которой нет у обычных сервисов 3. является ли `hasUnresolvedParams` неверной эвристикой именно в этом месте 4. что именно надо исправить ### 3.2. Что ответил Opus по сути - Root cause — не данные Terraform и не сами строки `fast-2.8` / `default`, а backend-ошибка на `GET /instanceOperations/{opUid}?fields=cfsParams` именно для VDC. - VDC отличается от обычных сервисов тем, что в его YAML есть динамический `descr` для `storageConfig.name`, который тянет `resourceRealm`. - `hasUnresolvedParams` была признана лишней и хрупкой эвристикой: она может ломать fallback на обычных строках. - Итоговое решение Opus: при ошибке GET идти дальше по браузерному flow, без условий по всем строковым параметрам. ### 3.3. Дополнительные уточнения в диалоге - Был отдельный спор по формулировке про Lucee / ColdFusion backend. - В итоге было зафиксировано, что этот термин — не отдельная гипотеза, а просто обозначение backend-слоя, который уже фигурировал в отчетах и traceback’ах. - Opus также подтвердил, что для VDC этот GET нужен только как вспомогательный шаг для `resolveRefSvcParamValues`, а не как обязательный бизнес-этап. --- ## 4. Что изменили в коде ### 4.1. `provider/internal/core/client.go` - В `CreateGenericInstanceUniversalV6` удалён gate по `hasUnresolvedParams`. - Теперь логика такая: - если `GET /instanceOperations/{opUid}?fields=cfsParams` успешен — парсим и резолвим `ref_svc_id` - если GET падает — просто продолжаем POST’ить параметры, а потом идём в `validate-cfs` и `run` - Функция `hasUnresolvedParams` удалена полностью. - После удаления была убрана осиротевшая документационная строка, оставшаяся над `isHexDigit`. ### 4.2. `provider/internal/core/client_test.go` - Добавлен тест: - `TestCreateGenericInstanceUniversalV6_ContinuesWhenOpDetailsGETFails` - Тест моделирует: - `POST /instances` - `POST /instanceOperations` - `GET /instanceOperations/{opUid}?fields=cfsParams` → 500 - `POST /instanceOperationCfsParams` - `GET /instanceOperations/{opUid}/validate-cfs` - `POST /instanceOperations/{opUid}/run` - финальный `GET /instances/{uid}` - Проверка теста: - create-flow завершился успешно - все 7 параметров были отправлены с ожидаемыми значениями - polling по операции был ровно один раз --- ## 5. Проверка после правки - `cd /home/naeel/TF/tf_provider/provider && go test ./internal/core` — успешно. - После ревью был пойман и исправлен только косметический хвост: - старый комментарий над `isHexDigit`, оставшийся после удаления `hasUnresolvedParams`. - После этого пакет `internal/core` снова прошёл тесты. --- ## 6. Вывод по итогам сессии - Проблема была не в обычных сервисах как таковых, а в специфике VDC-данных и backend-пути, который срабатывал на `GET ?fields=cfsParams`. - `hasUnresolvedParams` была неверной эвристикой именно в create-flow VDC и ломала рабочий fallback. - Правильное поведение: если GET падает, не гадать по строковым параметрам, а продолжать browser-like flow через POST параметров, validate и run. --- ## 7. Что дальше - Следующий этап — уже не правка логики, а публикация и стендовая проверка при необходимости. - DEV-релиз `2.0.3` успешно собран и загружен в registry `nubes-dev` через `TOOLS/scripts/03_build_and_upload_provider.sh --profile TOOLS/config/dev`. - Перед этим уже был подготовлен короткий запрос на ревью для Opus и получен ответ, который подтвердил направление правки. --- ## 8. Отдельный диалог про `organization_uid`, refSvcId и универсальное поведение ### 8.1. Что стало проблемой - В `vc_vdc` поле `organization_uid` можно передавать как display name (`kontora`), так и как UUID организации. - В коде `provider/internal/resources_gen/21_vc_vdc_resource.go` это поле сейчас резолвится через `ResolveRefSvcParamValue(...)` в UUID. - После `apply` Terraform видит расхождение: в конфиге было имя, в state оказался UUID, и появляется ошибка `Provider produced inconsistent result after apply`. - Параллельно в этом же ресурсе остаются ручные `EqualFold`-хаки, которые пытаются сохранить старое значение, но не решают кейс "имя vs UUID". ### 8.2. Почему это сравнивали с S3 - Для `nubes_s3_bucket` похожее поведение уже работает: ref-поле `s3_user_uid` проходит через общий механизм refSvc-резолва и state-refresh. - В S3 есть симметричный путь: UUID можно принимать на вход, а состояние при чтении синхронизируется через общий mapping-слой. - Поэтому S3 не падает на inconsistency, а VDC падает из-за локальных restore-хаков и разного поведения на create/read/update. ### 8.3. Что выяснили по коду - Ключевой участок VDC: - [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L197-L202) - [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L323-L338) - [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L388-L403) - [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L511-L525) - В S3 аналогичный слой устроен аккуратнее: - [provider/internal/resources_gen/13_s3bucket_resource.go](provider/internal/resources_gen/13_s3bucket_resource.go#L149-L159) - [provider/internal/resources_core/state_refresh.go](provider/internal/resources_core/state_refresh.go#L82-L96) - [provider/internal/resources_core/params_ref_mapping.go](provider/internal/resources_core/params_ref_mapping.go#L124-L147) ### 8.4. Что решил сделать дальше - Пользователю нужен не частный фикс только для VDC, а универсальная схема для всех refSvcId-полей. - Была сформулирована задача для Opus: определить, какой канон выбрать для state, где делать name→UUID и UUID→display_name, и как убрать ручные `EqualFold`-хаки без поломки S3 и других уже рабочих ресурсов. - Отдельно зафиксировано требование: ответ Opus нужен короткий, но сам вопрос должен быть подробным и однозначным. ### 8.5. Важный вывод на сейчас - Универсальное решение пока не внедрено. - Текущий безопасный путь — сначала получить короткий архитектурный ответ от Opus, а уже потом править генератор и пересобирать ресурсы. --- ## 9. Детерминированная пересборка генератора - После отдельного разбора `kind: modifier` выяснилось, что падение генерации было эксплуатационным: запускался устаревший бинарник `resource-generator`, а не текущие исходники. - В `TOOLS/scripts/02_generate_resources_and_docs_v2.sh` убран `mtime`-гард через `find ... -newer`; генераторы теперь всегда собираются заново перед прогоном. - Это сделано специально, чтобы старый бинарник больше не мог скрыть поддержку новых `kind`-веток в YAML-спеках. - Дополнительно `TOOLS/resource-generator/bin/` добавлен в ignore, чтобы локальный stale-артефакт не путал следующий запуск.