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.
Суть изменений:
- Динамический маппинг: Перед отправкой параметров провайдер теперь запрашивает детали операции (
GetInstanceOperation). - Определение UID: Мы строим карту существующих параметров:
ParamName -> { ID, UID, CurrentValue }. - Гибридная логика PUT/POST:
- Если параметр уже существует в операции (есть
instanceOperationCfsParamUid) -> Мы используем методPUT.- URL:
/instanceOperationCfsParams - Payload: включает
instanceOperationCfsParamUid.
- URL:
- Если параметр новый (нет UID) -> Мы используем метод
POST.- URL:
/instanceOperationCfsParams - Payload: включает только
instanceOperationUidиsvcOperationCfsParamId.
- URL:
- Если параметр уже существует в операции (есть
Фрагмент кода (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 воспроизвелась снова с тем же текстом.
Это означает, что либо:
- Логика
PUTтоже вызывает дублирование (возможно, API не поддерживает PUT для этого эндпоинта так, как мы ожидаем). - Или ошибка
instanceOperationCfsParamUid is String[]возникает из-за того, что я передаю этот UID в теле JSON, но API может ожидать его в URL или query params (хотя для PUT принято в теле или URL).
5. Планируемые дальнейшие шаги (остановлены)
Для полного решения требовалось бы:
- Проверить работу
PUTчерез curl с разными форматами payload. - Попробовать передавать UID параметра в рамках URL (REST-style):
/instanceOperationCfsParams/{uid}.
Статус: Работа остановлена по требованию пользователя. Код зафиксирован в текущем состоянии (Гибридный PUT/POST).