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  })