Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] VLAN support for CAPL clusters #525

Merged
merged 30 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f1962fa
Initial groundwork for VLAN controller
tchinmai7 Sep 27, 2024
1a3ebb7
call auto generated one
tchinmai7 Sep 27, 2024
3d23699
preflight stuff
tchinmai7 Sep 28, 2024
ca234c0
move to networkspec
tchinmai7 Sep 30, 2024
d70ff4a
add kubebuilder annotations
tchinmai7 Sep 30, 2024
8e6245f
Add list permissions
tchinmai7 Sep 30, 2024
4e0bb74
fixups
tchinmai7 Sep 30, 2024
11e3c26
fixups
tchinmai7 Sep 30, 2024
14bb6c1
Add delete perms
tchinmai7 Oct 1, 2024
62058c0
bump ccm to 4.16, add a vlan rke2 flavor
tchinmai7 Oct 2, 2024
c37b625
fixups
tchinmai7 Oct 2, 2024
acfce6d
add some tests
tchinmai7 Oct 2, 2024
a48857f
tests for vlan delete
tchinmai7 Oct 2, 2024
69e345d
fixup
tchinmai7 Oct 2, 2024
e145140
Merge branch 'main' into add-vlan-spec
tchinmai7 Oct 2, 2024
789d49b
lint fix
tchinmai7 Oct 3, 2024
d62b229
fix validator
tchinmai7 Oct 3, 2024
e77147d
lint fix for real
tchinmai7 Oct 3, 2024
f1cd17b
suggestions from review
tchinmai7 Oct 3, 2024
82de6a2
fix template
tchinmai7 Oct 3, 2024
f6ecb55
simplify
tchinmai7 Oct 3, 2024
a366ba7
base flavor on default
tchinmai7 Oct 3, 2024
171a0c9
Merge branch 'main' into add-vlan-spec
tchinmai7 Oct 3, 2024
a8879f4
use a global map instead of a configmap'
tchinmai7 Oct 3, 2024
71b6180
remove code
tchinmai7 Oct 3, 2024
5e6b217
add vlan helpers
tchinmai7 Oct 3, 2024
24a121a
get rid of error
tchinmai7 Oct 3, 2024
c9e8983
Merge branch 'main' into add-vlan-spec
tchinmai7 Oct 4, 2024
392b7e8
add tests and a per cluster lock
tchinmai7 Oct 4, 2024
00c3dc3
Update api/v1alpha2/linodecluster_types.go
tchinmai7 Oct 7, 2024
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
5 changes: 5 additions & 0 deletions api/v1alpha1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,8 @@ func Convert_v1alpha2_LinodeObjectStorageBucket_To_v1alpha1_LinodeObjectStorageB
}
return autoConvert_v1alpha2_LinodeObjectStorageBucket_To_v1alpha1_LinodeObjectStorageBucket(in, out, scope)
}

func Convert_v1alpha2_LinodeClusterSpec_To_v1alpha1_LinodeClusterSpec(in *infrastructurev1alpha2.LinodeClusterSpec, out *LinodeClusterSpec, scope conversion.Scope) error {
// VLAN is not supported in v1alpha1
return autoConvert_v1alpha2_LinodeClusterSpec_To_v1alpha1_LinodeClusterSpec(in, out, scope)
}
16 changes: 6 additions & 10 deletions api/v1alpha1/zz_generated.conversion.go

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

5 changes: 5 additions & 0 deletions api/v1alpha2/linodecluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ type NetworkSpec struct {
// additionalPorts contains list of ports to be configured with NodeBalancer.
// +optional
AdditionalPorts []LinodeNBPortConfig `json:"additionalPorts,omitempty"`

// UseVlan provisions a cluster that uses VLANs instead of VPCs. IPAM is managed internally.
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +optional
UseVlan bool `json:"useVlan"`
tchinmai7 marked this conversation as resolved.
Show resolved Hide resolved
}

