Skip to content

Commit 1f7b5be

Browse files
committed
Fixed extra_config update
1 parent f8288ec commit 1f7b5be

5 files changed

Lines changed: 222 additions & 118 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
***Warning: Using "Release Candidate" versions (-rc.X) in a **production environment** is **strongly discouraged**, as they may contain unresolved bugs and pose risks to the stability and security of your systems.***
22

3-
## 1.0.1-rc.1 (September 5th, 2025)
3+
## 1.1.0-rc.1 (September 9th, 2025)
4+
5+
IMPROVEMENTS :
6+
7+
* Added automatic state migration for `extra_config` in resource `cloudtemple_compute_virtual_machine`.
8+
- The `extra_config` parameter format has been changed from array of objects to a map for better usability
9+
- Existing Terraform states with the old format will be automatically migrated to the new format
10+
- Old format: `[{"key": "svga.present", "value": "TRUE"}]`
11+
- New format: `{"svga.present": "TRUE"}`
12+
- This migration is transparent and requires no user action
413

514
NEW FEATURES :
615

716
* Added update extra config to ressource `cloudtemple_compute_virtual_machine`.
17+
- Supported keys: `guestinfo.ignition.config.data`, `guestinfo.ignition.config.data.encoding`, `guestinfo.afterburn.initrd.network-kargs`, `stealclock.enable`, `disk.enableUUID`, `pciPassthru.use64BitMMIO`, `pciPassthru.64bitMMioSizeGB`
818

919
## 1.0.0 (September 5th, 2025)
1020

internal/client/compute_virtual_machine.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,17 @@ func (v *VirtualMachineClient) Recommendation(ctx context.Context, filter *Virtu
339339
return out, nil
340340
}
341341

