From a3dc806716bd10c4dc3855d6f64d0f73c04b21f3 Mon Sep 17 00:00:00 2001 From: ushabelgur Date: Fri, 1 Aug 2025 13:52:30 +0530 Subject: [PATCH 1/3] introduce disableNetworkPeering in apinetlet not to update peering status --- .../controllers/controllers_suite_test.go | 11 +- apinetlet/controllers/network_controller.go | 4 +- .../controllers/network_controller_test.go | 145 ++++++++++++++++++ cmd/apinetlet/main.go | 13 +- 4 files changed, 165 insertions(+), 8 deletions(-) diff --git a/apinetlet/controllers/controllers_suite_test.go b/apinetlet/controllers/controllers_suite_test.go index f83de1b7..b1b0ffc9 100644 --- a/apinetlet/controllers/controllers_suite_test.go +++ b/apinetlet/controllers/controllers_suite_test.go @@ -145,6 +145,10 @@ var _ = BeforeSuite(func() { }) func SetupTest(apiNetNamespace *corev1.Namespace) *corev1.Namespace { + return SetupTestWithNetworkPeeringFlag(apiNetNamespace, false) +} + +func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isNetworkPeeringDisabled bool) *corev1.Namespace { BeforeEach(func(ctx SpecContext) { k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, @@ -169,9 +173,10 @@ func SetupTest(apiNetNamespace *corev1.Namespace) *corev1.Namespace { }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkReconciler{ - Client: k8sManager.GetClient(), - APINetClient: k8sManager.GetClient(), - APINetNamespace: apiNetNamespace.Name, + Client: k8sManager.GetClient(), + APINetClient: k8sManager.GetClient(), + APINetNamespace: apiNetNamespace.Name, + NetworkPeeringDisabled: isNetworkPeeringDisabled, }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkInterfaceReconciler{ diff --git a/apinetlet/controllers/network_controller.go b/apinetlet/controllers/network_controller.go index 694adc21..81e534ad 100644 --- a/apinetlet/controllers/network_controller.go +++ b/apinetlet/controllers/network_controller.go @@ -42,6 +42,8 @@ type NetworkReconciler struct { APINetNamespace string WatchFilterValue string + + NetworkPeeringDisabled bool } //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch @@ -124,7 +126,7 @@ func (r *NetworkReconciler) updateNetworkStatus(ctx context.Context, log logr.Lo networkBase := network.DeepCopy() statusPeerings := apiNetNetworkPeeringsStatusToNetworkPeeringsStatus(apiNetNetwork.Status.Peerings, apiNetNetwork.Spec.Peerings) log.V(1).Info("network status peerings", "old", network.Status.Peerings, "new", statusPeerings) - if network.Status.State != state || !reflect.DeepEqual(network.Status.Peerings, statusPeerings) { + if network.Status.State != state || (!r.NetworkPeeringDisabled && !reflect.DeepEqual(network.Status.Peerings, statusPeerings)) { log.V(1).Info("Patching network status") network.Status.State = state network.Status.Peerings = statusPeerings diff --git a/apinetlet/controllers/network_controller_test.go b/apinetlet/controllers/network_controller_test.go index 90743b82..eb1bfca4 100644 --- a/apinetlet/controllers/network_controller_test.go +++ b/apinetlet/controllers/network_controller_test.go @@ -426,6 +426,151 @@ var _ = Describe("NetworkController", func() { Eventually(Get(network1)).Should(Satisfy(apierrors.IsNotFound)) Eventually(Get(network2)).Should(Satisfy(apierrors.IsNotFound)) + By("asserting the corresponding apinet network is gone as well") + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(apiNetNetwork1), apiNetNetwork1)).To(Satisfy(apierrors.IsNotFound)) + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(apiNetNetwork2), apiNetNetwork2)).To(Satisfy(apierrors.IsNotFound)) + }) + +}) + +var _ = Describe("NetworkControllerPeering", func() { + ns := SetupNamespace(&k8sClient) + ns1 := SetupNamespace(&k8sClient) + apiNetNs := SetupNamespace(&k8sClient) + SetupTestWithNetworkPeeringFlag(apiNetNs, true) + It("should not updated Ironcore Network peering status if NetworkPeeringDisabled is set to true", func(ctx SpecContext) { + By("creating a network network-1") + network1 := &networkingv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + Name: "network-1", + }, + Spec: networkingv1alpha1.NetworkSpec{ + Peerings: []networkingv1alpha1.NetworkPeering{ + { + Name: "peering-1", + NetworkRef: networkingv1alpha1.NetworkPeeringNetworkRef{ + Name: "network-2", + Namespace: ns1.Name, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, network1)).To(Succeed()) + + By("creating a network network-2") + network2 := &networkingv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns1.Name, + Name: "network-2", + }, + Spec: networkingv1alpha1.NetworkSpec{ + Peerings: []networkingv1alpha1.NetworkPeering{ + { + Name: "peering-2", + NetworkRef: networkingv1alpha1.NetworkPeeringNetworkRef{ + Name: "network-1", + Namespace: ns.Name, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, network2)).To(Succeed()) + + By("waiting for the corresponding APINet networks to be created") + apiNetNetwork1 := &apinetv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: apiNetNs.Name, + Name: string(network1.UID), + }, + } + Eventually(Get(apiNetNetwork1)).Should(Succeed()) + + apiNetNetwork2 := &apinetv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: apiNetNs.Name, + Name: string(network2.UID), + }, + } + Eventually(Get(apiNetNetwork2)).Should(Succeed()) + + By("inspecting the created apinet networks") + Expect(apiNetNetwork1.Labels).To(Equal(apinetletclient.SourceLabels(k8sClient.Scheme(), k8sClient.RESTMapper(), network1))) + Expect(apiNetNetwork1.Spec.ID).NotTo(BeEmpty()) + + Expect(apiNetNetwork2.Labels).To(Equal(apinetletclient.SourceLabels(k8sClient.Scheme(), k8sClient.RESTMapper(), network2))) + Expect(apiNetNetwork2.Spec.ID).NotTo(BeEmpty()) + + By("patching networks with peeringClaimRefs") + baseNetwork1 := network1.DeepCopy() + network1.Spec.PeeringClaimRefs = []networkingv1alpha1.NetworkPeeringClaimRef{{ + Name: network2.Name, + Namespace: network2.Namespace, + UID: network2.UID, + }} + Expect(k8sClient.Patch(ctx, network1, client.MergeFrom(baseNetwork1))).To(Succeed()) + + baseNetwork2 := network2.DeepCopy() + network2.Spec.PeeringClaimRefs = []networkingv1alpha1.NetworkPeeringClaimRef{{ + Name: network1.Name, + Namespace: network1.Namespace, + UID: network1.UID, + }} + Expect(k8sClient.Patch(ctx, network2, client.MergeFrom(baseNetwork2))).To(Succeed()) + + By("ensuring apinet network spec peerings are updated") + Eventually(Object(apiNetNetwork1)).Should(SatisfyAll( + HaveField("Spec.Peerings", ConsistOf(apinetv1alpha1.NetworkPeering{ + Name: network1.Spec.Peerings[0].Name, + ID: apiNetNetwork2.Spec.ID, + })), + )) + + Eventually(Object(apiNetNetwork2)).Should(SatisfyAll( + HaveField("Spec.Peerings", ConsistOf(apinetv1alpha1.NetworkPeering{ + Name: network2.Spec.Peerings[0].Name, + ID: apiNetNetwork1.Spec.ID, + })), + )) + + By("patching apinet network peering status") + apiNetNetwork2ID, _ := strconv.Atoi(apiNetNetwork2.Spec.ID) + Eventually(UpdateStatus(apiNetNetwork1, func() { + apiNetNetwork1.Status.Peerings = make(map[string][]apinetv1alpha1.NetworkPeeringStatus) + apiNetNetwork1.Status.Peerings["partition1"] = []apinetv1alpha1.NetworkPeeringStatus{{ + ID: int32(apiNetNetwork2ID), + State: apinetv1alpha1.NetworkPeeringStateReady, + }} + })).Should(Succeed()) + + apiNetNetwork1ID, _ := strconv.Atoi(apiNetNetwork1.Spec.ID) + Eventually(UpdateStatus(apiNetNetwork2, func() { + apiNetNetwork2.Status.Peerings = make(map[string][]apinetv1alpha1.NetworkPeeringStatus) + apiNetNetwork2.Status.Peerings["partition1"] = []apinetv1alpha1.NetworkPeeringStatus{{ + ID: int32(apiNetNetwork1ID), + State: apinetv1alpha1.NetworkPeeringStateReady, + }} + })).Should(Succeed()) + + By("ensuring ironcore networks peering status is updated") + Eventually(Object(network1)).Should(SatisfyAll( + HaveField("Status.Peerings", BeEmpty()), + )) + + Eventually(Object(network2)).Should(SatisfyAll( + HaveField("Status.Peerings", BeEmpty()), + )) + + By("deleting the networks") + Expect(k8sClient.Delete(ctx, network1)).To(Succeed()) + Expect(k8sClient.Delete(ctx, network2)).To(Succeed()) + + By("waiting for networks to be gone") + Eventually(Get(network1)).Should(Satisfy(apierrors.IsNotFound)) + Eventually(Get(network2)).Should(Satisfy(apierrors.IsNotFound)) + By("asserting the corresponding apinet network is gone as well") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(apiNetNetwork1), apiNetNetwork1)).To(Satisfy(apierrors.IsNotFound)) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(apiNetNetwork2), apiNetNetwork2)).To(Satisfy(apierrors.IsNotFound)) diff --git a/cmd/apinetlet/main.go b/cmd/apinetlet/main.go index 939ea97f..4560d02b 100644 --- a/cmd/apinetlet/main.go +++ b/cmd/apinetlet/main.go @@ -78,6 +78,8 @@ func main() { var tlsOpts []func(*tls.Config) + var disableNetworkPeering bool + flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") flag.BoolVar(&secureMetrics, "metrics-secure", true, @@ -100,6 +102,8 @@ func main() { flag.StringVar(&watchNamespace, "namespace", "", "Namespace that the controller watches to reconcile ironcore objects. If unspecified, the controller watches for ironcore objects across all namespaces.") flag.StringVar(&watchFilterValue, "watch-filter", "", fmt.Sprintf("label value that the controller watches to reconcile ironcore objects. Label key is always %s. If unspecified, the controller watches for all ironcore objects", commonv1alpha1.WatchLabel)) + flag.BoolVar(&disableNetworkPeering, "disable-network-peering", false, + "Disable the metalnet based network peering. If set to true the network peering is handled externally.") opts := zap.Options{ Development: true, @@ -274,10 +278,11 @@ func main() { } if err = (&controllers.NetworkReconciler{ - Client: mgr.GetClient(), - APINetClient: apiNetCluster.GetClient(), - APINetNamespace: apiNetNamespace, - WatchFilterValue: watchFilterValue, + Client: mgr.GetClient(), + APINetClient: apiNetCluster.GetClient(), + APINetNamespace: apiNetNamespace, + WatchFilterValue: watchFilterValue, + NetworkPeeringDisabled: disableNetworkPeering, }).SetupWithManager(mgr, apiNetCluster.GetCache()); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Network") os.Exit(1) From 91ca12fed8293cdc4abcd78edee4768e8a04c338 Mon Sep 17 00:00:00 2001 From: ushabelgur Date: Mon, 4 Aug 2025 10:25:05 +0530 Subject: [PATCH 2/3] rename flag --- apinetlet/controllers/controllers_suite_test.go | 10 +++++----- apinetlet/controllers/network_controller.go | 4 ++-- cmd/apinetlet/main.go | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apinetlet/controllers/controllers_suite_test.go b/apinetlet/controllers/controllers_suite_test.go index b1b0ffc9..b19ba846 100644 --- a/apinetlet/controllers/controllers_suite_test.go +++ b/apinetlet/controllers/controllers_suite_test.go @@ -148,7 +148,7 @@ func SetupTest(apiNetNamespace *corev1.Namespace) *corev1.Namespace { return SetupTestWithNetworkPeeringFlag(apiNetNamespace, false) } -func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isNetworkPeeringDisabled bool) *corev1.Namespace { +func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isPeeringStatusPropagationDisabled bool) *corev1.Namespace { BeforeEach(func(ctx SpecContext) { k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, @@ -173,10 +173,10 @@ func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isNetwor }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkReconciler{ - Client: k8sManager.GetClient(), - APINetClient: k8sManager.GetClient(), - APINetNamespace: apiNetNamespace.Name, - NetworkPeeringDisabled: isNetworkPeeringDisabled, + Client: k8sManager.GetClient(), + APINetClient: k8sManager.GetClient(), + APINetNamespace: apiNetNamespace.Name, + PeeringStatusPropagationDisabled: isPeeringStatusPropagationDisabled, }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkInterfaceReconciler{ diff --git a/apinetlet/controllers/network_controller.go b/apinetlet/controllers/network_controller.go index 81e534ad..455e97ee 100644 --- a/apinetlet/controllers/network_controller.go +++ b/apinetlet/controllers/network_controller.go @@ -43,7 +43,7 @@ type NetworkReconciler struct { WatchFilterValue string - NetworkPeeringDisabled bool + PeeringStatusPropagationDisabled bool } //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch @@ -126,7 +126,7 @@ func (r *NetworkReconciler) updateNetworkStatus(ctx context.Context, log logr.Lo networkBase := network.DeepCopy() statusPeerings := apiNetNetworkPeeringsStatusToNetworkPeeringsStatus(apiNetNetwork.Status.Peerings, apiNetNetwork.Spec.Peerings) log.V(1).Info("network status peerings", "old", network.Status.Peerings, "new", statusPeerings) - if network.Status.State != state || (!r.NetworkPeeringDisabled && !reflect.DeepEqual(network.Status.Peerings, statusPeerings)) { + if network.Status.State != state || (!r.PeeringStatusPropagationDisabled && !reflect.DeepEqual(network.Status.Peerings, statusPeerings)) { log.V(1).Info("Patching network status") network.Status.State = state network.Status.Peerings = statusPeerings diff --git a/cmd/apinetlet/main.go b/cmd/apinetlet/main.go index 4560d02b..0c4488bf 100644 --- a/cmd/apinetlet/main.go +++ b/cmd/apinetlet/main.go @@ -78,7 +78,7 @@ func main() { var tlsOpts []func(*tls.Config) - var disableNetworkPeering bool + var disablePeeringStatusPropagation bool flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") @@ -102,7 +102,7 @@ func main() { flag.StringVar(&watchNamespace, "namespace", "", "Namespace that the controller watches to reconcile ironcore objects. If unspecified, the controller watches for ironcore objects across all namespaces.") flag.StringVar(&watchFilterValue, "watch-filter", "", fmt.Sprintf("label value that the controller watches to reconcile ironcore objects. Label key is always %s. If unspecified, the controller watches for all ironcore objects", commonv1alpha1.WatchLabel)) - flag.BoolVar(&disableNetworkPeering, "disable-network-peering", false, + flag.BoolVar(&disablePeeringStatusPropagation, "disable-peering-status-propagation", false, "Disable the metalnet based network peering. If set to true the network peering is handled externally.") opts := zap.Options{ @@ -278,11 +278,11 @@ func main() { } if err = (&controllers.NetworkReconciler{ - Client: mgr.GetClient(), - APINetClient: apiNetCluster.GetClient(), - APINetNamespace: apiNetNamespace, - WatchFilterValue: watchFilterValue, - NetworkPeeringDisabled: disableNetworkPeering, + Client: mgr.GetClient(), + APINetClient: apiNetCluster.GetClient(), + APINetNamespace: apiNetNamespace, + WatchFilterValue: watchFilterValue, + PeeringStatusPropagationDisabled: disablePeeringStatusPropagation, }).SetupWithManager(mgr, apiNetCluster.GetCache()); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Network") os.Exit(1) From 294ca291622205f4e688216d8e5cf43454646b93 Mon Sep 17 00:00:00 2001 From: ushabelgur Date: Mon, 4 Aug 2025 15:23:04 +0530 Subject: [PATCH 3/3] revert flag name change --- apinetlet/controllers/controllers_suite_test.go | 10 +++++----- apinetlet/controllers/network_controller.go | 4 ++-- cmd/apinetlet/main.go | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apinetlet/controllers/controllers_suite_test.go b/apinetlet/controllers/controllers_suite_test.go index b19ba846..b1b0ffc9 100644 --- a/apinetlet/controllers/controllers_suite_test.go +++ b/apinetlet/controllers/controllers_suite_test.go @@ -148,7 +148,7 @@ func SetupTest(apiNetNamespace *corev1.Namespace) *corev1.Namespace { return SetupTestWithNetworkPeeringFlag(apiNetNamespace, false) } -func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isPeeringStatusPropagationDisabled bool) *corev1.Namespace { +func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isNetworkPeeringDisabled bool) *corev1.Namespace { BeforeEach(func(ctx SpecContext) { k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, @@ -173,10 +173,10 @@ func SetupTestWithNetworkPeeringFlag(apiNetNamespace *corev1.Namespace, isPeerin }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkReconciler{ - Client: k8sManager.GetClient(), - APINetClient: k8sManager.GetClient(), - APINetNamespace: apiNetNamespace.Name, - PeeringStatusPropagationDisabled: isPeeringStatusPropagationDisabled, + Client: k8sManager.GetClient(), + APINetClient: k8sManager.GetClient(), + APINetNamespace: apiNetNamespace.Name, + NetworkPeeringDisabled: isNetworkPeeringDisabled, }).SetupWithManager(k8sManager, k8sManager.GetCache())).To(Succeed()) Expect((&NetworkInterfaceReconciler{ diff --git a/apinetlet/controllers/network_controller.go b/apinetlet/controllers/network_controller.go index 455e97ee..81e534ad 100644 --- a/apinetlet/controllers/network_controller.go +++ b/apinetlet/controllers/network_controller.go @@ -43,7 +43,7 @@ type NetworkReconciler struct { WatchFilterValue string - PeeringStatusPropagationDisabled bool + NetworkPeeringDisabled bool } //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch @@ -126,7 +126,7 @@ func (r *NetworkReconciler) updateNetworkStatus(ctx context.Context, log logr.Lo networkBase := network.DeepCopy() statusPeerings := apiNetNetworkPeeringsStatusToNetworkPeeringsStatus(apiNetNetwork.Status.Peerings, apiNetNetwork.Spec.Peerings) log.V(1).Info("network status peerings", "old", network.Status.Peerings, "new", statusPeerings) - if network.Status.State != state || (!r.PeeringStatusPropagationDisabled && !reflect.DeepEqual(network.Status.Peerings, statusPeerings)) { + if network.Status.State != state || (!r.NetworkPeeringDisabled && !reflect.DeepEqual(network.Status.Peerings, statusPeerings)) { log.V(1).Info("Patching network status") network.Status.State = state network.Status.Peerings = statusPeerings diff --git a/cmd/apinetlet/main.go b/cmd/apinetlet/main.go index 0c4488bf..4560d02b 100644 --- a/cmd/apinetlet/main.go +++ b/cmd/apinetlet/main.go @@ -78,7 +78,7 @@ func main() { var tlsOpts []func(*tls.Config) - var disablePeeringStatusPropagation bool + var disableNetworkPeering bool flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") @@ -102,7 +102,7 @@ func main() { flag.StringVar(&watchNamespace, "namespace", "", "Namespace that the controller watches to reconcile ironcore objects. If unspecified, the controller watches for ironcore objects across all namespaces.") flag.StringVar(&watchFilterValue, "watch-filter", "", fmt.Sprintf("label value that the controller watches to reconcile ironcore objects. Label key is always %s. If unspecified, the controller watches for all ironcore objects", commonv1alpha1.WatchLabel)) - flag.BoolVar(&disablePeeringStatusPropagation, "disable-peering-status-propagation", false, + flag.BoolVar(&disableNetworkPeering, "disable-network-peering", false, "Disable the metalnet based network peering. If set to true the network peering is handled externally.") opts := zap.Options{ @@ -278,11 +278,11 @@ func main() { } if err = (&controllers.NetworkReconciler{ - Client: mgr.GetClient(), - APINetClient: apiNetCluster.GetClient(), - APINetNamespace: apiNetNamespace, - WatchFilterValue: watchFilterValue, - PeeringStatusPropagationDisabled: disablePeeringStatusPropagation, + Client: mgr.GetClient(), + APINetClient: apiNetCluster.GetClient(), + APINetNamespace: apiNetNamespace, + WatchFilterValue: watchFilterValue, + NetworkPeeringDisabled: disableNetworkPeering, }).SetupWithManager(mgr, apiNetCluster.GetCache()); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Network") os.Exit(1)