63 lines
5.0 KiB
Markdown
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).
|