Skip to content

Commit 27686ba

Browse files
committed
Add IPv6 support for VPC interfaces in Linode builder
1 parent a61f46e commit 27686ba

7 files changed

Lines changed: 293 additions & 3 deletions

File tree

.web-docs/components/builder/linode/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ This section outlines the fields configurable for a newer Linode interface objec
275275

276276
- `ipv4` (\*VPCInterfaceIPv4) - Interfaces can be configured with IPv4 addresses or ranges.
277277

278+
- `ipv6` (\*VPCInterfaceIPv6) - IPv6 configuration for this VPC interface.
279+
278280
<!-- End of code generated from the comments of the VPCInterface struct in builder/linode/linode_interfaces.go; -->
279281

280282

@@ -330,6 +332,43 @@ This section outlines the fields configurable for a newer Linode interface objec
330332
<!-- End of code generated from the comments of the VPCInterfaceIPv4Range struct in builder/linode/linode_interfaces.go; -->
331333

332334

335+
##### VPC Linode Interface IPv6 configuration object (VPCInterfaceIPv6)
336+
337+
###### Optional
338+
339+
<!-- Code generated from the comments of the VPCInterfaceIPv6 struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->
340+
341+
- `slaac` ([]VPCInterfaceIPv6SLAAC) - IPv6 SLAAC settings for this VPC interface.
342+
343+
- `ranges` ([]VPCInterfaceIPv6Range) - IPv6 ranges for this VPC interface.
344+
345+
- `is_public` (\*bool) - Whether the IPv6 addresses are publicly routable.
346+
347+
<!-- End of code generated from the comments of the VPCInterfaceIPv6 struct in builder/linode/linode_interfaces.go; -->
348+
349+
350+
##### VPC Linode Interface IPv6 SLAAC configuration object (VPCInterfaceIPv6SLAAC)
351+
352+
###### Required
353+
354+
<!-- Code generated from the comments of the VPCInterfaceIPv6SLAAC struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->
355+
356+
- `range` (string) - The IPv6 SLAAC range for this VPC interface.
357+
358+
<!-- End of code generated from the comments of the VPCInterfaceIPv6SLAAC struct in builder/linode/linode_interfaces.go; -->
359+
360+
361+
##### VPC Linode Interface IPv6 Range configuration object (VPCInterfaceIPv6Range)
362+
363+
###### Required
364+
365+
<!-- Code generated from the comments of the VPCInterfaceIPv6Range struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->
366+
367+
- `range` (string) - The IPv6 range for this VPC interface.
368+
369+
<!-- End of code generated from the comments of the VPCInterfaceIPv6Range struct in builder/linode/linode_interfaces.go; -->
370+
371+
333372
##### VLAN Linode Interface configuration object (VLANInterface)
334373

335374
###### Required

builder/linode/builder_test.go

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,71 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
569569
t.Fatalf("unexpected error: %v", err)
570570
}
571571

572+
config["linode_interface"] = []map[string]any{
573+
{
574+
"firewall_id": 123,
575+
"default_route": map[string]any{
576+
"ipv4": true,
577+
"ipv6": true,
578+
},
579+
"public": map[string]any{
580+
"ipv4": map[string]any{
581+
"address": []map[string]any{
582+
{
583+
"address": "auto",
584+
"primary": true,
585+
},
586+
},
587+
},
588+
"ipv6": map[string]any{
589+
"ranges": []map[string]any{
590+
{
591+
"range": "/64",
592+
},
593+
},
594+
},
595+
},
596+
},
597+
{
598+
"firewall_id": 123,
599+
"default_route": map[string]any{
600+
"ipv4": false,
601+
"ipv6": false,
602+
},
603+
"vpc": map[string]any{
604+
"subnet_id": 12345,
605+
"ipv4": map[string]any{
606+
"addresses": []map[string]any{
607+
{"address": "auto", "primary": false, "nat_1_1_address": "auto"},
608+
},
609+
},
610+
"ipv6": map[string]any{
611+
"slaac": []map[string]any{
612+
{
613+
"range": "2600:3c03:e000:123::/64",
614+
},
615+
},
616+
"ranges": []map[string]any{
617+
{
618+
"range": "2600:3c03:e000:123:1::/64",
619+
},
620+
},
621+
"is_public": true,
622+
},
623+
},
624+
},
625+
{
626+
"default_route": map[string]any{
627+
"ipv4": false,
628+
"ipv6": false,
629+
},
630+
"vlan": map[string]any{
631+
"vlan_label": "vlan-1",
632+
"ipam_address": "10.0.0.1/24",
633+
},
634+
},
635+
}
636+
572637
expectedLinodeInterfaces := []LinodeInterface{
573638
{
574639
FirewallID: linodego.Pointer(123),
@@ -611,6 +676,19 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
611676
},
612677
},
613678
},
679+
IPv6: &VPCInterfaceIPv6{
680+
SLAAC: []VPCInterfaceIPv6SLAAC{
681+
{
682+
Range: "2600:3c03:e000:123::/64",
683+
},
684+
},
685+
Ranges: []VPCInterfaceIPv6Range{
686+
{
687+
Range: "2600:3c03:e000:123:1::/64",
688+
},
689+
},
690+
IsPublic: linodego.Pointer(true),
691+
},
614692
},
615693
},
616694
{
@@ -625,8 +703,6 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
625703
},
626704
}
627705

