From 3c219893126e181ddd404ce8834a57e29cd2259e Mon Sep 17 00:00:00 2001 From: Arnau Verdaguer Date: Fri, 2 Feb 2024 11:46:03 +0100 Subject: [PATCH] Add type label into headless/normal services Adding type label to easier search between headless or normal service and use them to filter only the normal services during scale-down service removal. Resolves: OSPRH-4120 --- api/v1beta1/ovndbcluster_types.go | 5 +++ controllers/ovndbcluster_controller.go | 11 +++--- pkg/ovndbcluster/service.go | 6 ++-- tests/functional/base_test.go | 22 ++++++++++++ .../ovndbcluster_controller_test.go | 34 +++++++++++++++++++ 5 files changed, 72 insertions(+), 6 deletions(-) diff --git a/api/v1beta1/ovndbcluster_types.go b/api/v1beta1/ovndbcluster_types.go index 3ec9ed54..737b1ee1 100644 --- a/api/v1beta1/ovndbcluster_types.go +++ b/api/v1beta1/ovndbcluster_types.go @@ -31,6 +31,11 @@ const ( // SBDBType - Southbound database type SBDBType = "SB" + // ServiceHeadlessType - Constant to identify Headless services + ServiceHeadlessType = "headless" + // ServiceClusterType - Constant to identify Cluster services + ServiceClusterType = "cluster" + // DNSSuffix : hardcoded value on how DNSCore domain is configured DNSSuffix = "cluster.local" // TODO: retrieve it from environment diff --git a/controllers/ovndbcluster_controller.go b/controllers/ovndbcluster_controller.go index da671f89..156c5deb 100644 --- a/controllers/ovndbcluster_controller.go +++ b/controllers/ovndbcluster_controller.go @@ -533,9 +533,10 @@ func (r *OVNDBClusterReconciler) reconcileServices( // // Ensure the ovndbcluster headless service Exists // + headlessServiceLabels := util.MergeMaps(serviceLabels, map[string]string{"type": v1beta1.ServiceHeadlessType}) headlesssvc, err := service.NewService( - ovndbcluster.HeadlessService(serviceName, instance, serviceLabels), + ovndbcluster.HeadlessService(serviceName, instance, headlessServiceLabels, serviceLabels), time.Duration(5)*time.Second, nil, ) @@ -559,12 +560,13 @@ func (r *OVNDBClusterReconciler) reconcileServices( // // Create the ovndbcluster pod service if none exists // - ovndbServiceLabels := map[string]string{ + ovndbSelectorLabels := map[string]string{ common.AppSelector: serviceName, "statefulset.kubernetes.io/pod-name": ovnPod.Name, } + ovndbServiceLabels := util.MergeMaps(ovndbSelectorLabels, map[string]string{"type": v1beta1.ServiceClusterType}) svc, err := service.NewService( - ovndbcluster.Service(ovnPod.Name, instance, ovndbServiceLabels), + ovndbcluster.Service(ovnPod.Name, instance, ovndbServiceLabels, ovndbSelectorLabels), time.Duration(5)*time.Second, nil, ) @@ -581,11 +583,12 @@ func (r *OVNDBClusterReconciler) reconcileServices( } // Delete any extra services left after scale down + clusterServiceLabels := util.MergeMaps(serviceLabels, map[string]string{"type": v1beta1.ServiceClusterType}) svcList, err := service.GetServicesListWithLabel( ctx, helper, helper.GetBeforeObject().GetNamespace(), - serviceLabels, + clusterServiceLabels, ) if err == nil && len(svcList.Items) > int(*(instance.Spec.Replicas)) { for i := len(svcList.Items) - 1; i >= int(*(instance.Spec.Replicas)); i-- { diff --git a/pkg/ovndbcluster/service.go b/pkg/ovndbcluster/service.go index 1d9af1ea..a1d06872 100644 --- a/pkg/ovndbcluster/service.go +++ b/pkg/ovndbcluster/service.go @@ -12,6 +12,7 @@ func Service( serviceName string, instance *ovnv1.OVNDBCluster, serviceLabels map[string]string, + selectorLabels map[string]string, ) *corev1.Service { dbPortName := "north" raftPortName := "north-raft" @@ -30,7 +31,7 @@ func Service( Labels: serviceLabels, }, Spec: corev1.ServiceSpec{ - Selector: serviceLabels, + Selector: selectorLabels, Ports: []corev1.ServicePort{ { Name: dbPortName, @@ -52,6 +53,7 @@ func HeadlessService( serviceName string, instance *ovnv1.OVNDBCluster, serviceLabels map[string]string, + selectorLabels map[string]string, ) *corev1.Service { raftPortName := "north-raft" var raftPort int32 = 6643 @@ -66,7 +68,7 @@ func HeadlessService( Labels: serviceLabels, }, Spec: corev1.ServiceSpec{ - Selector: serviceLabels, + Selector: selectorLabels, Ports: []corev1.ServicePort{ { Name: raftPortName, diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index 04336727..db83fb8d 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -307,3 +307,25 @@ func GetPod(name types.NamespacedName) *corev1.Pod { func UpdatePod(pod *corev1.Pod) { k8sClient.Update(ctx, pod) } + +func GetServicesListWithLabel(namespace string, labelSelectorMap ...map[string]string) *corev1.ServiceList { + serviceList := &corev1.ServiceList{} + serviceListOpts := client.ListOptions{ + Namespace: namespace, + } + if len(labelSelectorMap) > 0 { + for i := 0; i < len(labelSelectorMap); i++ { + for key, value := range labelSelectorMap[i] { + ml := client.MatchingLabels{ + key: value, + } + ml.ApplyToList(&serviceListOpts) + } + } + } + Eventually(func(g Gomega) { + g.Expect(k8sClient.List(ctx, serviceList, &serviceListOpts)).Should(Succeed()) + }).Should(Succeed()) + + return serviceList +} diff --git a/tests/functional/ovndbcluster_controller_test.go b/tests/functional/ovndbcluster_controller_test.go index e046d0f6..4ca55d1b 100644 --- a/tests/functional/ovndbcluster_controller_test.go +++ b/tests/functional/ovndbcluster_controller_test.go @@ -226,6 +226,40 @@ var _ = Describe("OVNDBCluster controller", func() { DeferCleanup(th.DeleteInstance, instance) }) + It("should create services", func() { + internalAPINADName := types.NamespacedName{Namespace: namespace, Name: "internalapi"} + nad := th.CreateNetworkAttachmentDefinition(internalAPINADName) + DeferCleanup(th.DeleteInstance, nad) + + statefulSetName := types.NamespacedName{ + Namespace: namespace, + Name: "ovsdbserver-sb", + } + th.SimulateStatefulSetReplicaReadyWithPods( + statefulSetName, + map[string][]string{namespace + "/internalapi": {"10.0.0.1"}}, + ) + // Cluster is created with 1 replica, serviceListWithoutTypeLabel should be 2: + // - ovsdbserver-sb (headless type) + // - ovsdbserver-sb-0 (cluster type) + Eventually(func(g Gomega) { + serviceListWithoutTypeLabel := GetServicesListWithLabel(namespace) + g.Expect(len(serviceListWithoutTypeLabel.Items)).To(Equal(2)) + }).Should(Succeed()) + + Eventually(func(g Gomega) { + serviceListWithClusterType := GetServicesListWithLabel(namespace, map[string]string{"type": "cluster"}) + g.Expect(len(serviceListWithClusterType.Items)).To(Equal(1)) + g.Expect(serviceListWithClusterType.Items[0].Name).To(Equal("ovsdbserver-sb-0")) + }).Should(Succeed()) + + Eventually(func(g Gomega) { + serviceListWithHeadlessType := GetServicesListWithLabel(namespace, map[string]string{"type": "headless"}) + g.Expect(len(serviceListWithHeadlessType.Items)).To(Equal(1)) + g.Expect(serviceListWithHeadlessType.Items[0].Name).To(Equal("ovsdbserver-sb")) + }).Should(Succeed()) + }) + It("reports that the definition is missing", func() { th.ExpectConditionWithDetails( OVNDBClusterName,