Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion .web-docs/components/builder/linode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ can also be supplied to override the typical auto-generated key:
for more information on the Images available for use. Examples are `linode/debian12`,
`linode/debian13`, `linode/ubuntu24.04`, `linode/arch`, and `private/12345`.

- `swap_size` (int) - The disk size (MiB) allocated for swap space.
- `swap_size` (\*int) - The disk size (MiB) allocated for swap space.

- `private_ip` (bool) - If true, the created Linode will have private networking enabled and assigned
a private IPv4 address.
Expand Down Expand Up @@ -275,6 +275,8 @@ This section outlines the fields configurable for a newer Linode interface objec

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

- `ipv6` (\*VPCInterfaceIPv6) - IPv6 configuration for this VPC interface.

<!-- End of code generated from the comments of the VPCInterface struct in builder/linode/linode_interfaces.go; -->


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


##### VPC Linode Interface IPv6 configuration object (VPCInterfaceIPv6)

###### Optional

<!-- Code generated from the comments of the VPCInterfaceIPv6 struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->

- `slaac` ([]VPCInterfaceIPv6SLAAC) - IPv6 SLAAC settings for this VPC interface.

- `ranges` ([]VPCInterfaceIPv6Range) - IPv6 ranges for this VPC interface.

- `is_public` (\*bool) - Whether the IPv6 addresses are publicly routable.

<!-- End of code generated from the comments of the VPCInterfaceIPv6 struct in builder/linode/linode_interfaces.go; -->


##### VPC Linode Interface IPv6 SLAAC configuration object (VPCInterfaceIPv6SLAAC)

###### Required

<!-- Code generated from the comments of the VPCInterfaceIPv6SLAAC struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->

- `range` (string) - The IPv6 SLAAC range for this VPC interface.

<!-- End of code generated from the comments of the VPCInterfaceIPv6SLAAC struct in builder/linode/linode_interfaces.go; -->


##### VPC Linode Interface IPv6 Range configuration object (VPCInterfaceIPv6Range)

###### Required

<!-- Code generated from the comments of the VPCInterfaceIPv6Range struct in builder/linode/linode_interfaces.go; DO NOT EDIT MANUALLY -->

- `range` (string) - The IPv6 range for this VPC interface.

<!-- End of code generated from the comments of the VPCInterfaceIPv6Range struct in builder/linode/linode_interfaces.go; -->


##### VLAN Linode Interface configuration object (VLANInterface)

###### Required
Expand Down
139 changes: 137 additions & 2 deletions builder/linode/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,44 @@ func TestBuilderPrepare_Size(t *testing.T) {
}
}

func TestBuilderPrepare_SwapSize(t *testing.T) {
t.Run("omitted remains nil", func(t *testing.T) {
var b Builder
config := testConfig()
delete(config, "swap_size")

_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

if b.config.SwapSize != nil {
t.Fatalf("swap_size = %v, want nil", b.config.SwapSize)
}
})

t.Run("explicit zero remains non-nil", func(t *testing.T) {
var b Builder
config := testConfig()
config["swap_size"] = 0

_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

if b.config.SwapSize == nil || *b.config.SwapSize != 0 {
t.Fatalf("swap_size = %v, want pointer to 0", b.config.SwapSize)
}
})
}

func TestBuilderPrepare_Image(t *testing.T) {
var b Builder
config := testConfig()
Expand Down Expand Up @@ -531,6 +569,71 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}

config["linode_interface"] = []map[string]any{
{
"firewall_id": 123,
"default_route": map[string]any{
"ipv4": true,
"ipv6": true,
},
"public": map[string]any{
"ipv4": map[string]any{
"address": []map[string]any{
{
"address": "auto",
"primary": true,
},
},
},
"ipv6": map[string]any{
"ranges": []map[string]any{
{
"range": "/64",
},
},
},
},
},
{
"firewall_id": 123,
"default_route": map[string]any{
"ipv4": false,
"ipv6": false,
},
"vpc": map[string]any{
"subnet_id": 12345,
"ipv4": map[string]any{
"addresses": []map[string]any{
{"address": "auto", "primary": false, "nat_1_1_address": "auto"},
},
},
"ipv6": map[string]any{
"slaac": []map[string]any{
{
"range": "2600:3c03:e000:123::/64",
},
},
"ranges": []map[string]any{
{
"range": "2600:3c03:e000:123:1::/64",
},
},
"is_public": true,
},
},
},
{
"default_route": map[string]any{
"ipv4": false,
"ipv6": false,
},
"vlan": map[string]any{
"vlan_label": "vlan-1",
"ipam_address": "10.0.0.1/24",
},
},
}

expectedLinodeInterfaces := []LinodeInterface{
{
FirewallID: linodego.Pointer(123),
Expand Down Expand Up @@ -573,6 +676,19 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
},
},
},
IPv6: &VPCInterfaceIPv6{
SLAAC: []VPCInterfaceIPv6SLAAC{
{
Range: "2600:3c03:e000:123::/64",
},
},
Ranges: []VPCInterfaceIPv6Range{
{
Range: "2600:3c03:e000:123:1::/64",
},
},
IsPublic: linodego.Pointer(true),
},
},
},
{
Expand All @@ -587,8 +703,6 @@ func TestBuilderPrepare_LinodeNetworkInterfaces(t *testing.T) {
},
}

