github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/rsm/transformer_objection_generation_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 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 28 "github.com/golang/mock/gomock" 29 apps "k8s.io/api/apps/v1" 30 corev1 "k8s.io/api/core/v1" 31 "sigs.k8s.io/controller-runtime/pkg/client" 32 33 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 34 "github.com/1aal/kubeblocks/pkg/constant" 35 "github.com/1aal/kubeblocks/pkg/controller/builder" 36 ) 37 38 var _ = Describe("object generation transformer test.", func() { 39 BeforeEach(func() { 40 rsm = builder.NewReplicatedStateMachineBuilder(namespace, name). 41 SetUID(uid). 42 AddLabels(constant.AppComponentLabelKey, name). 43 SetReplicas(3). 44 AddMatchLabelsInMap(selectors). 45 SetServiceName(headlessSvcName). 46 SetRoles(roles). 47 SetService(service). 48 SetCredential(credential). 49 SetTemplate(template). 50 SetCustomHandler(observeActions). 51 GetObject() 52 53 transCtx = &rsmTransformContext{ 54 Context: ctx, 55 Client: graphCli, 56 EventRecorder: nil, 57 Logger: logger, 58 rsmOrig: rsm.DeepCopy(), 59 rsm: rsm, 60 } 61 62 transformer = &ObjectGenerationTransformer{} 63 }) 64 65 Context("Transform function", func() { 66 It("should work well", func() { 67 sts := builder.NewStatefulSetBuilder(namespace, name).GetObject() 68 headlessSvc := builder.NewHeadlessServiceBuilder(name, getHeadlessSvcName(*rsm)).GetObject() 69 svc := builder.NewServiceBuilder(name, name).GetObject() 70 env := builder.NewConfigMapBuilder(name, name+"-rsm-env").GetObject() 71 k8sMock.EXPECT(). 72 List(gomock.Any(), &apps.StatefulSetList{}, gomock.Any()). 73 DoAndReturn(func(_ context.Context, list *apps.StatefulSetList, _ ...client.ListOption) error { 74 return nil 75 }).Times(1) 76 k8sMock.EXPECT(). 77 List(gomock.Any(), &corev1.ServiceList{}, gomock.Any()). 78 DoAndReturn(func(_ context.Context, list *corev1.ServiceList, _ ...client.ListOption) error { 79 return nil 80 }).Times(1) 81 k8sMock.EXPECT(). 82 List(gomock.Any(), &corev1.ConfigMapList{}, gomock.Any()). 83 DoAndReturn(func(_ context.Context, list *corev1.ConfigMapList, _ ...client.ListOption) error { 84 return nil 85 }).Times(1) 86 87 dagExpected := mockDAG() 88 graphCli.Create(dagExpected, sts) 89 graphCli.Create(dagExpected, headlessSvc) 90 graphCli.Create(dagExpected, svc) 91 graphCli.Create(dagExpected, env) 92 graphCli.DependOn(dagExpected, sts, headlessSvc, svc, env) 93 94 // do Transform 95 dag := mockDAG() 96 Expect(transformer.Transform(transCtx, dag)).Should(Succeed()) 97 98 // compare DAGs 99 Expect(dag.Equals(dagExpected, less)).Should(BeTrue()) 100 101 By("set svc and alternative svcs to nil") 102 rsm.Spec.Service = nil 103 rsm.Spec.AlternativeServices = nil 104 k8sMock.EXPECT(). 105 List(gomock.Any(), &apps.StatefulSetList{}, gomock.Any()). 106 DoAndReturn(func(_ context.Context, list *apps.StatefulSetList, _ ...client.ListOption) error { 107 return nil 108 }).Times(1) 109 k8sMock.EXPECT(). 110 List(gomock.Any(), &corev1.ServiceList{}, gomock.Any()). 111 DoAndReturn(func(_ context.Context, list *corev1.ServiceList, _ ...client.ListOption) error { 112 return nil 113 }).Times(1) 114 k8sMock.EXPECT(). 115 List(gomock.Any(), &corev1.ConfigMapList{}, gomock.Any()). 116 DoAndReturn(func(_ context.Context, list *corev1.ConfigMapList, _ ...client.ListOption) error { 117 return nil 118 }).Times(1) 119 dag = mockDAG() 120 Expect(transformer.Transform(transCtx, dag)).Should(Succeed()) 121 }) 122 }) 123 124 Context("buildEnvConfigData function", func() { 125 It("should work well", func() { 126 By("build env config data") 127 rsm.Status.MembersStatus = []workloads.MemberStatus{ 128 { 129 PodName: getPodName(rsm.Name, 1), 130 ReplicaRole: workloads.ReplicaRole{Name: "leader", IsLeader: true}, 131 }, 132 { 133 PodName: getPodName(rsm.Name, 0), 134 ReplicaRole: workloads.ReplicaRole{Name: "follower", CanVote: true}, 135 }, 136 { 137 PodName: getPodName(rsm.Name, 2), 138 ReplicaRole: workloads.ReplicaRole{Name: "follower", CanVote: true}, 139 }, 140 } 141 requiredKeys := []string{ 142 "KB_REPLICA_COUNT", 143 "KB_0_HOSTNAME", 144 "KB_CLUSTER_UID", 145 } 146 cfg := buildEnvConfigData(*rsm) 147 148 By("builds Env Config correctly") 149 Expect(cfg).ShouldNot(BeNil()) 150 for _, k := range requiredKeys { 151 _, ok := cfg[k] 152 Expect(ok).Should(BeTrue()) 153 } 154 155 By("builds env config with resources recreate") 156 Expect(cfg["KB_CLUSTER_UID"]).Should(BeEquivalentTo(uid)) 157 158 By("builds Env Config with ConsensusSet status correctly") 159 toCheckKeys := append(requiredKeys, []string{ 160 "KB_LEADER", 161 "KB_FOLLOWERS", 162 }...) 163 for _, k := range toCheckKeys { 164 _, ok := cfg[k] 165 Expect(ok).Should(BeTrue()) 166 } 167 }) 168 }) 169 170 Context("well-known service labels", func() { 171 It("should work well", func() { 172 svc := buildSvc(*rsm) 173 Expect(svc).ShouldNot(BeNil()) 174 for k, ev := range service.Labels { 175 v, ok := svc.Labels[k] 176 Expect(ok).Should(BeTrue()) 177 Expect(v).Should(Equal(ev)) 178 } 179 }) 180 }) 181 182 Context("injectRoleProbeBaseContainer function", func() { 183 It("should reuse container 'kb-checkrole' if exists", func() { 184 templateCopy := template.DeepCopy() 185 templateCopy.Spec.Containers = append(templateCopy.Spec.Containers, corev1.Container{ 186 Name: constant.RoleProbeContainerName, 187 Image: "bar", 188 }) 189 injectRoleProbeBaseContainer(*rsm, templateCopy, "", nil) 190 Expect(len(templateCopy.Spec.Containers)).Should(Equal(2)) 191 probeContainer := templateCopy.Spec.Containers[1] 192 Expect(probeContainer.ReadinessProbe).ShouldNot(BeNil()) 193 Expect(len(probeContainer.Ports)).Should(Equal(1)) 194 Expect(probeContainer.Ports[0].ContainerPort).Should(BeElementOf([]int32{int32(defaultRoleProbeGRPCPort), int32(defaultRoleProbeDaemonPort)})) 195 }) 196 197 It("should not use default grpcPort in case of 'lorry-grpc-port' existence", func() { 198 rsm.Spec.RoleProbe.RoleUpdateMechanism = workloads.ReadinessProbeEventUpdate 199 templateCopy := template.DeepCopy() 200 templateCopy.Spec.Containers = append(templateCopy.Spec.Containers, corev1.Container{ 201 Name: constant.RoleProbeContainerName, 202 Image: "bar", 203 Ports: []corev1.ContainerPort{ 204 { 205 Name: constant.LorryGRPCPortName, 206 ContainerPort: 9555, 207 }, 208 }, 209 }) 210 injectRoleProbeBaseContainer(*rsm, templateCopy, "", nil) 211 Expect(len(templateCopy.Spec.Containers)).Should(Equal(2)) 212 probeContainer := templateCopy.Spec.Containers[1] 213 Expect(len(probeContainer.Ports)).Should(Equal(1)) 214 Expect(probeContainer.Ports[0].ContainerPort).Should(Equal(int32(9555))) 215 }) 216 217 It("container.ports nil", func() { 218 rsm.Spec.RoleProbe.RoleUpdateMechanism = workloads.ReadinessProbeEventUpdate 219 templateCopy := template.DeepCopy() 220 templateCopy.Spec.Containers = append(templateCopy.Spec.Containers, corev1.Container{ 221 Name: constant.RoleProbeContainerName, 222 Image: "bar", 223 Ports: nil, 224 }) 225 injectRoleProbeBaseContainer(*rsm, templateCopy, "", nil) 226 Expect(len(templateCopy.Spec.Containers)).Should(Equal(2)) 227 probeContainer := templateCopy.Spec.Containers[1] 228 Expect(len(probeContainer.Ports)).Should(Equal(1)) 229 Expect(probeContainer.Ports[0].ContainerPort).Should(Equal(int32(defaultRoleProbeGRPCPort))) 230 }) 231 232 It("container.ports.containerPort negative", func() { 233 rsm.Spec.RoleProbe.RoleUpdateMechanism = workloads.ReadinessProbeEventUpdate 234 templateCopy := template.DeepCopy() 235 templateCopy.Spec.Containers = append(templateCopy.Spec.Containers, corev1.Container{ 236 Name: constant.RoleProbeContainerName, 237 Image: "bar", 238 Ports: []corev1.ContainerPort{ 239 { 240 Name: constant.LorryGRPCPortName, 241 ContainerPort: -9999, 242 }, 243 }, 244 }) 245 injectRoleProbeBaseContainer(*rsm, templateCopy, "", nil) 246 Expect(len(templateCopy.Spec.Containers)).Should(Equal(2)) 247 probeContainer := templateCopy.Spec.Containers[1] 248 Expect(len(probeContainer.Ports)).Should(Equal(1)) 249 Expect(probeContainer.Ports[0].ContainerPort).Should(Equal(int32(defaultRoleProbeGRPCPort))) 250 }) 251 252 }) 253 254 })