628-
// Test set
629-
config["linode_interface"] = expectedLinodeInterfaces
630706
b = Builder{}
631707
_, warnings, err = b.Prepare(config)
632708
if len(warnings) > 0 {

builder/linode/linode_interfaces.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//go:generate packer-sdc struct-markdown
2-
//go:generate packer-sdc mapstructure-to-hcl2 -type LinodeInterface,InterfaceDefaultRoute,PublicInterface,PublicInterfaceIPv4,PublicInterfaceIPv6,PublicInterfaceIPv4Address,PublicInterfaceIPv6Range,VPCInterface,VPCInterfaceIPv4,VPCInterfaceIPv4Address,VPCInterfaceIPv4Range,VLANInterface
2+
//go:generate packer-sdc mapstructure-to-hcl2 -type LinodeInterface,InterfaceDefaultRoute,PublicInterface,PublicInterfaceIPv4,PublicInterfaceIPv6,PublicInterfaceIPv4Address,PublicInterfaceIPv6Range,VPCInterface,VPCInterfaceIPv4,VPCInterfaceIPv4Address,VPCInterfaceIPv4Range,VPCInterfaceIPv6,VPCInterfaceIPv6SLAAC,VPCInterfaceIPv6Range,VLANInterface
33
package linode
44

55
type LinodeInterface struct {
@@ -79,7 +79,11 @@ type VPCInterface struct {
7979

8080
// Interfaces can be configured with IPv4 addresses or ranges.
8181
IPv4 *VPCInterfaceIPv4 `mapstructure:"ipv4" required:"false"`
82+
83+
// IPv6 configuration for this VPC interface.
84+
IPv6 *VPCInterfaceIPv6 `mapstructure:"ipv6" required:"false"`
8285
}
86+
8387
type VPCInterfaceIPv4 struct {
8488
// IPv4 address settings for this VPC interface.
8589
Addresses []VPCInterfaceIPv4Address `mapstructure:"addresses" required:"false"`
@@ -110,6 +114,27 @@ type VPCInterfaceIPv4Range struct {
110114
Range string `mapstructure:"range" required:"true"`
111115
}
112116

117+
type VPCInterfaceIPv6 struct {
118+
// IPv6 SLAAC settings for this VPC interface.
119+
SLAAC []VPCInterfaceIPv6SLAAC `mapstructure:"slaac" required:"false"`
120+
121+
// IPv6 ranges for this VPC interface.
122+
Ranges []VPCInterfaceIPv6Range `mapstructure:"ranges" required:"false"`
123+
124+
// Whether the IPv6 addresses are publicly routable.
125+
IsPublic *bool `mapstructure:"is_public" required:"false"`
126+
}
127+
128+
type VPCInterfaceIPv6SLAAC struct {
129+
// The IPv6 SLAAC range for this VPC interface.
130+
Range string `mapstructure:"range" required:"true"`
131+
}
132+
133+
type VPCInterfaceIPv6Range struct {
134+
// The IPv6 range for this VPC interface.
135+
Range string `mapstructure:"range" required:"true"`
136+
}
137+
113138
type VLANInterface struct {
114139
// The VLAN's unique label. VLAN interfaces on the same Linode must have a unique `vlan_label`.
115140
VLANLabel string `mapstructure:"vlan_label" required:"true"`

builder/linode/linode_interfaces.hcl2spec.go

Lines changed: 75 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

builder/linode/step_create_linode.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ func flattenVPCInterface(vpc *VPCInterface) *linodego.VPCInterfaceCreateOptions
9595
Ranges: linodego.Pointer(ranges),
9696
}
9797
}
98+
if vpc.IPv6 != nil {
99+
slaac := make([]linodego.VPCInterfaceIPv6SLAACCreateOptions, len(vpc.IPv6.SLAAC))
100+
ranges := make([]linodego.VPCInterfaceIPv6RangeCreateOptions, len(vpc.IPv6.Ranges))
101+
for i, s := range vpc.IPv6.SLAAC {
102+
slaac[i] = linodego.VPCInterfaceIPv6SLAACCreateOptions{
103+
Range: s.Range,
104+
}
105+
}
106+
for i, r := range vpc.IPv6.Ranges {
107+
ranges[i] = linodego.VPCInterfaceIPv6RangeCreateOptions{
108+
Range: r.Range,
109+
}
110+
}
111+
result.IPv6 = &linodego.VPCInterfaceIPv6CreateOptions{
112+
SLAAC: linodego.Pointer(slaac),
113+
Ranges: linodego.Pointer(ranges),
114+
IsPublic: vpc.IPv6.IsPublic,
115+
}
116+
}
98117
return result
99118
}
100119

builder/linode/step_create_linode_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,44 @@ func TestFlattenVPCInterface_IPv4AddressFields(t *testing.T) {
5555
}
5656
}
5757

