Skip to content

Commit 265d4f0

Browse files
committed
add some comments and handle network helper
1 parent 22ba316 commit 265d4f0

9 files changed

+227
-138
lines changed

api/v1alpha2/linodemachine_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ type LinodeMachineSpec struct {
5959
BackupID int `json:"backupID,omitempty"`
6060
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
6161
Image string `json:"image,omitempty"`
62+
// Interfaces is a list of legacy network interfaces to use for the instance.
6263
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
6364
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces,omitempty"`
65+
// LinodeInterfaces is a list of Linode network interfaces to use for the instance. Requires Linode Interfaces beta opt-in to use.
6466
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
6567
// +kubebuilder:object:generate=true
6668
LinodeInterfaces []LinodeInterfaceCreateOptions `json:"linodeInterfaces,omitempty"`

config/crd/bases/infrastructure.cluster.x-k8s.io_linodemachines.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ spec:
238238
- linode
239239
type: string
240240
interfaces:
241+
description: Interfaces is a list of legacy network interfaces to
242+
use for the instance.
241243
items:
242244
description: InstanceConfigInterfaceCreateOptions defines network
243245
interface config
@@ -311,6 +313,9 @@ spec:
311313
- message: Value is immutable
312314
rule: self == oldSelf
313315
linodeInterfaces:
316+
description: LinodeInterfaces is a list of Linode network interfaces
317+
to use for the instance. Requires Linode Interfaces beta opt-in
318+
to use.
314319
items:
315320
description: LinodeInterfaceCreateOptions defines the linode network
316321
interface config

config/crd/bases/infrastructure.cluster.x-k8s.io_linodemachinetemplates.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ spec:
229229
- linode
230230
type: string
231231
interfaces:
232+
description: Interfaces is a list of legacy network interfaces
233+
to use for the instance.
232234
items:
233235
description: InstanceConfigInterfaceCreateOptions defines
234236
network interface config
@@ -303,6 +305,9 @@ spec:
303305
- message: Value is immutable
304306
rule: self == oldSelf
305307
linodeInterfaces:
308+
description: LinodeInterfaces is a list of Linode network
309+
interfaces to use for the instance. Requires Linode Interfaces
310+
beta opt-in to use.
306311
items:
307312
description: LinodeInterfaceCreateOptions defines the linode
308313
network interface config

docs/src/reference/out.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,8 @@ _Appears in:_
662662
| `authorizedUsers` _string array_ | | | |
663663
| `backupID` _integer_ | | | |
664664
| `image` _string_ | | | |
665-
| `interfaces` _[InstanceConfigInterfaceCreateOptions](#instanceconfiginterfacecreateoptions) array_ | | | |
666-
| `linodeInterfaces` _[LinodeInterfaceCreateOptions](#linodeinterfacecreateoptions) array_ | | | |
665+
| `interfaces` _[InstanceConfigInterfaceCreateOptions](#instanceconfiginterfacecreateoptions) array_ | Interfaces is a list of legacy network interfaces to use for the instance. | | |
666+
| `linodeInterfaces` _[LinodeInterfaceCreateOptions](#linodeinterfacecreateoptions) array_ | LinodeInterfaces is a list of Linode network interfaces to use for the instance. Requires Linode Interfaces beta opt-in to use. | | |
667667
| `backupsEnabled` _boolean_ | | | |
668668
| `privateIP` _boolean_ | | | |
669669
| `tags` _string array_ | Tags is a list of tags to apply to the Linode instance. | | |

internal/controller/linodemachine_controller.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,18 @@ func (r *LinodeMachineReconciler) reconcilePreflightConfigure(ctx context.Contex
623623
if machineScope.LinodeMachine.Spec.Configuration != nil && machineScope.LinodeMachine.Spec.Configuration.Kernel != "" {
624624
configData.Kernel = machineScope.LinodeMachine.Spec.Configuration.Kernel
625625
}
626+
// helpers.network does not work on instances using the new linode interfaces.
626627
// For cases where the network helper is not enabled on account level, we can enable it per instance level
627628
// Default is true, so we only need to update if it's explicitly set to false
628-
if machineScope.LinodeMachine.Spec.NetworkHelper != nil {
629-
configData.Helpers = &linodego.InstanceConfigHelpers{
630-
Network: *machineScope.LinodeMachine.Spec.NetworkHelper,
629+
if machineScope.LinodeMachine.Spec.InterfaceGeneration != linodego.GenerationLinode {
630+
if machineScope.LinodeMachine.Spec.NetworkHelper != nil {
631+
configData.Helpers = &linodego.InstanceConfigHelpers{
632+
Network: *machineScope.LinodeMachine.Spec.NetworkHelper,
633+
}
634+
} else {
635+
configData.Helpers = &linodego.InstanceConfigHelpers{
636+
Network: true,
637+
}
631638
}
632639
}
633640

internal/controller/linodemachine_controller_helpers.go

Lines changed: 115 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,26 @@ func retryIfTransient(err error, logger logr.Logger) (ctrl.Result, error) {
8383
func fillCreateConfig(createConfig *linodego.InstanceCreateOptions, machineScope *scope.MachineScope) {
8484
// This will only be empty if no interfaces or linodeInterfaces were specified in the LinodeMachine spec.
8585
// In that case we default to legacy interfaces.
86-
if createConfig.InterfaceGeneration == "" {
86+
switch createConfig.InterfaceGeneration {
87+
case linodego.GenerationLinode:
88+
// networkHelper is only applicable for Linode interfaces.
89+
// legacy interfaces have nework helper configured in reconcilePreflightConfigure at the instance level.
90+
if machineScope.LinodeMachine.Spec.NetworkHelper != nil {
91+
createConfig.NetworkHelper = machineScope.LinodeMachine.Spec.NetworkHelper
92+
} else {
93+
createConfig.NetworkHelper = ptr.To(true)
94+
}
95+
case linodego.GenerationLegacyConfig:
96+
createConfig.InterfaceGeneration = linodego.GenerationLegacyConfig
97+
default:
8798
createConfig.InterfaceGeneration = linodego.GenerationLegacyConfig
8899
}
100+
89101
if machineScope.LinodeMachine.Spec.PrivateIP != nil {
90102
createConfig.PrivateIP = *machineScope.LinodeMachine.Spec.PrivateIP
91-
} else {
92-
if createConfig.InterfaceGeneration == linodego.GenerationLegacyConfig {
93-
// Supported only for legacy network interfaces.
94-
createConfig.PrivateIP = true
95-
} else {
96-
// Network Helper is not supported for the new network interfaces.
97-
createConfig.NetworkHelper = nil
98-
}
103+
} else if createConfig.InterfaceGeneration != linodego.GenerationLinode {
104+
// Supported only for legacy network interfaces.
105+
createConfig.PrivateIP = true
99106
}
100107

101108
if createConfig.Tags == nil {
@@ -631,7 +638,7 @@ func getVPCLinodeInterfaceConfig(ctx context.Context, machineScope *scope.Machin
631638
for _, subnet := range linodeVPC.Spec.Subnets {
632639
if subnet.Label == subnetName {
633640
subnetID = subnet.SubnetID
634-
ipv6Config = getVPCInterfaceIPv6Config(machineScope, len(subnet.IPv6))
641+
ipv6Config = getVPCLinodeInterfaceIPv6Config(machineScope, len(subnet.IPv6))
635642
break
636643
}
637644
}
@@ -641,7 +648,7 @@ func getVPCLinodeInterfaceConfig(ctx context.Context, machineScope *scope.Machin
641648
}
642649
} else {
643650
subnetID = linodeVPC.Spec.Subnets[0].SubnetID // get first subnet if nothing specified
644-
ipv6Config = getVPCInterfaceIPv6Config(machineScope, len(linodeVPC.Spec.Subnets[0].IPv6))
651+
ipv6Config = getVPCLinodeInterfaceIPv6Config(machineScope, len(linodeVPC.Spec.Subnets[0].IPv6))
645652
}
646653

647654
if subnetID == 0 {
@@ -656,15 +663,6 @@ func getVPCLinodeInterfaceConfig(ctx context.Context, machineScope *scope.Machin
656663
if !isVPCInterfaceIPv6ConfigEmpty(ipv6Config) {
657664
linodeInterfaces[iface].VPC.IPv6 = ipv6Config
658665
}
659-
if netInterface.VPC.IPv4 == nil {
660-
linodeInterfaces[iface].VPC.IPv4 = &linodego.VPCInterfaceIPv4CreateOptions{
661-
Addresses: []linodego.VPCInterfaceIPv4AddressCreateOptions{{
662-
Primary: ptr.To(true),
663-
NAT1To1Address: ptr.To("auto"),
664-
Address: "auto",
665-
}},
666-
}
667-
}
668666
return nil, nil //nolint:nilnil // it is important we don't return an interface if a VPC interface already exists
669667
}
670668
}
@@ -731,7 +729,7 @@ func getVPCLinodeInterfaceConfigFromDirectID(ctx context.Context, machineScope *
731729
for _, subnet := range vpc.Subnets {
732730
if subnet.Label == subnetName {
733731
subnetID = subnet.ID
734-
ipv6Config = getVPCInterfaceIPv6Config(machineScope, len(subnet.IPv6))
732+
ipv6Config = getVPCLinodeInterfaceIPv6Config(machineScope, len(subnet.IPv6))
735733
break
736734
}
737735
}
@@ -740,7 +738,7 @@ func getVPCLinodeInterfaceConfigFromDirectID(ctx context.Context, machineScope *
740738
}
741739
} else {
742740
subnetID = vpc.Subnets[0].ID
743-
ipv6Config = getVPCInterfaceIPv6Config(machineScope, len(vpc.Subnets[0].IPv6))
741+
ipv6Config = getVPCLinodeInterfaceIPv6Config(machineScope, len(vpc.Subnets[0].IPv6))
744742
}
745743

746744
// Check if a VPC interface already exists
@@ -762,6 +760,7 @@ func getVPCLinodeInterfaceConfigFromDirectID(ctx context.Context, machineScope *
762760
Addresses: []linodego.VPCInterfaceIPv4AddressCreateOptions{{
763761
Primary: ptr.To(true),
764762
NAT1To1Address: ptr.To("auto"),
763+
Address: "auto",
765764
}},
766765
},
767766
},
@@ -890,12 +889,12 @@ func getMachineIPv6Config(machineScope *scope.MachineScope, numIPv6RangesInSubne
890889
return intfOpts
891890
}
892891

893-
// getVPCInterfaceIPv6Config returns the IPv6 configuration for a LinodeMachine.
892+
// getVPCLinodeInterfaceIPv6Config returns the IPv6 configuration for a LinodeMachine.
894893
// It checks the LinodeMachine's IPv6Options for SLAAC and Ranges settings.
895894
// If `EnableSLAAC` is set, it will enable SLAAC with the default IPv6 CIDR range.
896895
// If `EnableRanges` is set, it will enable IPv6 ranges with the default IPv6 CIDR range.
897896
// If `IsPublicIPv6` is set, it will be used to determine if the IPv6 range should be publicly routable or not.
898-
func getVPCInterfaceIPv6Config(machineScope *scope.MachineScope, numIPv6RangesInSubnet int) *linodego.VPCInterfaceIPv6CreateOptions {
897+
func getVPCLinodeInterfaceIPv6Config(machineScope *scope.MachineScope, numIPv6RangesInSubnet int) *linodego.VPCInterfaceIPv6CreateOptions {
899898
intfOpts := &linodego.VPCInterfaceIPv6CreateOptions{}
900899

901900
// If there are no IPv6 ranges in the subnet or if IPv6 options are not specified, return nil.
@@ -928,8 +927,6 @@ func getVPCInterfaceIPv6Config(machineScope *scope.MachineScope, numIPv6RangesIn
928927

929928
// Unfortunately, this is necessary since DeepCopy can't be generated for linodego.LinodeInterfaceCreateOptions
930929
// so here we manually create the options for Linode interfaces.
931-
//
932-
//nolint:gocognit,cyclop,gocritic,nestif,nolintlint // Also, unfortunately, this cannot be made any reasonably simpler with how complicated the linodego struct is
933930
func constructLinodeInterfaceCreateOpts(createOpts []infrav1alpha2.LinodeInterfaceCreateOptions) []linodego.LinodeInterfaceCreateOptions {
934931
linodeInterfaces := make([]linodego.LinodeInterfaceCreateOptions, len(createOpts))
935932
for idx, iface := range createOpts {
@@ -943,91 +940,11 @@ func constructLinodeInterfaceCreateOpts(createOpts []infrav1alpha2.LinodeInterfa
943940
}
944941
// Handle VPC
945942
if iface.VPC != nil {
946-
var (
947-
ipv4Addrs []linodego.VPCInterfaceIPv4AddressCreateOptions
948-
ipv4Ranges []linodego.VPCInterfaceIPv4RangeCreateOptions
949-
ipv6Ranges []linodego.VPCInterfaceIPv6RangeCreateOptions
950-
ipv6SLAAC []linodego.VPCInterfaceIPv6SLAACCreateOptions
951-
ipv6IsPublic bool
952-
)
953-
if iface.VPC.IPv4 != nil {
954-
for _, addr := range iface.VPC.IPv4.Addresses {
955-
ipv4Addrs = append(ipv4Addrs, linodego.VPCInterfaceIPv4AddressCreateOptions{
956-
Address: addr.Address,
957-
Primary: addr.Primary,
958-
NAT1To1Address: addr.NAT1To1Address,
959-
})
960-
}
961-
for _, rng := range iface.VPC.IPv4.Ranges {
962-
ipv4Ranges = append(ipv4Ranges, linodego.VPCInterfaceIPv4RangeCreateOptions{
963-
Range: rng.Range,
964-
})
965-
}
966-
} else {
967-
// If no IPv4 addresses are specified, we set a default NAT1To1 address to "any"
968-
ipv4Addrs = []linodego.VPCInterfaceIPv4AddressCreateOptions{
969-
{
970-
Primary: ptr.To(true),
971-
NAT1To1Address: ptr.To("auto"),
972-
Address: "auto", // Default to auto-assigned address
973-
},
974-
}
975-
}
976-
if iface.VPC.IPv6 != nil {
977-
for _, slaac := range iface.VPC.IPv6.SLAAC {
978-
ipv6SLAAC = append(ipv6SLAAC, linodego.VPCInterfaceIPv6SLAACCreateOptions{
979-
Range: slaac.Range,
980-
})
981-
}
982-
for _, rng := range iface.VPC.IPv6.Ranges {
983-
ipv6Ranges = append(ipv6Ranges, linodego.VPCInterfaceIPv6RangeCreateOptions{
984-
Range: rng.Range,
985-
})
986-
}
987-
ipv6IsPublic = iface.VPC.IPv6.IsPublic
988-
}
989-
ifaceCreateOpts.VPC = &linodego.VPCInterfaceCreateOptions{
990-
SubnetID: iface.VPC.SubnetID,
991-
IPv4: &linodego.VPCInterfaceIPv4CreateOptions{
992-
Addresses: ipv4Addrs,
993-
Ranges: ipv4Ranges,
994-
},
995-
IPv6: &linodego.VPCInterfaceIPv6CreateOptions{
996-
SLAAC: ipv6SLAAC,
997-
Ranges: ipv6Ranges,
998-
IsPublic: ipv6IsPublic,
999-
},
1000-
}
943+
ifaceCreateOpts.VPC = constructLinodeInterfaceVPC(iface)
1001944
}
1002945
// Handle Public Interface
1003946
if iface.Public != nil {
1004-
var (
1005-
ipv4Addrs []linodego.PublicInterfaceIPv4AddressCreateOptions
1006-
ipv6Ranges []linodego.PublicInterfaceIPv6RangeCreateOptions
1007-
)
1008-
if iface.Public.IPv4 != nil {
1009-
for _, addr := range iface.Public.IPv4.Addresses {
1010-
ipv4Addrs = append(ipv4Addrs, linodego.PublicInterfaceIPv4AddressCreateOptions{
1011-
Address: addr.Address,
1012-
Primary: addr.Primary,
1013-
})
1014-
}
1015-
}
1016-
if iface.Public.IPv6 != nil {
1017-
for _, rng := range iface.Public.IPv6.Ranges {
1018-
ipv6Ranges = append(ipv6Ranges, linodego.PublicInterfaceIPv6RangeCreateOptions{
1019-
Range: rng.Range,
1020-
})
1021-
}
1022-
}
1023-
ifaceCreateOpts.Public = &linodego.PublicInterfaceCreateOptions{
1024-
IPv4: &linodego.PublicInterfaceIPv4CreateOptions{
1025-
Addresses: ipv4Addrs,
1026-
},
1027-
IPv6: &linodego.PublicInterfaceIPv6CreateOptions{
1028-
Ranges: ipv6Ranges,
1029-
},
1030-
}
947+
ifaceCreateOpts.Public = constructLinodeInterfacePublic(iface)
1031948
}
1032949
// Handle Default Route
1033950
if iface.DefaultRoute != nil {
@@ -1044,6 +961,96 @@ func constructLinodeInterfaceCreateOpts(createOpts []infrav1alpha2.LinodeInterfa
1044961
return linodeInterfaces
1045962
}
1046963

964+
// constructLinodeInterfaceVPC constructs a Linode VPC interface configuration from the provided LinodeInterfaceCreateOptions.
965+
func constructLinodeInterfaceVPC(iface infrav1alpha2.LinodeInterfaceCreateOptions) *linodego.VPCInterfaceCreateOptions {
966+
var (
967+
ipv4Addrs []linodego.VPCInterfaceIPv4AddressCreateOptions
968+
ipv4Ranges []linodego.VPCInterfaceIPv4RangeCreateOptions
969+
ipv6Ranges []linodego.VPCInterfaceIPv6RangeCreateOptions
970+
ipv6SLAAC []linodego.VPCInterfaceIPv6SLAACCreateOptions
971+
ipv6IsPublic bool
972+
)
973+
if iface.VPC.IPv4 != nil {
974+
for _, addr := range iface.VPC.IPv4.Addresses {
975+
ipv4Addrs = append(ipv4Addrs, linodego.VPCInterfaceIPv4AddressCreateOptions{
976+
Address: addr.Address,
977+
Primary: addr.Primary,
978+
NAT1To1Address: addr.NAT1To1Address,
979+
})
980+
}
981+
for _, rng := range iface.VPC.IPv4.Ranges {
982+
ipv4Ranges = append(ipv4Ranges, linodego.VPCInterfaceIPv4RangeCreateOptions{
983+
Range: rng.Range,
984+
})
985+
}
986+
} else {
987+
// If no IPv4 addresses are specified, we set a default NAT1To1 address to "any"
988+
ipv4Addrs = []linodego.VPCInterfaceIPv4AddressCreateOptions{
989+
{
990+
Primary: ptr.To(true),
991+
NAT1To1Address: ptr.To("auto"),
992+
Address: "auto", // Default to auto-assigned address
993+
},
994+
}
995+
}
996+
if iface.VPC.IPv6 != nil {
997+
for _, slaac := range iface.VPC.IPv6.SLAAC {
998+
ipv6SLAAC = append(ipv6SLAAC, linodego.VPCInterfaceIPv6SLAACCreateOptions{
999+
Range: slaac.Range,
1000+
})
1001+
}
1002+
for _, rng := range iface.VPC.IPv6.Ranges {
1003+
ipv6Ranges = append(ipv6Ranges, linodego.VPCInterfaceIPv6RangeCreateOptions{
1004+
Range: rng.Range,
1005+
})
1006+
}
1007+
ipv6IsPublic = iface.VPC.IPv6.IsPublic
1008+
}
1009+
return &linodego.VPCInterfaceCreateOptions{
1010+
SubnetID: iface.VPC.SubnetID,
1011+
IPv4: &linodego.VPCInterfaceIPv4CreateOptions{
1012+
Addresses: ipv4Addrs,
1013+
Ranges: ipv4Ranges,
1014+
},
1015+
IPv6: &linodego.VPCInterfaceIPv6CreateOptions{
1016+
SLAAC: ipv6SLAAC,
1017+
Ranges: ipv6Ranges,
1018+
IsPublic: ipv6IsPublic,
1019+
},
1020+
}
1021+
}
1022+
1023+
// constructLinodeInterfacePublic constructs a Linode Public interface configuration from the provided LinodeInterfaceCreateOptions.
1024+
func constructLinodeInterfacePublic(iface infrav1alpha2.LinodeInterfaceCreateOptions) *linodego.PublicInterfaceCreateOptions {
1025+
var (
1026+
ipv4Addrs []linodego.PublicInterfaceIPv4AddressCreateOptions
1027+
ipv6Ranges []linodego.PublicInterfaceIPv6RangeCreateOptions
1028+
)
1029+
if iface.Public.IPv4 != nil {
1030+
for _, addr := range iface.Public.IPv4.Addresses {
1031+
ipv4Addrs = append(ipv4Addrs, linodego.PublicInterfaceIPv4AddressCreateOptions{
1032+
Address: addr.Address,
1033+
Primary: addr.Primary,
1034+
})
1035+
}
1036+
}
1037+
if iface.Public.IPv6 != nil {
1038+
for _, rng := range iface.Public.IPv6.Ranges {
1039+
ipv6Ranges = append(ipv6Ranges, linodego.PublicInterfaceIPv6RangeCreateOptions{
1040+
Range: rng.Range,
1041+
})
1042+
}
1043+
}
1044+
return &linodego.PublicInterfaceCreateOptions{
1045+
IPv4: &linodego.PublicInterfaceIPv4CreateOptions{
1046+
Addresses: ipv4Addrs,
1047+
},
1048+
IPv6: &linodego.PublicInterfaceIPv6CreateOptions{
1049+
Ranges: ipv6Ranges,
1050+
},
1051+
}
1052+
}
1053+
10471054
// For converting LinodeMachineSpec to linodego.InstanceCreateOptions. Any defaulting should be done in fillCreateConfig instead
10481055
func linodeMachineSpecToInstanceCreateConfig(machineSpec infrav1alpha2.LinodeMachineSpec, machineTags []string) *linodego.InstanceCreateOptions {
10491056
instCreateOpts := &linodego.InstanceCreateOptions{

0 commit comments

Comments
 (0)