From b539aab22851817aea981727eb27a8da73edcc43 Mon Sep 17 00:00:00 2001 From: kaje783 <120482249+kaje783@users.noreply.github.com> Date: Wed, 18 Jan 2023 04:57:28 +0100 Subject: [PATCH] fix(vm): Add parser for CustomEFIDisk (#208) * feat: add support for "args" flag for VM * switch from args to kvmarguments, update type * cosmetics: `kvmarguments` -> `kvm_arguments` also update doc to match description from the official PVE documentation. * fix(vm): Add parser for CustomEFIDisk * use parseDiskSize(&string) from utils.go for CustomEFIDisk * readd the remove space by github space * address linter errors, remove duplicated code, add unit test Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --- proxmox/utils.go | 44 +++++++++++++++++++ proxmox/utils_test.go | 37 ++++++++++++++++ proxmox/virtual_environment_vm_types.go | 34 ++++++++++++++ .../resource_virtual_environment_container.go | 2 +- proxmoxtf/resource_virtual_environment_vm.go | 4 +- proxmoxtf/utils.go | 35 --------------- 6 files changed, 118 insertions(+), 38 deletions(-) create mode 100644 proxmox/utils.go create mode 100644 proxmox/utils_test.go diff --git a/proxmox/utils.go b/proxmox/utils.go new file mode 100644 index 000000000..4f4f62382 --- /dev/null +++ b/proxmox/utils.go @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package proxmox + +import ( + "fmt" + "math" + "strconv" + "strings" +) + +func ParseDiskSize(size *string) (int, error) { + if size == nil { + return 0, nil + } + + if strings.HasSuffix(*size, "T") { + diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "T")) + if err != nil { + return -1, fmt.Errorf("failed to parse disk size: %w", err) + } + return int(math.Ceil(float64(diskSize) * 1024)), nil + } + + if strings.HasSuffix(*size, "G") { + diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "G")) + if err != nil { + return -1, fmt.Errorf("failed to parse disk size: %w", err) + } + return diskSize, nil + } + + if strings.HasSuffix(*size, "M") { + diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "M")) + if err != nil { + return -1, fmt.Errorf("failed to parse disk size: %w", err) + } + return int(math.Ceil(float64(diskSize) / 1024)), nil + } + + return -1, fmt.Errorf("cannot parse disk size \"%s\"", *size) +} diff --git a/proxmox/utils_test.go b/proxmox/utils_test.go new file mode 100644 index 000000000..914f82974 --- /dev/null +++ b/proxmox/utils_test.go @@ -0,0 +1,37 @@ +package proxmox + +import ( + "testing" +) + +func TestParseDiskSize(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + size *string + want int + wantErr bool + }{ + {"handle null size", nil, 0, false}, + {"parse terabytes", strPtr("2T"), 2048, false}, + {"parse gigabytes", strPtr("2G"), 2, false}, + {"parse megabytes", strPtr("2048M"), 2, false}, + {"error on arbitrary string", strPtr("something"), -1, true}, + {"error on missing unit", strPtr("12345"), -1, true}, + } + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got, err := ParseDiskSize(tt.size) + if (err != nil) != tt.wantErr { + t.Errorf("ParseDiskSize() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("ParseDiskSize() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/proxmox/virtual_environment_vm_types.go b/proxmox/virtual_environment_vm_types.go index 0a63529d2..d3a905b2e 100644 --- a/proxmox/virtual_environment_vm_types.go +++ b/proxmox/virtual_environment_vm_types.go @@ -1421,6 +1421,40 @@ func (r *CustomCPUEmulation) UnmarshalJSON(b []byte) error { return nil } +// UnmarshalJSON converts a CustomEFIDisk string to an object. +func (r *CustomEFIDisk) UnmarshalJSON(b []byte) error { + var s string + + err := json.Unmarshal(b, &s) + if err != nil { + return fmt.Errorf("failed to unmarshal CustomEFIDisk: %w", err) + } + + pairs := strings.Split(s, ",") + + for _, p := range pairs { + v := strings.Split(strings.TrimSpace(p), "=") + + if len(v) == 2 { + switch v[0] { + case "format": + r.Format = &v[1] + case "file": + r.FileVolume = v[1] + case "size": + iv, err := ParseDiskSize(&v[1]) + if err != nil { + return err + } + + r.DiskSize = &iv + } + } + } + + return nil +} + // UnmarshalJSON converts a CustomNetworkDevice string to an object. func (r *CustomNetworkDevice) UnmarshalJSON(b []byte) error { var s string diff --git a/proxmoxtf/resource_virtual_environment_container.go b/proxmoxtf/resource_virtual_environment_container.go index c2482057a..e1013aa32 100644 --- a/proxmoxtf/resource_virtual_environment_container.go +++ b/proxmoxtf/resource_virtual_environment_container.go @@ -1535,7 +1535,7 @@ func resourceVirtualEnvironmentContainerRead( volumeParts := strings.Split(containerConfig.RootFS.Volume, ":") disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] = volumeParts[0] - diskSize, err := parseDiskSize(containerConfig.RootFS.DiskSize) + diskSize, err := proxmox.ParseDiskSize(containerConfig.RootFS.DiskSize) if err != nil { return diag.FromErr(err) } diff --git a/proxmoxtf/resource_virtual_environment_vm.go b/proxmoxtf/resource_virtual_environment_vm.go index e27471086..693cfaf29 100644 --- a/proxmoxtf/resource_virtual_environment_vm.go +++ b/proxmoxtf/resource_virtual_environment_vm.go @@ -1706,7 +1706,7 @@ func resourceVirtualEnvironmentVMCreateClone( continue } - compareNumber, err := parseDiskSize(currentDiskInfo.Size) + compareNumber, err := proxmox.ParseDiskSize(currentDiskInfo.Size) if err != nil { return diag.FromErr(err) } @@ -3043,7 +3043,7 @@ func resourceVirtualEnvironmentVMReadCustom( diskSize := 0 var err error - diskSize, err = parseDiskSize(dd.Size) + diskSize, err = proxmox.ParseDiskSize(dd.Size) if err != nil { return diag.FromErr(err) } diff --git a/proxmoxtf/utils.go b/proxmoxtf/utils.go index c5e349a0a..dfba77d19 100644 --- a/proxmoxtf/utils.go +++ b/proxmoxtf/utils.go @@ -7,9 +7,7 @@ package proxmoxtf import ( "errors" "fmt" - "math" "regexp" - "strconv" "strings" "testing" "time" @@ -487,39 +485,6 @@ func getDiskDatastores(vm *proxmox.VirtualEnvironmentVMGetResponseData, d *schem return datastores } -func parseDiskSize(size *string) (int, error) { - var diskSize int - var err error - if size != nil { - if strings.HasSuffix(*size, "T") { - diskSize, err = strconv.Atoi(strings.TrimSuffix(*size, "T")) - - if err != nil { - return -1, err - } - - diskSize = int(math.Ceil(float64(diskSize) * 1024)) - } else if strings.HasSuffix(*size, "G") { - diskSize, err = strconv.Atoi(strings.TrimSuffix(*size, "G")) - - if err != nil { - return -1, err - } - } else if strings.HasSuffix(*size, "M") { - diskSize, err = strconv.Atoi(strings.TrimSuffix(*size, "M")) - - if err != nil { - return -1, err - } - - diskSize = int(math.Ceil(float64(diskSize) / 1024)) - } else { - return -1, fmt.Errorf("cannot parse storage size \"%s\"", *size) - } - } - return diskSize, err -} - func getPCIInfo(vm *proxmox.VirtualEnvironmentVMGetResponseData, d *schema.ResourceData) map[string]*proxmox.CustomPCIDevice { pciDevices := map[string]*proxmox.CustomPCIDevice{}