type LinodeNBPortConfig struct {
Expand Down
7 changes: 7 additions & 0 deletions api/v1alpha2/linodecluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@
}
}

if r.Spec.Network.UseVlan && r.Spec.VPCRef != nil {
errs = append(errs, &field.Error{
Field: "Cannot use VLANs and VPCs together. Unset `network.useVlan` or remove `vpcRef`",
Type: field.ErrorTypeInvalid,
})

Check warning on line 113 in api/v1alpha2/linodecluster_webhook.go

View check run for this annotation

Codecov / codecov/patch

api/v1alpha2/linodecluster_webhook.go#L110-L113

Added lines #L110 - L113 were not covered by tests
}

if len(errs) == 0 {
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,13 @@ spec:
nodeBalancerID:
description: NodeBalancerID is the id of NodeBalancer.
type: integer
useVlan:
description: UseVlan provisions a cluster that uses VLANs instead
of VPCs. IPAM is managed internally.
type: boolean
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
type: object
region:
description: The Linode Region the LinodeCluster lives in.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,13 @@ spec:
nodeBalancerID:
description: NodeBalancerID is the id of NodeBalancer.
type: integer
useVlan:
description: UseVlan provisions a cluster that uses VLANs
instead of VPCs. IPAM is managed internally.
type: boolean
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
type: object
region:
description: The Linode Region the LinodeCluster lives in.
Expand Down
11 changes: 11 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ kind: ClusterRole
metadata:
name: manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
Expand Down
14 changes: 14 additions & 0 deletions controller/linodecluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
return nil
}

