diff --git a/pkg/cloudprovider/ironcore/load_balancer.go b/pkg/cloudprovider/ironcore/load_balancer.go index 4f612e0..c1be3bd 100644 --- a/pkg/cloudprovider/ironcore/load_balancer.go +++ b/pkg/cloudprovider/ironcore/load_balancer.go @@ -12,10 +12,12 @@ import ( v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" cloudprovider "k8s.io/cloud-provider" servicehelper "k8s.io/cloud-provider/service/helpers" "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -157,6 +159,12 @@ func (o *ironcoreLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterNa NetworkRef: v1.LocalObjectReference{ Name: o.cloudConfig.NetworkName, }, + NetworkInterfaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + LabelKeyClusterName: clusterName, + }, + }, + Ports: lbPorts, }, } @@ -238,7 +246,7 @@ func waitLoadBalancerActive(ctx context.Context, ironcoreClient client.Client, e } func (o *ironcoreLoadBalancer) applyLoadBalancerRoutingForLoadBalancer(ctx context.Context, loadBalancer *networkingv1alpha1.LoadBalancer, nodes []*v1.Node) error { - loadBalacerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name) + loadBalacerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer) if err != nil { return fmt.Errorf("failed to get NetworkInterfaces for Nodes: %w", err) } @@ -275,7 +283,7 @@ func (o *ironcoreLoadBalancer) applyLoadBalancerRoutingForLoadBalancer(ctx conte return nil } -func (o *ironcoreLoadBalancer) getLoadBalancerDestinationsForNodes(ctx context.Context, nodes []*v1.Node, networkName string) ([]networkingv1alpha1.LoadBalancerDestination, error) { +func (o *ironcoreLoadBalancer) getLoadBalancerDestinationsForNodes(ctx context.Context, nodes []*v1.Node, lb *networkingv1alpha1.LoadBalancer) ([]networkingv1alpha1.LoadBalancerDestination, error) { var loadbalancerDestinations []networkingv1alpha1.LoadBalancerDestination for _, node := range nodes { machineName := extractMachineNameFromProviderID(node.Spec.ProviderID) @@ -297,9 +305,21 @@ func (o *ironcoreLoadBalancer) getLoadBalancerDestinationsForNodes(ctx context.C } // If the NetworkInterface is not part of Network we continue - if networkInterface.Spec.NetworkRef.Name != networkName { + if networkInterface.Spec.NetworkRef.Name != lb.Spec.NetworkRef.Name { continue } + // Check if the network interface matches the LoadBalancer's NetworkInterfaceSelector labels + if lb.Spec.NetworkInterfaceSelector != nil { + selector, err := metav1.LabelSelectorAsSelector(lb.Spec.NetworkInterfaceSelector) + if err != nil { + return nil, fmt.Errorf("invalid label selector in LoadBalancer %s: %w", lb.Name, err) + } + + // If the NIC labels don't match the selector, skip this NIC + if !selector.Matches(labels.Set(networkInterface.Labels)) { + continue + } + } // Create a LoadBalancerDestination for every NetworkInterface IP for _, nicIP := range networkInterface.Status.IPs { @@ -349,7 +369,7 @@ func (o *ironcoreLoadBalancer) UpdateLoadBalancer(ctx context.Context, clusterNa } klog.V(2).InfoS("Updating LoadBalancerRouting destinations for LoadBalancer", "LoadBalancerRouting", client.ObjectKeyFromObject(loadBalancerRouting), "LoadBalancer", client.ObjectKeyFromObject(loadBalancer)) - loadBalancerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name) + loadBalancerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer) if err != nil { return fmt.Errorf("failed to get NetworkInterfaces for LoadBalancer %s: %w", client.ObjectKeyFromObject(loadBalancer), err) } diff --git a/pkg/cloudprovider/ironcore/load_balancer_test.go b/pkg/cloudprovider/ironcore/load_balancer_test.go index 7c961c4..6674051 100644 --- a/pkg/cloudprovider/ironcore/load_balancer_test.go +++ b/pkg/cloudprovider/ironcore/load_balancer_test.go @@ -56,6 +56,9 @@ var _ = Describe("LoadBalancer", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: network.Name}, @@ -201,6 +204,9 @@ var _ = Describe("LoadBalancer", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: network.Name}, @@ -374,6 +380,9 @@ var _ = Describe("LoadBalancer", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: network.Name}, @@ -384,6 +393,7 @@ var _ = Describe("LoadBalancer", func() { Name: machine.Name, UID: machine.UID, }, + ProviderID: "foo/bar", }, } Expect(k8sClient.Create(ctx, networkInterface)).To(Succeed()) @@ -402,6 +412,9 @@ var _ = Describe("LoadBalancer", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterfacefoo"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: "foo"}, @@ -412,6 +425,7 @@ var _ = Describe("LoadBalancer", func() { Name: machine.Name, UID: machine.UID, }, + ProviderID: "wrong/foo", }, } Expect(k8sClient.Create(ctx, networkInterfaceFoo)).To(Succeed()) @@ -421,7 +435,7 @@ var _ = Describe("LoadBalancer", func() { Eventually(UpdateStatus(networkInterfaceFoo, func() { networkInterfaceFoo.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable networkInterfaceFoo.Status.IPs = []commonv1alpha1.IP{ - commonv1alpha1.MustParseIP("100.0.0.1"), + commonv1alpha1.MustParseIP("100.0.0.2"), } })).Should(Succeed()) @@ -523,11 +537,14 @@ var _ = Describe("LoadBalancer", func() { ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface2"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: network.Name}, IPs: []networkingv1alpha1.IPSource{{ - Value: commonv1alpha1.MustParseNewIP("100.0.0.2"), + Value: commonv1alpha1.MustParseNewIP("100.0.0.3"), }}, MachineRef: &commonv1alpha1.LocalUIDReference{ Name: machine2.Name, @@ -543,7 +560,7 @@ var _ = Describe("LoadBalancer", func() { Eventually(UpdateStatus(networkInterface2, func() { networkInterface2.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable networkInterface2.Status.IPs = []commonv1alpha1.IP{ - commonv1alpha1.MustParseIP("100.0.0.2"), + commonv1alpha1.MustParseIP("100.0.0.3"), } })).Should(Succeed()) @@ -590,6 +607,7 @@ var _ = Describe("LoadBalancer", func() { })), // networkInterfaceFoo will not be listed in destinations, because network "foo" used by // networkInterfaceFoo does not exist + // Ensure only two destination exists HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ { IP: commonv1alpha1.MustParseIP("100.0.0.1"), @@ -599,7 +617,7 @@ var _ = Describe("LoadBalancer", func() { ProviderID: networkInterface.Spec.ProviderID, }, }, { - IP: commonv1alpha1.MustParseIP("100.0.0.2"), + IP: commonv1alpha1.MustParseIP("100.0.0.3"), TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ UID: networkInterface2.UID, Name: networkInterface2.Name, @@ -609,8 +627,7 @@ var _ = Describe("LoadBalancer", func() { })), )) }) - - It("should ensure LoadBalancer with legacy name", func(ctx SpecContext) { + It("should update LoadBalancer Routing destinations when any nic is deleted", func(ctx SpecContext) { By("creating a machine object") machine := &computev1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ @@ -627,10 +644,13 @@ var _ = Describe("LoadBalancer", func() { DeferCleanup(k8sClient.Delete, machine) By("creating a network interface for machine") - networkInterface := &networkingv1alpha1.NetworkInterface{ + networkInterface1 := &networkingv1alpha1.NetworkInterface{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ NetworkRef: corev1.LocalObjectReference{Name: network.Name}, @@ -641,27 +661,30 @@ var _ = Describe("LoadBalancer", func() { Name: machine.Name, UID: machine.UID, }, + ProviderID: "foo://bar", }, } - Expect(k8sClient.Create(ctx, networkInterface)).To(Succeed()) - DeferCleanup(k8sClient.Delete, networkInterface) + Expect(k8sClient.Create(ctx, networkInterface1)).To(Succeed()) By("patching the network interface status") - Eventually(UpdateStatus(networkInterface, func() { - networkInterface.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable - networkInterface.Status.IPs = []commonv1alpha1.IP{ + Eventually(UpdateStatus(networkInterface1, func() { + networkInterface1.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable + networkInterface1.Status.IPs = []commonv1alpha1.IP{ commonv1alpha1.MustParseIP("100.0.0.1"), } })).Should(Succeed()) - By("creating a network interface for machine with network") - networkInterfaceFoo := &networkingv1alpha1.NetworkInterface{ + By("creating another network interface for machine") + networkInterface2 := &networkingv1alpha1.NetworkInterface{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, - Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterfacefoo"), + Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface2"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, }, Spec: networkingv1alpha1.NetworkInterfaceSpec{ - NetworkRef: corev1.LocalObjectReference{Name: "foo"}, + NetworkRef: corev1.LocalObjectReference{Name: network.Name}, IPs: []networkingv1alpha1.IPSource{{ Value: commonv1alpha1.MustParseNewIP("100.0.0.2"), }}, @@ -669,16 +692,17 @@ var _ = Describe("LoadBalancer", func() { Name: machine.Name, UID: machine.UID, }, + ProviderID: "foo://bar", }, } - Expect(k8sClient.Create(ctx, networkInterfaceFoo)).To(Succeed()) - DeferCleanup(k8sClient.Delete, networkInterfaceFoo) + Expect(k8sClient.Create(ctx, networkInterface2)).To(Succeed()) + DeferCleanup(k8sClient.Delete, networkInterface2) By("patching the network interface status") - Eventually(UpdateStatus(networkInterfaceFoo, func() { - networkInterfaceFoo.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable - networkInterfaceFoo.Status.IPs = []commonv1alpha1.IP{ - commonv1alpha1.MustParseIP("100.0.0.1"), + Eventually(UpdateStatus(networkInterface2, func() { + networkInterface2.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable + networkInterface2.Status.IPs = []commonv1alpha1.IP{ + commonv1alpha1.MustParseIP("100.0.0.2"), } })).Should(Succeed()) @@ -701,7 +725,7 @@ var _ = Describe("LoadBalancer", func() { Name: "primary", NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ NetworkInterfaceRef: &corev1.LocalObjectReference{ - Name: networkInterface.Name, + Name: networkInterface1.Name, }, }, }, @@ -709,7 +733,281 @@ var _ = Describe("LoadBalancer", func() { Name: "secondary", NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ NetworkInterfaceRef: &corev1.LocalObjectReference{ - Name: networkInterfaceFoo.Name, + Name: networkInterface2.Name, + }, + }, + }, + } + })).Should(Succeed()) + + By("creating test service of type load balancer") + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "service-", + Namespace: ns.Name, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + Ports: []corev1.ServicePort{ + { + Name: "https", + Protocol: "TCP", + Port: 443, + TargetPort: intstr.IntOrString{IntVal: 443}, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, service)).To(Succeed()) + DeferCleanup(k8sClient.Delete, service) + + // Start a goroutine to patch public IP into load banacer status in order to succeed EnsureLoadBalancer call + loadBalancer := &networkingv1alpha1.LoadBalancer{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + Name: lbProvider.GetLoadBalancerName(ctx, clusterName, service), + }, + } + go func() { + defer GinkgoRecover() + By("patching public IP into load balancer status") + Eventually(UpdateStatus(loadBalancer, func() { + loadBalancer.Status.IPs = []commonv1alpha1.IP{commonv1alpha1.MustParseIP("10.0.0.1")} + })).Should(Succeed()) + }() + + By("ensuring load balancer for service") + Expect(lbProvider.EnsureLoadBalancer(ctx, clusterName, service, []*corev1.Node{node})).Error().ToNot(HaveOccurred()) + + By("ensuring the load balancer type is public and load balancer status has public IP") + Eventually(Object(loadBalancer)).Should(SatisfyAll( + HaveField("Spec.Type", Equal(networkingv1alpha1.LoadBalancerTypePublic)), + HaveField("Status.IPs", Equal([]commonv1alpha1.IP{commonv1alpha1.MustParseIP("10.0.0.1")})))) + + By("creating a second machine object") + machine2 := &computev1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "machine-", + }, + Spec: computev1alpha1.MachineSpec{ + MachineClassRef: corev1.LocalObjectReference{Name: "machine-class"}, + Image: "my-image:latest", + Volumes: []computev1alpha1.Volume{}, + }, + } + Expect(k8sClient.Create(ctx, machine2)).To(Succeed()) + DeferCleanup(k8sClient.Delete, machine2) + + By("creating a network interface for the second machine") + networkInterface3 := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface3"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: network.Name}, + IPs: []networkingv1alpha1.IPSource{{ + Value: commonv1alpha1.MustParseNewIP("100.0.0.3"), + }}, + MachineRef: &commonv1alpha1.LocalUIDReference{ + Name: machine2.Name, + UID: machine2.UID, + }, + ProviderID: "foo://bar", + }, + } + Expect(k8sClient.Create(ctx, networkInterface3)).To(Succeed()) + DeferCleanup(k8sClient.Delete, networkInterface3) + + By("patching the network interface status") + Eventually(UpdateStatus(networkInterface3, func() { + networkInterface3.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable + networkInterface3.Status.IPs = []commonv1alpha1.IP{ + commonv1alpha1.MustParseIP("100.0.0.3"), + } + })).Should(Succeed()) + + By("patching the network interfaces of the machine") + Eventually(Update(machine2, func() { + machine2.Spec.NetworkInterfaces = []computev1alpha1.NetworkInterface{ + { + Name: "primary", + NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ + NetworkInterfaceRef: &corev1.LocalObjectReference{ + Name: networkInterface3.Name, + }, + }, + }, + } + })).Should(Succeed()) + + By("creating node object with a provider ID referencing the machine") + node2 := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: machine2.Name, + }, + Spec: corev1.NodeSpec{ + ProviderID: getProviderID(machine2.Namespace, machine2.Name), + }, + } + Expect(k8sClient.Create(ctx, node2)).To(Succeed()) + DeferCleanup(k8sClient.Delete, node2) + + By("ensuring destinations of load balancer routing gets updated for node and node2") + Expect(lbProvider.UpdateLoadBalancer(ctx, clusterName, service, []*corev1.Node{node, node2})).NotTo(HaveOccurred()) + lbRouting := &networkingv1alpha1.LoadBalancerRouting{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: service.Namespace, + Name: loadBalancer.Name, + }, + } + Eventually(Object(lbRouting)).Should(SatisfyAll( + HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + })), + HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ + { + IP: commonv1alpha1.MustParseIP("100.0.0.1"), + TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ + UID: networkInterface1.UID, + Name: networkInterface1.Name, + ProviderID: networkInterface1.Spec.ProviderID, + }, + }, { + IP: commonv1alpha1.MustParseIP("100.0.0.2"), + TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ + UID: networkInterface2.UID, + Name: networkInterface2.Name, + ProviderID: networkInterface2.Spec.ProviderID, + }, + }, { + IP: commonv1alpha1.MustParseIP("100.0.0.3"), + TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ + UID: networkInterface3.UID, + Name: networkInterface3.Name, + ProviderID: networkInterface3.Spec.ProviderID, + }, + }, + })), + )) + + By("Deleting a networkInterface") + Expect(k8sClient.Delete(ctx, networkInterface1)).Should(Succeed()) + By("patching the network interfaces of the machine") + Eventually(Update(machine, func() { + machine.Spec.NetworkInterfaces = []computev1alpha1.NetworkInterface{ + { + Name: "secondary", + NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ + NetworkInterfaceRef: &corev1.LocalObjectReference{ + Name: networkInterface2.Name, + }, + }, + }, + } + })).Should(Succeed()) + By("ensuring destinations of load balancer routing gets updated for node and node2") + Expect(lbProvider.UpdateLoadBalancer(ctx, clusterName, service, []*corev1.Node{node, node2})).NotTo(HaveOccurred()) + Eventually(Object(lbRouting)).Should(SatisfyAll( + HaveField("ObjectMeta.OwnerReferences", ContainElement(metav1.OwnerReference{ + APIVersion: "networking.ironcore.dev/v1alpha1", + Kind: "LoadBalancer", + Name: loadBalancer.Name, + UID: loadBalancer.UID, + })), + HaveField("Destinations", ContainElements([]networkingv1alpha1.LoadBalancerDestination{ + { + IP: commonv1alpha1.MustParseIP("100.0.0.2"), + TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ + UID: networkInterface2.UID, + Name: networkInterface2.Name, + ProviderID: networkInterface2.Spec.ProviderID, + }, + }, { + IP: commonv1alpha1.MustParseIP("100.0.0.3"), + TargetRef: &networkingv1alpha1.LoadBalancerTargetRef{ + UID: networkInterface3.UID, + Name: networkInterface3.Name, + ProviderID: networkInterface3.Spec.ProviderID, + }, + }, + })), + )) + }) + It("should ensure LoadBalancer with legacy name", func(ctx SpecContext) { + By("creating a machine object") + machine := &computev1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "machine-", + }, + Spec: computev1alpha1.MachineSpec{ + MachineClassRef: corev1.LocalObjectReference{Name: "machine-class"}, + Image: "my-image:latest", + Volumes: []computev1alpha1.Volume{}, + }, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed()) + DeferCleanup(k8sClient.Delete, machine) + + By("creating a network interface for machine") + networkInterface := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + Name: fmt.Sprintf("%s-%s", machine.Name, "networkinterface"), + Labels: map[string]string{ + LabelKeyClusterName: clusterName, + }, + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: network.Name}, + IPs: []networkingv1alpha1.IPSource{{ + Value: commonv1alpha1.MustParseNewIP("100.0.0.1"), + }}, + MachineRef: &commonv1alpha1.LocalUIDReference{ + Name: machine.Name, + UID: machine.UID, + }, + }, + } + Expect(k8sClient.Create(ctx, networkInterface)).To(Succeed()) + DeferCleanup(k8sClient.Delete, networkInterface) + + By("patching the network interface status") + Eventually(UpdateStatus(networkInterface, func() { + networkInterface.Status.State = networkingv1alpha1.NetworkInterfaceStateAvailable + networkInterface.Status.IPs = []commonv1alpha1.IP{ + commonv1alpha1.MustParseIP("100.0.0.1"), + } + })).Should(Succeed()) + + By("creating node object with a provider ID referencing the machine") + node := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: machine.Name, + }, + Spec: corev1.NodeSpec{ + ProviderID: getProviderID(machine.Namespace, machine.Name), + }, + } + Expect(k8sClient.Create(ctx, node)).To(Succeed()) + DeferCleanup(k8sClient.Delete, node) + + By("patching the network interfaces of the machine") + Eventually(Update(machine, func() { + machine.Spec.NetworkInterfaces = []computev1alpha1.NetworkInterface{ + { + Name: "primary", + NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ + NetworkInterfaceRef: &corev1.LocalObjectReference{ + Name: networkInterface.Name, }, }, }, diff --git a/pkg/cloudprovider/ironcore/suite_test.go b/pkg/cloudprovider/ironcore/suite_test.go index 5d2f01c..eaffca3 100644 --- a/pkg/cloudprovider/ironcore/suite_test.go +++ b/pkg/cloudprovider/ironcore/suite_test.go @@ -80,7 +80,7 @@ var _ = BeforeSuite(func() { // Note that you must have the required binaries setup under the bin directory to perform // the tests directly. When we run make test it will be setup and used automatically. BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", - fmt.Sprintf("1.30.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + fmt.Sprintf("1.31.0-%s-%s", runtime.GOOS, runtime.GOARCH)), } testEnvExt = &envtestext.EnvironmentExtensions{ APIServiceDirectoryPaths: []string{