Files
tf_provider/docs/DEBUG_REPORT_VM_FIX.md
2026-06-30 15:45:24 +04:00

5.0 KiB

Отчет о работе: Исправление ошибки 500 при модификации VM

1. Проблема

При попытке изменить ресурс nubes_vm_instance (например, изменить vm_cpu), Terraform получает ошибку 500 от API:

Status 500: {"ERROR":"Invalid call of the function [checkParam], 4th Argument [instanceOperationCfsParamUid] is of invalid type, Cannot cast String [] to a value of type [guid]","DETAIL":"the function is located at [/app/api/v1/resources/instance_operation_cfs_param_ls.cfc]"}

2. Анализ причины

Сообщение Cannot cast String [] to a value of type [guid] указывает на то, что бэкенд получает массив строк там, где ожидает одиночный GUID. Обычно это происходит в REST API, когда клиент отправляет несколько значений для одного ключа, или когда отправляется POST запрос для создания сущности, которая уже существует, и система дублирует параметр в список.

В отличие от создания (Create), операция модификации (Modify/Update) в Nubes API при инициализации (GET /instanceOperations/...) уже содержит текущие значения параметров (CfsParams).

Если мы безусловно используем метод POST для отправки параметров (как это было сделано в ресурсе Postgres), мы создаем дубликат параметра. По всей видимости, движок API (ColdFusion?) объединяет старое и новое значение в массив, что ломает валидацию checkParam.

3. Выполненные действия (Solution Attempt)

Я модифицировал файл internal/provider/vm_resource.go, полностью переписав функцию submitVMOperationParams.

Суть изменений:

  1. Динамический маппинг: Перед отправкой параметров провайдер теперь запрашивает детали операции (GetInstanceOperation).
  2. Определение UID: Мы строим карту существующих параметров: ParamName -> { ID, UID, CurrentValue }.
  3. Гибридная логика PUT/POST:
    • Если параметр уже существует в операции (есть instanceOperationCfsParamUid) -> Мы используем метод PUT.
      • URL: /instanceOperationCfsParams
      • Payload: включает instanceOperationCfsParamUid.
    • Если параметр новый (нет UID) -> Мы используем метод POST.
      • URL: /instanceOperationCfsParams
      • Payload: включает только instanceOperationUid и svcOperationCfsParamId.

Фрагмент кода (internal/provider/vm_resource.go):

if info.Uid != "" {
    // Update existing parameter -> PUT
    method = "PUT"
    payload = map[string]interface{}{
        "instanceOperationCfsParamUid": info.Uid,
        "svcOperationCfsParamId":       info.Id,
        "instanceOperationUid":         operationUid,
        "paramValue":                   np.Value,
    }
} else {
    // Create new parameter -> POST
    method = "POST"
    // ...
}

4. Текущий статус

Код компилируется и выполняется. Был обновлен провайдер (terraform-provider-nubes). Однако, при последнем запуске (terraform apply) ошибка 500 воспроизвелась снова с тем же текстом.

Это означает, что либо:

  1. Логика PUT тоже вызывает дублирование (возможно, API не поддерживает PUT для этого эндпоинта так, как мы ожидаем).
  2. Или ошибка instanceOperationCfsParamUid is String[] возникает из-за того, что я передаю этот UID в теле JSON, но API может ожидать его в URL или query params (хотя для PUT принято в теле или URL).

5. Планируемые дальнейшие шаги (остановлены)

Для полного решения требовалось бы:

  1. Проверить работу PUT через curl с разными форматами payload.
  2. Попробовать передавать UID параметра в рамках URL (REST-style): /instanceOperationCfsParams/{uid}.

Статус: Работа остановлена по требованию пользователя. Код зафиксирован в текущем состоянии (Гибридный PUT/POST).