func (r *LinodeClusterReconciler) reconcileDelete(ctx context.Context, logger logr.Logger, clusterScope *scope.ClusterScope) error {

Check failure on line 223 in controller/linodecluster_controller.go

View workflow job for this annotation

GitHub Actions / go-analyze

calculated cyclomatic complexity for function reconcileDelete is 19, max is 15 (cyclop)
logger.Info("deleting cluster")
switch {
case clusterScope.LinodeCluster.Spec.Network.LoadBalancerType == "external":
Expand Down Expand Up @@ -262,6 +262,20 @@
return errors.New("waiting for associated LinodeMachine objects to be deleted")
}

if clusterScope.LinodeCluster.Spec.Network.UseVlan {
var ipsMap corev1.ConfigMap
err := clusterScope.Client.Get(ctx, client.ObjectKey{Namespace: clusterScope.Cluster.Namespace, Name: fmt.Sprintf("%s-ips", clusterScope.Cluster.Name)}, &ipsMap)
if err != nil && !apierrors.IsNotFound(err) {
logger.Error(err, "failed to get ips configmap")
return err

Check warning on line 270 in controller/linodecluster_controller.go

View check run for this annotation

Codecov / codecov/patch

controller/linodecluster_controller.go#L266-L270

Added lines #L266 - L270 were not covered by tests
}
err = clusterScope.Client.Delete(ctx, &ipsMap)
if err != nil && !apierrors.IsNotFound(err) {
logger.Error(err, "failed to delete ips configmap")
return err

Check warning on line 275 in controller/linodecluster_controller.go

View check run for this annotation

Codecov / codecov/patch

controller/linodecluster_controller.go#L272-L275

Added lines #L272 - L275 were not covered by tests
}
}

if err := clusterScope.RemoveCredentialsRefFinalizer(ctx); err != nil {
logger.Error(err, "failed to remove credentials finalizer")
setFailureReason(clusterScope, cerrs.DeleteClusterError, err, r)
Expand Down
1 change: 1 addition & 0 deletions controller/linodemachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ type LinodeMachineReconciler struct {
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines,verbs=get;watch;list
// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps;,verbs=get;watch;list;create;update;patch
AshleyDumaine marked this conversation as resolved.
Show resolved Hide resolved

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
163 changes: 142 additions & 21 deletions controller/linodemachine_controller_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@
"errors"
"fmt"
"net/http"
"net/netip"
"slices"
"sort"

"github.com/go-logr/logr"
"github.com/google/uuid"
"github.com/linode/linodego"
"golang.org/x/exp/maps"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
cerrs "sigs.k8s.io/cluster-api/errors"
Expand All @@ -51,7 +55,11 @@

// Size limit in bytes on the decoded metadata.user_data for cloud-init
// The decoded user_data must not exceed 16384 bytes per the Linode API
const maxBootstrapDataBytes = 16384
const (
maxBootstrapDataBytes = 16384
vlanIPRange = "10.0.0.0/8"
vlanIPFormat = "%s/11"
)

var (
errNoPublicIPv4Addrs = errors.New("no public ipv4 addresses set")
Expand Down Expand Up @@ -80,24 +88,7 @@
return ctrl.Result{}, err
}

func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, logger logr.Logger) (*linodego.InstanceCreateOptions, error) {
var err error

createConfig := linodeMachineSpecToInstanceCreateConfig(machineScope.LinodeMachine.Spec)
if createConfig == nil {
err = errors.New("failed to convert machine spec to create instance config")

logger.Error(err, "Panic! Struct of LinodeMachineSpec is different than InstanceCreateOptions")

return nil, err
}

createConfig.Booted = util.Pointer(false)

if err := setUserData(ctx, machineScope, createConfig, logger); err != nil {
return nil, err
}

func fillCreateConfig(createConfig *linodego.InstanceCreateOptions, machineScope *scope.MachineScope) {
if machineScope.LinodeMachine.Spec.PrivateIP != nil {
createConfig.PrivateIP = *machineScope.LinodeMachine.Spec.PrivateIP
} else {
Expand All @@ -119,8 +110,28 @@
if createConfig.RootPass == "" {
createConfig.RootPass = uuid.NewString()
}
}

func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, logger logr.Logger) (*linodego.InstanceCreateOptions, error) {
var err error

createConfig := linodeMachineSpecToInstanceCreateConfig(machineScope.LinodeMachine.Spec)
if createConfig == nil {
err = errors.New("failed to convert machine spec to create instance config")

Check warning on line 120 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L120

Added line #L120 was not covered by tests

logger.Error(err, "Panic! Struct of LinodeMachineSpec is different than InstanceCreateOptions")

Check warning on line 122 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L122

Added line #L122 was not covered by tests

return nil, err

Check warning on line 124 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L124

Added line #L124 was not covered by tests
}

// if vpc, attach additional interface as eth0 to linode
createConfig.Booted = util.Pointer(false)
if err := setUserData(ctx, machineScope, createConfig, logger); err != nil {
return nil, err
}

fillCreateConfig(createConfig, machineScope)

// if vpc is enabled, attach additional interface as eth0 to linode
if machineScope.LinodeCluster.Spec.VPCRef != nil {
iface, err := getVPCInterfaceConfig(ctx, machineScope, createConfig.Interfaces, logger)
if err != nil {
Expand All @@ -134,6 +145,19 @@
}
}

// if vlan is enabled, attach additional interface as eth0 to linode
if machineScope.LinodeCluster.Spec.Network.UseVlan {
iface, err := getVlanInterfaceConfig(ctx, machineScope, logger)
if err != nil {
logger.Error(err, "Failed to get VLAN interface config")
return nil, err

Check warning on line 153 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L150-L153

Added lines #L150 - L153 were not covered by tests
}
if iface != nil {

Check warning on line 155 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L155

Added line #L155 was not covered by tests
// add VLAN interface as first interface
createConfig.Interfaces = slices.Insert(createConfig.Interfaces, 0, *iface)

Check warning on line 157 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L157

Added line #L157 was not covered by tests
}
}

if machineScope.LinodeMachine.Spec.PlacementGroupRef != nil {
pgID, err := getPlacementGroupID(ctx, machineScope, logger)
if err != nil {
Expand Down Expand Up @@ -191,14 +215,22 @@
Type: clusterv1.MachineExternalIP,
})

// Iterate over interfaces in config and find VPC specific ips
// Iterate over interfaces in config and find VPC or VLAN specific ips
for _, iface := range configs[0].Interfaces {
if iface.VPCID != nil && iface.IPv4.VPC != "" {
ips = append(ips, clusterv1.MachineAddress{
Address: iface.IPv4.VPC,
Type: clusterv1.MachineInternalIP,
})
}

if iface.Purpose == linodego.InterfacePurposeVLAN {
// vlan addresses have a /11 appended to them - we should strip it out.
ips = append(ips, clusterv1.MachineAddress{
Address: netip.MustParsePrefix(iface.IPAMAddress).Addr().String(),
Type: clusterv1.MachineInternalIP,
})

Check warning on line 232 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L229-L232

Added lines #L229 - L232 were not covered by tests
}
}

// if a node has private ip, store it as well
Expand Down Expand Up @@ -345,6 +377,95 @@
return *linodeFirewall.Spec.FirewallID, nil
}

func getNextIP(ips []string, prefixStr string) string {
prefix := netip.MustParsePrefix(prefixStr)
currentIp := prefix.Addr().Next()

Check warning on line 382 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L380-L382

Added lines #L380 - L382 were not covered by tests

ipString := currentIp.String()
for {
if !slices.Contains(ips, ipString) {
break

Check warning on line 387 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L384-L387

Added lines #L384 - L387 were not covered by tests
}
currentIp = currentIp.Next()
ipString = currentIp.String()

Check warning on line 390 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L389-L390

Added lines #L389 - L390 were not covered by tests
}
return ipString

Check warning on line 392 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L392

Added line #L392 was not covered by tests
}

func createIPsConfigMap(ctx context.Context, machineScope *scope.MachineScope, ip string) error {
return machineScope.Client.Create(ctx, &corev1.ConfigMap{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you give an example of what is in this configmap? I wonder if we could use part of the LInodeCluster spec for this information instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a simple map of machineName -> IP address

apiVersion: v1
data:
  schinmai-test-control-plane-f4g7c: 10.0.0.3
  schinmai-test-control-plane-mfxh6: 10.0.0.2
  schinmai-test-control-plane-mhczj: 10.0.0.1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-10-02T19:12:38Z"
  labels:
    clusterctl.cluster.x-k8s.io/move: "true"
  name: schinmai-test-ips
  namespace: default
  resourceVersion: "7452"
  uid: cf59bb0a-4340-4461-8317-c02748d72050

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted for a configmap so that we can have a record of what IP was assigned to which machine for updates (the linodeMachine spec doesn't have it)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we just add this info to the status on each of the LinodeMachines in this case?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still not totally sure on the consumer of this information so I might be missing part of the context

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this info is indeed saved into the status of linodeMachines - When X linodeMachines are reconciled in parallel, the linodeMacine controller needs to pick an IP for each instance, independently. To avoid assigning the same IP to multiple machines, I'm using the configmap as a locking mechanism, and a record of the IPs assigned to each machine. IF the configmap was sucessfully updated by the reconcile loop, it guaranteees that no other machine can get that IP and we eliminate conflicts

ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-ips", machineScope.Cluster.Name),
Namespace: machineScope.Cluster.Namespace,
Labels: map[string]string{
"clusterctl.cluster.x-k8s.io/move": "true",
},
},
Data: map[string]string{
machineScope.LinodeMachine.Name: ip,
},
})

Check warning on line 407 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L395-L407

Added lines #L395 - L407 were not covered by tests
}

func reserveNextIP(ctx context.Context, machineScope *scope.MachineScope, logger logr.Logger) (string, error) {
namespace := machineScope.Cluster.Namespace
clusterName := machineScope.Cluster.Name
var nextIP string
var ipsMap corev1.ConfigMap
AshleyDumaine marked this conversation as resolved.
Show resolved Hide resolved
err := machineScope.Client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: fmt.Sprintf("%s-ips", clusterName)}, &ipsMap)
if err != nil {
if apierrors.IsNotFound(err) {
nextIP = getNextIP([]string{}, vlanIPRange)
if err := createIPsConfigMap(ctx, machineScope, nextIP); err != nil {
return "", fmt.Errorf("creating Ips configmap: %w", err)

Check warning on line 420 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L410-L420

Added lines #L410 - L420 were not covered by tests
}
logger.Info("Machine got ip", machineScope.LinodeMachine.Name, nextIP)
return fmt.Sprintf(vlanIPFormat, nextIP), nil

Check warning on line 423 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L422-L423

Added lines #L422 - L423 were not covered by tests
}
return "", fmt.Errorf("retreiving ips configmap %s/%s: %w", namespace, fmt.Sprintf("%s-ips", clusterName), err)

Check warning on line 425 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L425

Added line #L425 was not covered by tests
}

if ip, ok := ipsMap.Data[machineScope.LinodeMachine.Name]; ok {
return fmt.Sprintf(vlanIPFormat, ip), nil

Check warning on line 429 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L428-L429

Added lines #L428 - L429 were not covered by tests
}

err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
if err := machineScope.Client.Get(ctx, client.ObjectKeyFromObject(&ipsMap), &ipsMap); err != nil {
return err

Check warning on line 434 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L432-L434

Added lines #L432 - L434 were not covered by tests
}

nextIP = getNextIP(maps.Values(ipsMap.Data), vlanIPRange)
ipsMap.Data[machineScope.LinodeMachine.Name] = nextIP
if err := machineScope.Client.Update(ctx, &ipsMap); err != nil {
return err

Check warning on line 440 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L437-L440

Added lines #L437 - L440 were not covered by tests
}
return nil

Check warning on line 442 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L442

Added line #L442 was not covered by tests
})
if err != nil {
return "", fmt.Errorf("updating ips in configmap %s/%s: %w", namespace, fmt.Sprintf("%s-ips", clusterName), err)

Check warning on line 445 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L444-L445

Added lines #L444 - L445 were not covered by tests
}

