github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/rsm/pod_role_event_handler_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 rsm 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 corev1 "k8s.io/api/core/v1" 31 "sigs.k8s.io/controller-runtime/pkg/client" 32 logf "sigs.k8s.io/controller-runtime/pkg/log" 33 34 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 35 "github.com/1aal/kubeblocks/pkg/constant" 36 "github.com/1aal/kubeblocks/pkg/controller/builder" 37 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 38 ) 39 40 var _ = Describe("pod role label event handler test", func() { 41 Context("Handle function", func() { 42 It("should work well", func() { 43 cli := k8sMock 44 reqCtx := intctrlutil.RequestCtx{ 45 Ctx: ctx, 46 Log: logger, 47 } 48 pod := builder.NewPodBuilder(namespace, getPodName(name, 0)).SetUID(uid).GetObject() 49 objectRef := corev1.ObjectReference{ 50 APIVersion: "v1", 51 Kind: "Pod", 52 Namespace: pod.Namespace, 53 Name: pod.Name, 54 UID: pod.UID, 55 FieldPath: readinessProbeEventFieldPath, 56 } 57 role := workloads.ReplicaRole{ 58 Name: "leader", 59 AccessMode: workloads.ReadWriteMode, 60 IsLeader: true, 61 CanVote: true, 62 } 63 64 By("build an expected message") 65 message := fmt.Sprintf("Readiness probe failed: error: health rpc failed: rpc error: code = Unknown desc = {\"event\":\"Success\",\"originalRole\":\"\",\"role\":\"%s\"}", role.Name) 66 event := builder.NewEventBuilder(namespace, "foo"). 67 SetInvolvedObject(objectRef). 68 SetMessage(message). 69 GetObject() 70 71 handler := &PodRoleEventHandler{} 72 k8sMock.EXPECT(). 73 Get(gomock.Any(), gomock.Any(), &corev1.Pod{}, gomock.Any()). 74 DoAndReturn(func(_ context.Context, objKey client.ObjectKey, p *corev1.Pod, _ ...client.GetOptions) error { 75 p.Namespace = objKey.Namespace 76 p.Name = objKey.Name 77 p.UID = pod.UID 78 p.Labels = map[string]string{constant.AppInstanceLabelKey: name} 79 return nil 80 }).Times(1) 81 k8sMock.EXPECT(). 82 Get(gomock.Any(), gomock.Any(), &workloads.ReplicatedStateMachine{}, gomock.Any()). 83 DoAndReturn(func(_ context.Context, objKey client.ObjectKey, rsm *workloads.ReplicatedStateMachine, _ ...client.GetOptions) error { 84 rsm.Namespace = objKey.Namespace 85 rsm.Name = objKey.Name 86 rsm.Spec.Roles = []workloads.ReplicaRole{role} 87 return nil 88 }).Times(1) 89 k8sMock.EXPECT(). 90 Patch(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 91 DoAndReturn(func(_ context.Context, pd *corev1.Pod, patch client.Patch, _ ...client.PatchOption) error { 92 Expect(pd).ShouldNot(BeNil()) 93 Expect(pd.Labels).ShouldNot(BeNil()) 94 Expect(pd.Labels[roleLabelKey]).Should(Equal(role.Name)) 95 Expect(pd.Labels[rsmAccessModeLabelKey]).Should(BeEquivalentTo(role.AccessMode)) 96 return nil 97 }).Times(1) 98 k8sMock.EXPECT(). 99 Patch(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 100 DoAndReturn(func(_ context.Context, evt *corev1.Event, patch client.Patch, _ ...client.PatchOption) error { 101 Expect(evt).ShouldNot(BeNil()) 102 Expect(evt.Annotations).ShouldNot(BeNil()) 103 Expect(evt.Annotations[roleChangedAnnotKey]).Should(Equal(fmt.Sprintf("count-%d", evt.Count))) 104 return nil 105 }).Times(1) 106 Expect(handler.Handle(cli, reqCtx, nil, event)).Should(Succeed()) 107 108 By("build an unexpected message") 109 message = "unexpected message" 110 event = builder.NewEventBuilder(namespace, "foo"). 111 SetInvolvedObject(objectRef). 112 SetMessage(message). 113 GetObject() 114 k8sMock.EXPECT(). 115 Patch(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 116 DoAndReturn(func(_ context.Context, evt *corev1.Event, patch client.Patch, _ ...client.PatchOption) error { 117 Expect(evt).ShouldNot(BeNil()) 118 Expect(evt.Annotations).ShouldNot(BeNil()) 119 Expect(evt.Annotations[roleChangedAnnotKey]).Should(Equal(fmt.Sprintf("count-%d", evt.Count))) 120 return nil 121 }).Times(1) 122 Expect(handler.Handle(cli, reqCtx, nil, event)).Should(Succeed()) 123 }) 124 }) 125 126 Context("parseProbeEventMessage function", func() { 127 It("should work well", func() { 128 reqCtx := intctrlutil.RequestCtx{ 129 Ctx: ctx, 130 Log: logf.FromContext(ctx).WithValues("pod-role-event-handler", namespace), 131 } 132 133 By("build an well formatted message") 134 roleName := "leader" 135 message := fmt.Sprintf("Readiness probe failed: error: health rpc failed: rpc error: code = Unknown desc = {\"event\":\"Success\",\"originalRole\":\"\",\"role\":\"%s\"}", roleName) 136 event := builder.NewEventBuilder(namespace, "foo"). 137 SetMessage(message). 138 GetObject() 139 msg := parseProbeEventMessage(reqCtx, event) 140 Expect(msg).ShouldNot(BeNil()) 141 Expect(msg.Role).Should(Equal(roleName)) 142 143 By("build an error formatted message") 144 message = "Readiness probe failed: error: health rpc failed: rpc error: code = Unknown desc = {\"event\":}" 145 event.Message = message 146 Expect(parseProbeEventMessage(reqCtx, event)).Should(BeNil()) 147 }) 148 }) 149 })