diff --git a/HISTORY/SONNET/2026-07-08_find_instance_by_display_name_bug.md b/HISTORY/SONNET/2026-07-08_find_instance_by_display_name_bug.md new file mode 100644 index 0000000..25e5a66 --- /dev/null +++ b/HISTORY/SONNET/2026-07-08_find_instance_by_display_name_bug.md @@ -0,0 +1,26 @@ +# 2026-07-08 — FindInstanceByDisplayName: анализ Opus + +## Проблема + +`FindInstanceByDisplayName("NaeelOrg", 19)` возвращает nil → adopt не работает → план показывает `+ create`. + +## Три кандидата (Opus) + +### 🔴 #1: silent error swallow в GetInstanceStateRaw +`client.go:~605` — `GetInstanceStateRaw` может возвращать ошибку, которая проглатывается `continue`. Ни search-путь, ни fallback не логируют ошибку. + +### 🟡 #2: fields с URL-encoded запятыми +`url.Values.Encode()` кодирует `,` → `%2C`. Если API не понимает `%2C`, search возвращает пустой массив → fallback → провал. + +### 🟡 #3: API возвращает другое имя поля +Если API возвращает `display_name` вместо `displayName` — `item.DisplayName` = "", `EqualFold("", "NaeelOrg")` = false. + +## Что делать (по приоритету) + +1. **Добавить stderr-лог** на каждый `continue` в `FindInstanceByDisplayName` — покажет точную причину. +2. **Убрать `fields`** из search-запроса (строка ~574) — проверить кандидата #2. +3. **Включить `NUBES_DEBUG_HTTP=1`** — лог doRequest. + +## Доп. баг + +Fallback использует `size=100`, search-путь — `pageSize=100`. Разные параметры пагинации. diff --git a/TEST_STAND/buck0/main.tf b/TEST_STAND/buck0/main.tf index 6441c6e..346a620 100644 --- a/TEST_STAND/buck0/main.tf +++ b/TEST_STAND/buck0/main.tf @@ -14,9 +14,10 @@ provider "nubes" { } # S3 bucket — замени "buck0" на своё имя везде ниже -resource "nubes_s3bucket" "bukka" { # ← замени buck0 на своё имя ресурса - resource_name = "Бакет тест1" # ← замени buck0 на своё имя ресурса - s3_user_uid = "naeel-s3" - # s3_user_uid = var.s3_user_uid - bucket_name = "buck0" # ← замени buck0 на своё имя бакета +resource "nubes_s3bucket" "bukka0" { # ← замени buck0 на своё имя ресурса + resource_name = "btst" # ← замени buck0 на своё имя ресурса + #s3_user_uid = "naeel-s3" + s3_user_uid = var.s3_user_uid + bucket_name = "buck01" # ← замени buck0 на своё имя бакета + adopt_existing_on_create = true } diff --git a/TEST_STAND/kuber/main.tf b/TEST_STAND/kuber/main.tf index 3ee3452..a870064 100644 --- a/TEST_STAND/kuber/main.tf +++ b/TEST_STAND/kuber/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { nubes = { source = "terra.k8c.ru/nubes-test/nubes" - version = "5.0.66" + version = "5.0.67" } } } diff --git a/TOOLS/config/test/profile.env b/TOOLS/config/test/profile.env index 547af1e..1eb1f1d 100644 --- a/TOOLS/config/test/profile.env +++ b/TOOLS/config/test/profile.env @@ -3,7 +3,7 @@ NUBES_API_ENDPOINT="https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" TOKEN_FILE="secrets/test.token" # Version -VERSION="5.0.66" +VERSION="5.0.67" # Docs generation — ONLY from docs_gen// (never from docs/) DOCS_GEN_DIR="provider/docs_gen/test" diff --git a/prompt_for_opus_bugs.md b/prompt_for_opus_bugs.md index 8998202..1fc0503 100644 --- a/prompt_for_opus_bugs.md +++ b/prompt_for_opus_bugs.md @@ -1,53 +1,28 @@ -# Prompt for Opus — поиск багов в 3 файлах - -Проверь эти 3 конкретных файла на баги, аналогичные `skip_missing_on_delete` (провайдерский параметр с плохим дефолтом, которого нет в API YAML). - -## Файл 1: Шаблон генератора -`/home/naeel/tf_provider/TOOLS/resource-generator/internal/templates/templates.go` - -Смотри все хардкодженные атрибуты (НЕ из `.SchemaParams` / `.OutputParams`): -- `resource_name` -- `operation_timeout` -- `log_level` -- `suspend_on_destroy` -- `adopt_existing_on_create` -- `skip_missing_on_delete` -- `git_revision` -- `{service}_id` - -Вопросы: -- У каждого: правильный ли дефолт? -- Не создаёт ли проблем при параллельных/повторных apply? -- `skip_missing_on_delete` с дефолтом `false` — уже известный баг. Есть ли другие? - -## Файл 2: CRUD-логика -`/home/naeel/tf_provider/provider/internal/resources_core/crud.go` - -Вопросы: -- `FindSubresourceInStateOut` — не должна ли проверка молча пропускать удаление? -- `IsSubresourceMissingError` — все ли ошибки ловит? -- `adoptExistingInstanceOnCreate` — есть ли гонки при параллельном adopt? - -## Файл 3: Сгенерированный subresource -`/home/naeel/tf_provider/generated/test/go/90_postgres_database_resource.go` - -Вопросы: -- Delete (строки 251-330): правильный ли handling "объект уже удалён"? -- Create: что при duplicate? -- `skipMissingOnDelete` — везде ли корректно? - -## Что искать -1. Ошибки вместо идемпотентности (delete/create должны быть идемпотентны) -2. Плохие дефолты (как `skip_missing_on_delete=false`) -3. Гонки при параллельных операциях -4. Провайдерские параметры не из API — все ли оправданы? +# Задача: FindInstanceByDisplayName не находит существующий инстанс — анализ ## Контекст -- API не поддерживает параллельные операции на одном инстансе -- Subresource delete падает с ошибкой если объект уже удалён -- `skip_missing_on_delete` — костыль для обхода, дефолт `false` (баг) -- Уже добавлен instance-level mutex в v5.0.63 -## Формат ответа -Для каждого бага: `файл:строка` → симптом → причина → исправление. -Не читай другие файлы без необходимости. +Провайдер `terraform-provider-nubes` v5.0.65, test-стенд. +Инстанс: `NaeelOrg`, serviceId=19, instanceUid=`3f0850f2-3506-4efd-b84b-7270b5027ab5`, статус Running. + +## Симптом + +`terraform plan` с `adopt_existing_on_create=true`, `resource_name="NaeelOrg"` → `+ create`. Apply → «уже существует». + +## Доказано curl-тестами + +1. Search API: `GET /instances?search=NaeelOrg&serviceId=19&isAuxiliary=false&isDeleted=false` + `UA: Mozilla/5.0` → находит. +2. GetInstanceStateRaw: `GET /instances/3f0850f2-...` → возвращает, isDeleted=false, Running. + +## Ключевые файлы + +- `provider/internal/core/client.go` — `FindInstanceByDisplayName()`:568, `doRequest()`:949, `GetInstanceStateRaw()`:753, `isInstanceDeleted()`:741 +- `provider/internal/resources_core/resource_diagnostics.go` — `PlanExistingResourceDiagnostics()`:14 +- `provider/internal/resources_core/crud.go` — `CreateResource()`:21, `adoptExistingInstanceOnCreate()`:142 +- `generated/test/go/19_vc_org_resource.go` — `ModifyPlan()` +- `TEST_STAND/kuber/resources.tf` — манифест +- `HISTORY/OPUS/3006_0_answers.md`:220 — search ✅ / fallback ❌ + +## Задание + +Найти **точно**, почему `FindInstanceByDisplayName("NaeelOrg", 19)` возвращает nil. Если не хватает данных — сказать, какой curl-тест запустить. diff --git a/provider/main.go b/provider/main.go index 2703504..ee5746d 100644 --- a/provider/main.go +++ b/provider/main.go @@ -17,7 +17,7 @@ import ( ) var ( - version string = "5.0.66" + version string = "5.0.67" ) func main() {