// Test set
config["linode_interface"] = expectedLinodeInterfaces
b = Builder{}
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
Expand Down Expand Up @@ -989,6 +1103,27 @@ func TestBuilderPrepare_CustomDisksValidation(t *testing.T) {
}
})

t.Run("IncompatibleSwapSizeZero", func(t *testing.T) {
var b Builder
config := testConfig()
delete(config, "image")
config["swap_size"] = 0
config["disk"] = []map[string]any{
{"label": "boot", "size": 25000, "image": "linode/arch"},
}
config["config"] = []map[string]any{
{"label": "my-config"},
}

_, _, err := b.Prepare(config)
if err == nil {
t.Fatal("expected error with swap_size=0 and custom disks")
}
if !strings.Contains(err.Error(), "swap_size cannot be specified when using custom disks") {
t.Fatalf("expected specific error message, got: %s", err)
}
})

t.Run("IncompatibleStackScriptID", func(t *testing.T) {
var b Builder
config := testConfig()
Expand Down
4 changes: 2 additions & 2 deletions builder/linode/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ type Config struct {
Image string `mapstructure:"image" required:"false"`

// The disk size (MiB) allocated for swap space.
SwapSize int `mapstructure:"swap_size" required:"false"`
SwapSize *int `mapstructure:"swap_size" required:"false"`

// If true, the created Linode will have private networking enabled and assigned
// a private IPv4 address.
Expand Down Expand Up @@ -720,7 +720,7 @@ func (c *Config) Prepare(raws ...any) ([]string, error) {
errs, errors.New("authorized_users cannot be specified when using custom disks (specify in disk blocks instead)"))
}

if c.SwapSize > 0 {
if c.SwapSize != nil {
errs = packersdk.MultiErrorAppend(
errs, errors.New("swap_size cannot be specified when using custom disks (create a swap disk instead)"))
}
Expand Down
27 changes: 26 additions & 1 deletion builder/linode/linode_interfaces.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type LinodeInterface,InterfaceDefaultRoute,PublicInterface,PublicInterfaceIPv4,PublicInterfaceIPv6,PublicInterfaceIPv4Address,PublicInterfaceIPv6Range,VPCInterface,VPCInterfaceIPv4,VPCInterfaceIPv4Address,VPCInterfaceIPv4Range,VLANInterface
//go:generate packer-sdc mapstructure-to-hcl2 -type LinodeInterface,InterfaceDefaultRoute,PublicInterface,PublicInterfaceIPv4,PublicInterfaceIPv6,PublicInterfaceIPv4Address,PublicInterfaceIPv6Range,VPCInterface,VPCInterfaceIPv4,VPCInterfaceIPv4Address,VPCInterfaceIPv4Range,VPCInterfaceIPv6,VPCInterfaceIPv6SLAAC,VPCInterfaceIPv6Range,VLANInterface
package linode

type LinodeInterface struct {
Expand Down Expand Up @@ -79,7 +79,11 @@ type VPCInterface struct {

// Interfaces can be configured with IPv4 addresses or ranges.
IPv4 *VPCInterfaceIPv4 `mapstructure:"ipv4" required:"false"`

// IPv6 configuration for this VPC interface.
IPv6 *VPCInterfaceIPv6 `mapstructure:"ipv6" required:"false"`
}

type VPCInterfaceIPv4 struct {
// IPv4 address settings for this VPC interface.
Addresses []VPCInterfaceIPv4Address `mapstructure:"addresses" required:"false"`
Expand Down Expand Up @@ -110,6 +114,27 @@ type VPCInterfaceIPv4Range struct {
Range string `mapstructure:"range" required:"true"`
}

type VPCInterfaceIPv6 struct {
// IPv6 SLAAC settings for this VPC interface.
SLAAC []VPCInterfaceIPv6SLAAC `mapstructure:"slaac" required:"false"`

// IPv6 ranges for this VPC interface.
Ranges []VPCInterfaceIPv6Range `mapstructure:"ranges" required:"false"`

// Whether the IPv6 addresses are publicly routable.
IsPublic *bool `mapstructure:"is_public" required:"false"`
}

type VPCInterfaceIPv6SLAAC struct {
// The IPv6 SLAAC range for this VPC interface.
Range string `mapstructure:"range" required:"true"`
}

type VPCInterfaceIPv6Range struct {
// The IPv6 range for this VPC interface.
Range string `mapstructure:"range" required:"true"`
}

type VLANInterface struct {
// The VLAN's unique label. VLAN interfaces on the same Linode must have a unique `vlan_label`.
VLANLabel string `mapstructure:"vlan_label" required:"true"`
Expand Down
75 changes: 75 additions & 0 deletions builder/linode/linode_interfaces.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading