github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/handler/handler_builder_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package handler 21 22 import ( 23 "context" 24 "fmt" 25 26 . "github.com/onsi/ginkgo/v2" 27 . "github.com/onsi/gomega" 28 29 "github.com/golang/mock/gomock" 30 appsv1 "k8s.io/api/apps/v1" 31 corev1 "k8s.io/api/core/v1" 32 "k8s.io/client-go/util/workqueue" 33 "sigs.k8s.io/controller-runtime/pkg/client" 34 "sigs.k8s.io/controller-runtime/pkg/event" 35 "sigs.k8s.io/controller-runtime/pkg/reconcile" 36 37 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 38 "github.com/1aal/kubeblocks/pkg/constant" 39 "github.com/1aal/kubeblocks/pkg/controller/builder" 40 "github.com/1aal/kubeblocks/pkg/controller/model" 41 ) 42 43 var _ = Describe("handler builder test.", func() { 44 Context("CRUD events", func() { 45 It("should work well", func() { 46 By("build resource tree") 47 namespace := "foo" 48 clusterName := "bar" 49 componentName := "test" 50 rsmName := fmt.Sprintf("%s-%s", clusterName, componentName) 51 stsName := rsmName 52 podName := stsName + "-0" 53 eventName := podName + ".123456" 54 labels := map[string]string{ 55 constant.AppManagedByLabelKey: constant.AppName, 56 constant.AppNameLabelKey: clusterName + "def", 57 constant.AppComponentLabelKey: componentName + "def", 58 constant.AppInstanceLabelKey: clusterName, 59 constant.KBAppComponentLabelKey: componentName, 60 } 61 rsm := builder.NewReplicatedStateMachineBuilder(namespace, rsmName). 62 AddLabelsInMap(labels). 63 GetObject() 64 sts := builder.NewStatefulSetBuilder(namespace, stsName). 65 AddLabelsInMap(labels). 66 GetObject() 67 pod := builder.NewPodBuilder(namespace, podName). 68 SetOwnerReferences("apps/v1", "StatefulSet", sts). 69 GetObject() 70 objectRef := corev1.ObjectReference{ 71 APIVersion: "v1", 72 Kind: "Pod", 73 Namespace: namespace, 74 Name: pod.Name, 75 UID: pod.UID, 76 } 77 evt := builder.NewEventBuilder(namespace, eventName). 78 SetInvolvedObject(objectRef). 79 GetObject() 80 81 finderCtx := &FinderContext{ 82 Context: ctx, 83 Reader: k8sMock, 84 Scheme: *model.GetScheme(), 85 } 86 handler := NewBuilder(finderCtx). 87 AddFinder(NewInvolvedObjectFinder(&corev1.Pod{})). 88 AddFinder(NewOwnerFinder(&appsv1.StatefulSet{})). 89 AddFinder(NewDelegatorFinder(&workloads.ReplicatedStateMachine{}, 90 []string{constant.AppInstanceLabelKey, constant.KBAppComponentLabelKey})). 91 Build() 92 93 By("build events and queue") 94 queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "handler-builder-test") 95 createEvent := event.CreateEvent{Object: evt} 96 updateEvent := event.UpdateEvent{ObjectOld: evt, ObjectNew: evt} 97 deleteEvent := event.DeleteEvent{Object: evt} 98 genericEvent := event.GenericEvent{Object: evt} 99 100 cases := []struct { 101 name string 102 testFunc func() 103 getTimes int 104 }{ 105 { 106 name: "Create", 107 testFunc: func() { handler.Create(ctx, createEvent, queue) }, 108 getTimes: 1, 109 }, 110 { 111 name: "Update", 112 testFunc: func() { handler.Update(ctx, updateEvent, queue) }, 113 getTimes: 2, 114 }, 115 { 116 name: "Delete", 117 testFunc: func() { handler.Delete(ctx, deleteEvent, queue) }, 118 getTimes: 1, 119 }, 120 { 121 name: "Generic", 122 testFunc: func() { handler.Generic(ctx, genericEvent, queue) }, 123 getTimes: 1, 124 }, 125 } 126 for _, c := range cases { 127 By(fmt.Sprintf("test %s interface", c.name)) 128 k8sMock.EXPECT(). 129 Get(gomock.Any(), gomock.Any(), &appsv1.StatefulSet{}, gomock.Any()). 130 DoAndReturn(func(_ context.Context, objKey client.ObjectKey, stsTmp *appsv1.StatefulSet, _ ...client.ListOptions) error { 131 *stsTmp = *sts 132 return nil 133 }).Times(c.getTimes) 134 k8sMock.EXPECT(). 135 Get(gomock.Any(), gomock.Any(), &corev1.Pod{}, gomock.Any()). 136 DoAndReturn(func(_ context.Context, objKey client.ObjectKey, podTmp *corev1.Pod, _ ...client.ListOptions) error { 137 *podTmp = *pod 138 return nil 139 }).Times(c.getTimes) 140 c.testFunc() 141 item, shutdown := queue.Get() 142 Expect(shutdown).Should(BeFalse()) 143 request, ok := item.(reconcile.Request) 144 Expect(ok).Should(BeTrue()) 145 Expect(request.Namespace).Should(Equal(rsm.Namespace)) 146 Expect(request.Name).Should(Equal(rsm.Name)) 147 queue.Done(item) 148 queue.Forget(item) 149 } 150 151 queue.ShutDown() 152 }) 153 }) 154 })