342-
type UpdateExtraConfigRequest struct {
343-
ExtraConfig []VirtualMachineExtraConfig `json:"extraConfig"`
344-
}
345-
346-
func (v *VirtualMachineClient) UpdateExtraConfig(ctx context.Context, id string, req *UpdateExtraConfigRequest) (string, error) {
342+
// type UpdateExtraConfigRequest struct {
343+
// DiskEnableUUID map[string]string `json:"disk.enableUUID,omitempty"`
344+
// PCIPassthruUse64BitMMIO map[string]string `json:"pciPassthru.use64BitMMIO,omitempty"`
345+
// PCIPassthru64bitMMioSizeGB map[string]string `json:"pciPassthru.64bitMMioSizeGB,omitempty"`
346+
// GuestinfoIgnitionConfigData map[string]string `json:"guestinfo.ignition.config.data,omitempty"`
347+
// GuestinfoIgnitionConfigDataEncoding map[string]string `json:"guestinfo.ignition.config.data.encoding,omitempty"`
348+
// GuestinfoAfterburnInitrdNetworkKargs map[string]string `json:"guestinfo.afterburn.initrd.network-kargs,omitempty"`
349+
// StealclockEnable map[string]string `json:"stealclock.enable,omitempty"`
350+
// }
351+
352+
func (v *VirtualMachineClient) UpdateExtraConfig(ctx context.Context, id string, req map[string]interface{}) (string, error) {
347353
r := v.c.newRequest("PATCH", "/compute/v1/vcenters/virtual_machines/%s/extra_config", id)
348354
r.obj = req
349355
return v.c.doRequestAndReturnActivity(ctx, r)

internal/provider/helpers/helper_compute_virtual_machine.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package helpers
33
import (
44
"context"
55
"fmt"
6+
"strconv"
67

78
"github.com/cloud-temple/terraform-provider-cloudtemple/internal/client"
89
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -272,18 +273,30 @@ func FlattenOSNetworkAdapterData(osNetworkAdapter *client.NetworkAdapter) interf
272273
return networkAdapter
273274
}
274275

275-
// ExpandExtraConfig convertit une map Terraform en slice de structures pour l'API
276-
func ExpandExtraConfig(extraConfigMap map[string]interface{}) []client.VirtualMachineExtraConfig {
277-
if extraConfigMap == nil {
278-
return nil
279-
}
276+
// convertExtraConfigValue convertit une valeur string vers le type approprié selon la clé
277+
func ConvertExtraConfigValue(key, value string) (interface{}, error) {
278+
switch key {
279+
// Clés booléennes VMware (strictes)
280+
case "disk.enableUUID", "stealclock.enable", "pciPassthru.use64BitMMIO":
281+
switch value {
282+
case "TRUE", "true":
283+
return true, nil
284+
case "FALSE", "false":
285+
return false, nil
286+
default:
287+
return nil, fmt.Errorf("invalid boolean value '%s' for key '%s', expected 'TRUE' or 'FALSE'", value, key)
288+
}
280289

281-
extraConfig := make([]client.VirtualMachineExtraConfig, 0, len(extraConfigMap))
282-
for key, value := range extraConfigMap {
283-
extraConfig = append(extraConfig, client.VirtualMachineExtraConfig{
284-
Key: key,
285-
Value: value.(string),
286-
})
290+
// Clés numériques
291+
case "pciPassthru.64bitMMioSizeGB":
292+
if i, err := strconv.Atoi(value); err != nil {
293+
return nil, fmt.Errorf("invalid integer value '%s' for key '%s': %v", value, key, err)
294+
} else {
295+
return i, nil
296+
}
297+
298+
// Clés string (par défaut - toutes les non gérées)
299+
default:
300+
return value, nil
287301
}
288-
return extraConfig
289302
}

internal/provider/helpers/helper_compute_virtual_machine_test.go

Lines changed: 51 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -7,107 +7,79 @@ import (
77
"github.com/cloud-temple/terraform-provider-cloudtemple/internal/client"
88
)
99

10-
func TestExpandExtraConfig(t *testing.T) {
10+
func TestConvertExtraConfigValue(t *testing.T) {
1111
tests := []struct {
12-
name string
13-
input map[string]interface{}
14-
expected []client.VirtualMachineExtraConfig
12+
name string
13+
key string
14+
value string
15+
expected interface{}
16+
expectError bool
1517
}{
18+
// Tests pour les clés booléennes
1619
{
17-
name: "nil input",
18-
input: nil,
19-
expected: nil,
20+
name: "boolean TRUE",
21+
key: "disk.enableUUID",
22+
value: "TRUE",
23+
expected: true,
2024
},
2125
{
22-
name: "empty map",
23-
input: map[string]interface{}{},
24-
expected: []client.VirtualMachineExtraConfig{},
26+
name: "boolean FALSE",
27+
key: "stealclock.enable",
28+
value: "FALSE",
29+
expected: false,
2530
},
2631
{
27-
name: "single config",
28-
input: map[string]interface{}{
29-
"stealclock.enable": "TRUE",
30-
},
31-
expected: []client.VirtualMachineExtraConfig{
32-
{
33-
Key: "stealclock.enable",
34-
Value: "TRUE",
35-
},
36-
},
32+
name: "boolean invalid value",
33+
key: "disk.enableUUID",
34+
value: "yes",
35+
expectError: true,
3736
},
37+
// Tests pour les clés numériques
3838
{
39-
name: "multiple configs",
40-
input: map[string]interface{}{
41-
"guestinfo.ignition.config.data": "base64_encoded_data",
42-
"guestinfo.ignition.config.data.encoding": "base64",
43-
"guestinfo.afterburn.initrd.network-kargs": "ip=dhcp",
44-
"stealclock.enable": "TRUE",
45-
"disk.enableUUID": "TRUE",
46-
"pciPassthru.use64BitMMIO": "TRUE",
47-
"pciPassthru.64bitMMioSizeGB": "64",
48-
},
49-
expected: []client.VirtualMachineExtraConfig{
50-
{
51-
Key: "guestinfo.ignition.config.data",
52-
Value: "base64_encoded_data",
53-
},
54-
{
55-
Key: "guestinfo.ignition.config.data.encoding",
56-
Value: "base64",
57-
},
58-
{
59-
Key: "guestinfo.afterburn.initrd.network-kargs",
60-
Value: "ip=dhcp",
61-
},
62-
{
63-
Key: "stealclock.enable",
64-
Value: "TRUE",
65-
},
66-
{
67-
Key: "disk.enableUUID",
68-
Value: "TRUE",
69-
},
70-
{
71-
Key: "pciPassthru.use64BitMMIO",
72-
Value: "TRUE",
73-
},
74-
{
75-
Key: "pciPassthru.64bitMMioSizeGB",
76-
Value: "64",
77-
},
78-
},
39+
name: "integer valid",
40+
key: "pciPassthru.64bitMMioSizeGB",
41+
value: "64",
42+
expected: 64,
43+
},
44+
{
45+
name: "integer invalid",
46+
key: "pciPassthru.64bitMMioSizeGB",
47+
value: "not_a_number",
48+
expectError: true,
49+
},
50+
// Tests pour les clés string (non gérées)
51+
{
52+
name: "string unmanaged key",
53+
key: "svga.present",
54+
value: "TRUE",
55+
expected: "TRUE",
56+
},
57+
{
58+
name: "string ignition data",
59+
key: "guestinfo.ignition.config.data",
60+
value: "base64_data",
61+
expected: "base64_data",
7962
},
8063
}
8164

8265
for _, tt := range tests {
8366
t.Run(tt.name, func(t *testing.T) {
84-
result := ExpandExtraConfig(tt.input)
67+
result, err := ConvertExtraConfigValue(tt.key, tt.value)
8568

86-
if tt.expected == nil {
87-
if result != nil {
88-
t.Errorf("Expected nil, got %v", result)
69+
if tt.expectError {
70+
if err == nil {
71+
t.Errorf("Expected error but got none")
8972
}
9073
return
9174
}
9275

93-
if len(result) != len(tt.expected) {
94-
t.Errorf("Expected %d items, got %d", len(tt.expected), len(result))
76+
if err != nil {
77+
t.Errorf("Unexpected error: %v", err)
9578
return
9679
}
9780

98-
// Convert to maps for easier comparison since order might vary
99-
resultMap := make(map[string]string)
100-
for _, item := range result {
101-
resultMap[item.Key] = item.Value
102-
}
103-
104-
expectedMap := make(map[string]string)
105-
for _, item := range tt.expected {
106-
expectedMap[item.Key] = item.Value
107-
}
108-
109-
if !reflect.DeepEqual(resultMap, expectedMap) {
110-
t.Errorf("Expected %v, got %v", expectedMap, resultMap)
81+
if !reflect.DeepEqual(result, tt.expected) {
82+
t.Errorf("Expected %v (%T), got %v (%T)", tt.expected, tt.expected, result, result)
11183
}
11284
})
11385
}

0 commit comments

Comments
 (0)