validateAndBuildModifyRequest validates modify presets against the current instance and spec store, returning a ready-to-send API request or an error.
(presets *tui.ModifyPresets, currentInstance *api.Instance, specs *utils.SpecStore)
| 357 | // validateAndBuildModifyRequest validates modify presets against the current instance |
| 358 | // and spec store, returning a ready-to-send API request or an error. |
| 359 | func validateAndBuildModifyRequest(presets *tui.ModifyPresets, currentInstance *api.Instance, specs *utils.SpecStore) (api.InstanceModifyRequest, error) { |
| 360 | req := api.InstanceModifyRequest{} |
| 361 | hasChanges := false |
| 362 | |
| 363 | // GPU type validation |
| 364 | if presets.GPUType != nil { |
| 365 | gpuType := strings.ToLower(*presets.GPUType) |
| 366 | |
| 367 | normalizedGPU, ok := specs.NormalizeGPUType(gpuType) |
| 368 | if !ok { |
| 369 | availableGPUs := specs.GPUOptions() |
| 370 | return req, usageErr("invalid GPU type '%s'. Valid options: %s", gpuType, strings.Join(availableGPUs, ", ")) |
| 371 | } |
| 372 | |
| 373 | req.GPUType = &normalizedGPU |
| 374 | hasChanges = true |
| 375 | } |
| 376 | |
| 377 | // VCPUs validation (development only) |
| 378 | if presets.VCPUs != nil { |
| 379 | vcpus := *presets.VCPUs |
| 380 | |
| 381 | // Determine effective GPU type for validation |
| 382 | effectiveGPU := currentInstance.GPUType |
| 383 | if req.GPUType != nil { |
| 384 | effectiveGPU = *req.GPUType |
| 385 | } |
| 386 | effectiveNumGPUs := 1 |
| 387 | if presets.NumGPUs != nil { |
| 388 | effectiveNumGPUs = *presets.NumGPUs |
| 389 | } else if currentInstance.NumGPUs != "" { |
| 390 | if n, err := fmt.Sscanf(currentInstance.NumGPUs, "%d", &effectiveNumGPUs); n != 1 || err != nil { |
| 391 | effectiveNumGPUs = 1 |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | allowedVCPUs := specs.VCPUOptions(effectiveGPU, effectiveNumGPUs) |
| 396 | if allowedVCPUs != nil && !slices.Contains(allowedVCPUs, vcpus) { |
| 397 | return req, usageErr("vcpus must be one of %v for %s with %d GPU(s)", allowedVCPUs, effectiveGPU, effectiveNumGPUs) |
| 398 | } |
| 399 | |
| 400 | req.CPUCores = &vcpus |
| 401 | hasChanges = true |
| 402 | } |
| 403 | |
| 404 | // NumGPUs validation |
| 405 | if presets.NumGPUs != nil { |
| 406 | numGPUs := *presets.NumGPUs |
| 407 | |
| 408 | effectiveGPU := currentInstance.GPUType |
| 409 | if req.GPUType != nil { |
| 410 | effectiveGPU = *req.GPUType |
| 411 | } |
| 412 | allowedGPUCounts := specs.GPUCounts(effectiveGPU) |
| 413 | if !slices.Contains(allowedGPUCounts, numGPUs) { |
| 414 | return req, usageErr("num-gpus %d is not valid for %s. Allowed: %v", numGPUs, effectiveGPU, allowedGPUCounts) |
| 415 | } |
| 416 |
no test coverage detected