58+
func TestFlattenVPCInterface_IPv6Fields(t *testing.T) {
59+
vpc := &VPCInterface{
60+
SubnetID: 12345,
61+
IPv6: &VPCInterfaceIPv6{
62+
SLAAC: []VPCInterfaceIPv6SLAAC{
63+
{Range: "2600:3c03:e000:123::/64"},
64+
},
65+
Ranges: []VPCInterfaceIPv6Range{
66+
{Range: "2600:3c03:e000:123:1::/64"},
67+
},
68+
IsPublic: linodego.Pointer(true),
69+
},
70+
}
71+
72+
got := flattenVPCInterface(vpc)
73+
if got == nil {
74+
t.Fatal("flattenVPCInterface() returned nil")
75+
}
76+
if got.IPv6 == nil {
77+
t.Fatal("flattenVPCInterface().IPv6 returned nil")
78+
}
79+
if got.IPv6.SLAAC == nil || len(*got.IPv6.SLAAC) != 1 {
80+
t.Fatalf("slaac = %v, want one slaac range", got.IPv6.SLAAC)
81+
}
82+
if (*got.IPv6.SLAAC)[0].Range != "2600:3c03:e000:123::/64" {
83+
t.Fatalf("slaac range = %q, want 2600:3c03:e000:123::/64", (*got.IPv6.SLAAC)[0].Range)
84+
}
85+
if got.IPv6.Ranges == nil || len(*got.IPv6.Ranges) != 1 {
86+
t.Fatalf("ranges = %v, want one ipv6 range", got.IPv6.Ranges)
87+
}
88+
if (*got.IPv6.Ranges)[0].Range != "2600:3c03:e000:123:1::/64" {
89+
t.Fatalf("range = %q, want 2600:3c03:e000:123:1::/64", (*got.IPv6.Ranges)[0].Range)
90+
}
91+
if got.IPv6.IsPublic == nil || !*got.IPv6.IsPublic {
92+
t.Fatalf("is_public = %v, want true", got.IPv6.IsPublic)
93+
}
94+
}
95+
5896
func TestFlattenConfigInterface_AllFields(t *testing.T) {
5997
vpcIP := &InterfaceIPv4{VPC: "10.0.0.2", NAT1To1: linodego.Pointer("198.51.100.2")}
6098
iface := Interface{

docs/builders/linode.mdx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,24 @@ This section outlines the fields configurable for a newer Linode interface objec
127127

128128
@include 'builder/linode/VPCInterfaceIPv4Range-required.mdx'
129129

130+
##### VPC Linode Interface IPv6 configuration object (VPCInterfaceIPv6)
131+
132+
###### Optional
133+
134+
@include 'builder/linode/VPCInterfaceIPv6-not-required.mdx'
135+
136+
##### VPC Linode Interface IPv6 SLAAC configuration object (VPCInterfaceIPv6SLAAC)
137+
138+
###### Required
139+
140+
@include 'builder/linode/VPCInterfaceIPv6SLAAC-required.mdx'
141+
142+
##### VPC Linode Interface IPv6 Range configuration object (VPCInterfaceIPv6Range)
143+
144+
###### Required
145+
146+
@include 'builder/linode/VPCInterfaceIPv6Range-required.mdx'
147+
130148
##### VLAN Linode Interface configuration object (VLANInterface)
131149

132150
###### Required

0 commit comments

Comments
 (0)