Skip to content

Commit 137de92

Browse files
Fix VPC interface addresses flattening (#408)
* Fix VPC interface addresses flattening in `flattenVPCInterface` * Comprehensive uni test suites for flatten functions * format
1 parent e648171 commit 137de92

3 files changed

Lines changed: 399 additions & 12 deletions

File tree

builder/linode/step_create_disk_config_test.go

Lines changed: 144 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package linode
22

33
import (
4+
"reflect"
45
"strings"
56
"testing"
67

@@ -271,22 +272,52 @@ func TestFlattenDisk(t *testing.T) {
271272
t.Run(tt.name, func(t *testing.T) {
272273
got := flattenDisk(tt.disk)
273274

274-
if got.Label != tt.want.Label {
275-
t.Errorf("flattenDisk() Label = %v, want %v", got.Label, tt.want.Label)
276-
}
277-
if got.Size != tt.want.Size {
278-
t.Errorf("flattenDisk() Size = %v, want %v", got.Size, tt.want.Size)
279-
}
280-
if got.Image != tt.want.Image {
281-
t.Errorf("flattenDisk() Image = %v, want %v", got.Image, tt.want.Image)
282-
}
283-
if got.Filesystem != tt.want.Filesystem {
284-
t.Errorf("flattenDisk() Filesystem = %v, want %v", got.Filesystem, tt.want.Filesystem)
275+
if !reflect.DeepEqual(got, tt.want) {
276+
t.Fatalf("flattenDisk() = %+v, want %+v", got, tt.want)
285277
}
286278
})
287279
}
288280
}
289281

282+
func TestFlattenDisk_AllFields(t *testing.T) {
283+
disk := Disk{
284+
Label: "boot",
285+
Size: 32000,
286+
Image: "linode/ubuntu24.04",
287+
Filesystem: "ext4",
288+
AuthorizedKeys: []string{"ssh-rsa AAAA-test"},
289+
AuthorizedUsers: []string{"root", "devops"},
290+
StackscriptID: 123,
291+
StackscriptData: map[string]string{"foo": "bar"},
292+
}
293+
294+
got := flattenDisk(disk)
295+
if got.Label != disk.Label {
296+
t.Fatalf("Label = %q, want %q", got.Label, disk.Label)
297+
}
298+
if got.Size != disk.Size {
299+
t.Fatalf("Size = %d, want %d", got.Size, disk.Size)
300+
}
301+
if got.Image != disk.Image {
302+
t.Fatalf("Image = %q, want %q", got.Image, disk.Image)
303+
}
304+
if got.Filesystem != disk.Filesystem {
305+
t.Fatalf("Filesystem = %q, want %q", got.Filesystem, disk.Filesystem)
306+
}
307+
if len(got.AuthorizedKeys) != 1 || got.AuthorizedKeys[0] != "ssh-rsa AAAA-test" {
308+
t.Fatalf("AuthorizedKeys = %v, want [ssh-rsa AAAA-test]", got.AuthorizedKeys)
309+
}
310+
if len(got.AuthorizedUsers) != 2 || got.AuthorizedUsers[0] != "root" || got.AuthorizedUsers[1] != "devops" {
311+
t.Fatalf("AuthorizedUsers = %v, want [root devops]", got.AuthorizedUsers)
312+
}
313+
if got.StackscriptID != 123 {
314+
t.Fatalf("StackscriptID = %d, want 123", got.StackscriptID)
315+
}
316+
if got.StackscriptData["foo"] != "bar" {
317+
t.Fatalf("StackscriptData = %v, want map[foo:bar]", got.StackscriptData)
318+
}
319+
}
320+
290321
func TestFlattenInstanceConfigHelpers(t *testing.T) {
291322
t.Run("Nil helpers returns nil", func(t *testing.T) {
292323
result := flattenInstanceConfigHelpers(nil)
@@ -437,10 +468,112 @@ func TestFlattenInstanceConfig(t *testing.T) {
437468
if opts.Label != tt.config.Label {
438469
t.Errorf("flattenInstanceConfig() Label = %v, want %v", opts.Label, tt.config.Label)
439470
}
471+
if opts.Comments != tt.config.Comments {
472+
t.Errorf("flattenInstanceConfig() Comments = %v, want %v", opts.Comments, tt.config.Comments)
473+
}
474+
475+
if tt.config.Devices != nil {
476+
if tt.config.Devices.SDA != nil {
477+
if opts.Devices.SDA == nil || opts.Devices.SDA.DiskID != diskLabelToID[tt.config.Devices.SDA.DiskLabel] {
478+
t.Errorf("flattenInstanceConfig() SDA = %v, want disk id %d", opts.Devices.SDA, diskLabelToID[tt.config.Devices.SDA.DiskLabel])
479+
}
480+
}
481+
if tt.config.Devices.SDB != nil {
482+
if opts.Devices.SDB == nil || opts.Devices.SDB.DiskID != diskLabelToID[tt.config.Devices.SDB.DiskLabel] {
483+
t.Errorf("flattenInstanceConfig() SDB = %v, want disk id %d", opts.Devices.SDB, diskLabelToID[tt.config.Devices.SDB.DiskLabel])
484+
}
485+
}
486+
}
487+
488+
if len(opts.Interfaces) != len(tt.config.Interfaces) {
489+
t.Errorf("flattenInstanceConfig() Interfaces length = %d, want %d", len(opts.Interfaces), len(tt.config.Interfaces))
490+
}
491+
for i := range tt.config.Interfaces {
492+
if i >= len(opts.Interfaces) {
493+
break
494+
}
495+
if opts.Interfaces[i].Purpose != linodego.ConfigInterfacePurpose(tt.config.Interfaces[i].Purpose) {
496+
t.Errorf("flattenInstanceConfig() Interfaces[%d].Purpose = %q, want %q", i, opts.Interfaces[i].Purpose, tt.config.Interfaces[i].Purpose)
497+
}
498+
if opts.Interfaces[i].Primary != tt.config.Interfaces[i].Primary {
499+
t.Errorf("flattenInstanceConfig() Interfaces[%d].Primary = %v, want %v", i, opts.Interfaces[i].Primary, tt.config.Interfaces[i].Primary)
500+
}
501+
}
502+
503+
if tt.config.RootDevice == "" {
504+
if opts.RootDevice != nil {
505+
t.Errorf("flattenInstanceConfig() RootDevice = %v, want nil", opts.RootDevice)
506+
}
507+
} else {
508+
if opts.RootDevice == nil || *opts.RootDevice != tt.config.RootDevice {
509+
t.Errorf("flattenInstanceConfig() RootDevice = %v, want %q", opts.RootDevice, tt.config.RootDevice)
510+
}
511+
}
512+
513+
if opts.MemoryLimit != tt.config.MemoryLimit || opts.Kernel != tt.config.Kernel || opts.InitRD != tt.config.InitRD || opts.RunLevel != tt.config.RunLevel || opts.VirtMode != tt.config.VirtMode {
514+
t.Errorf("flattenInstanceConfig() scalar fields mismatch: got %+v, config %+v", opts, tt.config)
515+
}
440516
})
441517
}
442518
}
443519

520+
func TestFlattenInstanceConfig_AllFields(t *testing.T) {
521+
diskLabelToID := map[string]int{"boot": 101, "swap": 202}
522+
trueVal := true
523+
cfg := InstanceConfig{
524+
Label: "cfg-all",
525+
Comments: "all fields",
526+
Devices: &InstanceConfigDevices{
527+
SDA: &InstanceConfigDevice{DiskLabel: "boot"},
528+
SDB: &InstanceConfigDevice{DiskLabel: "swap"},
529+
},
530+
Helpers: &InstanceConfigHelpers{
531+
UpdateDBDisabled: &trueVal,
532+
Distro: &trueVal,
533+
ModulesDep: &trueVal,
534+
Network: &trueVal,
535+
DevTmpFsAutomount: &trueVal,
536+
},
537+
Interfaces: []Interface{{Purpose: "public", Primary: true}},
538+
MemoryLimit: 2048,
539+
Kernel: "linode/grub2",
540+
InitRD: 44,
541+
RootDevice: "/dev/sda",
542+
RunLevel: "default",
543+
VirtMode: "paravirt",
544+
}
545+
546+
opts, err := flattenInstanceConfig(cfg, diskLabelToID)
547+
if err != nil {
548+
t.Fatalf("flattenInstanceConfig() unexpected error: %v", err)
549+
}
550+
551+
if opts.Label != cfg.Label || opts.Comments != cfg.Comments {
552+
t.Fatalf("label/comments = %q/%q, want %q/%q", opts.Label, opts.Comments, cfg.Label, cfg.Comments)
553+
}
554+
if opts.Devices.SDA == nil || opts.Devices.SDA.DiskID != 101 {
555+
t.Fatalf("SDA = %v, want DiskID 101", opts.Devices.SDA)
556+
}
557+
if opts.Devices.SDB == nil || opts.Devices.SDB.DiskID != 202 {
558+
t.Fatalf("SDB = %v, want DiskID 202", opts.Devices.SDB)
559+
}
560+
if opts.Helpers == nil || !opts.Helpers.UpdateDBDisabled || !opts.Helpers.Distro || !opts.Helpers.ModulesDep || !opts.Helpers.Network || !opts.Helpers.DevTmpFsAutomount {
561+
t.Fatalf("helpers = %+v, want all true", opts.Helpers)
562+
}
563+
if len(opts.Interfaces) != 1 {
564+
t.Fatalf("interfaces length = %d, want 1", len(opts.Interfaces))
565+
}
566+
if opts.Interfaces[0].Purpose != linodego.ConfigInterfacePurpose("public") || !opts.Interfaces[0].Primary {
567+
t.Fatalf("interface mapping = %+v, want purpose public primary true", opts.Interfaces[0])
568+
}
569+
if opts.MemoryLimit != cfg.MemoryLimit || opts.Kernel != cfg.Kernel || opts.InitRD != cfg.InitRD || opts.RunLevel != cfg.RunLevel || opts.VirtMode != cfg.VirtMode {
570+
t.Fatalf("scalar config fields not mapped correctly: %+v", opts)
571+
}
572+
if opts.RootDevice == nil || *opts.RootDevice != cfg.RootDevice {
573+
t.Fatalf("RootDevice = %v, want %q", opts.RootDevice, cfg.RootDevice)
574+
}
575+
}
576+
444577
// TestSelectBootConfig tests the boot configuration selection logic
445578
func TestSelectBootConfig(t *testing.T) {
446579
tests := []struct {

builder/linode/step_create_linode.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ func flattenVPCInterface(vpc *VPCInterface) *linodego.VPCInterfaceCreateOptions
8080
ranges := make([]linodego.VPCInterfaceIPv4RangeCreateOptions, len(vpc.IPv4.Ranges))
8181
for i, addr := range vpc.IPv4.Addresses {
8282
addresses[i] = linodego.VPCInterfaceIPv4AddressCreateOptions{
83-
Address: addr.Address,
83+
Address: addr.Address,
84+
Primary: addr.Primary,
85+
NAT1To1Address: addr.NAT1To1Address,
8486
}
8587
}
8688
for i, r := range vpc.IPv4.Ranges {

0 commit comments

Comments
 (0)