logger.Info("onbtained IP for machine", "name", machineScope.LinodeMachine.Name, "ip", nextIP)
return fmt.Sprintf(vlanIPFormat, nextIP), nil

Check warning on line 449 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L448-L449

Added lines #L448 - L449 were not covered by tests
}

func getVlanInterfaceConfig(ctx context.Context, machineScope *scope.MachineScope, logger logr.Logger) (*linodego.InstanceConfigInterfaceCreateOptions, error) {
logger = logger.WithValues("vlanName", machineScope.Cluster.Name)

Check warning on line 453 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L452-L453

Added lines #L452 - L453 were not covered by tests

// Try to obtain a IP for the machine using its name

ip, err := reserveNextIP(ctx, machineScope, logger)
if err != nil {
return nil, err

Check warning on line 459 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L457-L459

Added lines #L457 - L459 were not covered by tests
}

return &linodego.InstanceConfigInterfaceCreateOptions{
Purpose: linodego.InterfacePurposeVLAN,
Label: machineScope.Cluster.Name,
IPAMAddress: ip,
}, nil

Check warning on line 466 in controller/linodemachine_controller_helpers.go

View check run for this annotation

Codecov / codecov/patch

controller/linodemachine_controller_helpers.go#L462-L466

Added lines #L462 - L466 were not covered by tests
}

func getVPCInterfaceConfig(ctx context.Context, machineScope *scope.MachineScope, interfaces []linodego.InstanceConfigInterfaceCreateOptions, logger logr.Logger) (*linodego.InstanceConfigInterfaceCreateOptions, error) {
name := machineScope.LinodeCluster.Spec.VPCRef.Name
namespace := machineScope.LinodeCluster.Spec.VPCRef.Namespace
Expand Down
Loading