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

63 lines
5.0 KiB
Markdown

# Отчет о работе: Исправление ошибки 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):
```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).