github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/factory/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 factory 21 22 import ( 23 "encoding/json" 24 "fmt" 25 26 . "github.com/onsi/ginkgo/v2" 27 . "github.com/onsi/gomega" 28 29 "golang.org/x/exp/slices" 30 appsv1 "k8s.io/api/apps/v1" 31 corev1 "k8s.io/api/core/v1" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/types" 34 "sigs.k8s.io/controller-runtime/pkg/client" 35 36 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 37 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 38 cfgcm "github.com/1aal/kubeblocks/pkg/configuration/config_manager" 39 "github.com/1aal/kubeblocks/pkg/constant" 40 "github.com/1aal/kubeblocks/pkg/controller/component" 41 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 42 testapps "github.com/1aal/kubeblocks/pkg/testutil/apps" 43 viper "github.com/1aal/kubeblocks/pkg/viperx" 44 ) 45 46 var _ = Describe("builder", func() { 47 const clusterDefName = "test-clusterdef" 48 const clusterVersionName = "test-clusterversion" 49 const clusterName = "test-cluster" 50 const mysqlCompDefName = "replicasets" 51 const mysqlCompName = "mysql" 52 const proxyCompDefName = "proxy" 53 54 allFieldsClusterDefObj := func(needCreate bool) *appsv1alpha1.ClusterDefinition { 55 By("By assure an clusterDefinition obj") 56 clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). 57 AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). 58 AddComponentDef(testapps.StatelessNginxComponent, proxyCompDefName). 59 GetObject() 60 if needCreate { 61 Expect(testCtx.CreateObj(testCtx.Ctx, clusterDefObj)).Should(Succeed()) 62 } 63 return clusterDefObj 64 } 65 66 allFieldsClusterVersionObj := func(needCreate bool) *appsv1alpha1.ClusterVersion { 67 By("By assure an clusterVersion obj") 68 clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). 69 AddComponentVersion(mysqlCompDefName). 70 AddContainerShort("mysql", testapps.ApeCloudMySQLImage). 71 AddComponentVersion(proxyCompDefName). 72 AddInitContainerShort("nginx-init", testapps.NginxImage). 73 AddContainerShort("nginx", testapps.NginxImage). 74 GetObject() 75 if needCreate { 76 Expect(testCtx.CreateObj(testCtx.Ctx, clusterVersionObj)).Should(Succeed()) 77 } 78 return clusterVersionObj 79 } 80 81 newExtraEnvs := func() map[string]string { 82 jsonStr, _ := json.Marshal(map[string]string{ 83 "mock-key": "mock-value", 84 }) 85 return map[string]string{ 86 constant.ExtraEnvAnnotationKey: string(jsonStr), 87 } 88 } 89 90 newAllFieldsClusterObj := func( 91 clusterDefObj *appsv1alpha1.ClusterDefinition, 92 clusterVersionObj *appsv1alpha1.ClusterVersion, 93 needCreate bool, 94 ) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, types.NamespacedName) { 95 // setup Cluster obj requires default ClusterDefinition and ClusterVersion objects 96 if clusterDefObj == nil { 97 clusterDefObj = allFieldsClusterDefObj(needCreate) 98 } 99 if clusterVersionObj == nil { 100 clusterVersionObj = allFieldsClusterVersionObj(needCreate) 101 } 102 pvcSpec := testapps.NewPVCSpec("1Gi") 103 clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, 104 clusterDefObj.Name, clusterVersionObj.Name). 105 AddAnnotationsInMap(newExtraEnvs()). 106 AddComponent(mysqlCompName, mysqlCompDefName).SetReplicas(1). 107 AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). 108 AddService(testapps.ServiceVPCName, corev1.ServiceTypeLoadBalancer). 109 AddService(testapps.ServiceInternetName, corev1.ServiceTypeLoadBalancer). 110 GetObject() 111 key := client.ObjectKeyFromObject(clusterObj) 112 if needCreate { 113 Expect(testCtx.CreateObj(testCtx.Ctx, clusterObj)).Should(Succeed()) 114 } 115 return clusterObj, clusterDefObj, clusterVersionObj, key 116 } 117 118 newStsObj := func() *appsv1.StatefulSet { 119 container := corev1.Container{ 120 Name: "mysql", 121 VolumeMounts: []corev1.VolumeMount{{ 122 Name: "mysql-config", 123 MountPath: "/mnt/config", 124 }}, 125 } 126 return testapps.NewStatefulSetFactory(testCtx.DefaultNamespace, "mock-sts", clusterName, mysqlCompName). 127 AddAppNameLabel("mock-app"). 128 AddAppInstanceLabel(clusterName). 129 AddAppComponentLabel(mysqlCompName). 130 SetReplicas(1).AddContainer(container). 131 AddVolumeClaimTemplate(corev1.PersistentVolumeClaim{ 132 ObjectMeta: metav1.ObjectMeta{Name: testapps.DataVolumeName}, 133 Spec: testapps.NewPVC("1Gi"), 134 }).GetObject() 135 } 136 newReqCtx := func() intctrlutil.RequestCtx { 137 reqCtx := intctrlutil.RequestCtx{ 138 Ctx: testCtx.Ctx, 139 Log: logger, 140 Recorder: clusterRecorder, 141 } 142 return reqCtx 143 } 144 newAllFieldsComponent := func(clusterDef *appsv1alpha1.ClusterDefinition, clusterVersion *appsv1alpha1.ClusterVersion) *component.SynthesizedComponent { 145 cluster, clusterDef, clusterVersion, _ := newAllFieldsClusterObj(clusterDef, clusterVersion, false) 146 reqCtx := newReqCtx() 147 By("assign every available fields") 148 component, err := component.BuildComponent( 149 reqCtx, 150 nil, 151 cluster, 152 clusterDef, 153 &clusterDef.Spec.ComponentDefs[0], 154 &cluster.Spec.ComponentSpecs[0], 155 nil, 156 &clusterVersion.Spec.ComponentVersions[0]) 157 Expect(err).Should(Succeed()) 158 Expect(component).ShouldNot(BeNil()) 159 return component 160 } 161 newClusterObjs := func(clusterDefObj *appsv1alpha1.ClusterDefinition) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster, *component.SynthesizedComponent) { 162 cluster, clusterDef, clusterVersion, _ := newAllFieldsClusterObj(clusterDefObj, nil, false) 163 synthesizedComponent := newAllFieldsComponent(clusterDef, clusterVersion) 164 return clusterDef, cluster, synthesizedComponent 165 } 166 167 Context("has helper function which builds specific object from cue template", func() { 168 It("builds PVC correctly", func() { 169 snapshotName := "test-snapshot-name" 170 sts := newStsObj() 171 _, cluster, synthesizedComponent := newClusterObjs(nil) 172 pvcKey := types.NamespacedName{ 173 Namespace: "default", 174 Name: "data-mysql-01-replicasets-0", 175 } 176 pvc := BuildPVC(cluster, synthesizedComponent, &synthesizedComponent.VolumeClaimTemplates[0], pvcKey, snapshotName) 177 Expect(pvc).ShouldNot(BeNil()) 178 Expect(pvc.Spec.AccessModes).Should(Equal(sts.Spec.VolumeClaimTemplates[0].Spec.AccessModes)) 179 Expect(pvc.Spec.Resources).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.Resources)) 180 Expect(pvc.Spec.StorageClassName).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.StorageClassName)) 181 Expect(pvc.Labels[constant.VolumeTypeLabelKey]).ShouldNot(BeEmpty()) 182 }) 183 184 It("builds Conn. Credential correctly", func() { 185 var ( 186 clusterDefObj = testapps.NewClusterDefFactoryWithConnCredential("conn-cred").GetObject() 187 clusterDef, cluster, synthesizedComponent = newClusterObjs(clusterDefObj) 188 ) 189 credential := BuildConnCredential(clusterDef, cluster, synthesizedComponent) 190 Expect(credential).ShouldNot(BeNil()) 191 Expect(credential.Labels["apps.kubeblocks.io/cluster-type"]).Should(BeEmpty()) 192 By("setting type") 193 characterType := "test-character-type" 194 clusterDef.Spec.Type = characterType 195 credential = BuildConnCredential(clusterDef, cluster, synthesizedComponent) 196 Expect(credential).ShouldNot(BeNil()) 197 Expect(credential.Labels["apps.kubeblocks.io/cluster-type"]).Should(Equal(characterType)) 198 // "username": "root", 199 // "SVC_FQDN": "$(SVC_FQDN)", 200 // "RANDOM_PASSWD": "$(RANDOM_PASSWD)", 201 // "tcpEndpoint": "tcp:$(SVC_FQDN):$(SVC_PORT_mysql)", 202 // "paxosEndpoint": "paxos:$(SVC_FQDN):$(SVC_PORT_paxos)", 203 // "UUID": "$(UUID)", 204 // "UUID_B64": "$(UUID_B64)", 205 // "UUID_STR_B64": "$(UUID_STR_B64)", 206 // "UUID_HEX": "$(UUID_HEX)", 207 Expect(credential.StringData).ShouldNot(BeEmpty()) 208 Expect(credential.StringData["username"]).Should(Equal("root")) 209 210 for _, v := range []string{ 211 "SVC_FQDN", 212 "RANDOM_PASSWD", 213 "UUID", 214 "UUID_B64", 215 "UUID_STR_B64", 216 "UUID_HEX", 217 "HEADLESS_SVC_FQDN", 218 } { 219 Expect(credential.StringData[v]).ShouldNot(BeEquivalentTo(fmt.Sprintf("$(%s)", v))) 220 } 221 Expect(credential.StringData["RANDOM_PASSWD"]).Should(HaveLen(8)) 222 svcFQDN := fmt.Sprintf("%s-%s.%s.svc", cluster.Name, synthesizedComponent.Name, cluster.Namespace) 223 headlessSvcFQDN := fmt.Sprintf("%s-%s-headless.%s.svc", cluster.Name, synthesizedComponent.Name, cluster.Namespace) 224 var mysqlPort corev1.ServicePort 225 var paxosPort corev1.ServicePort 226 for _, s := range synthesizedComponent.Services[0].Spec.Ports { 227 switch s.Name { 228 case "mysql": 229 mysqlPort = s 230 case "paxos": 231 paxosPort = s 232 } 233 } 234 Expect(credential.StringData["SVC_FQDN"]).Should(Equal(svcFQDN)) 235 Expect(credential.StringData["HEADLESS_SVC_FQDN"]).Should(Equal(headlessSvcFQDN)) 236 Expect(credential.StringData["tcpEndpoint"]).Should(Equal(fmt.Sprintf("tcp:%s:%d", svcFQDN, mysqlPort.Port))) 237 Expect(credential.StringData["paxosEndpoint"]).Should(Equal(fmt.Sprintf("paxos:%s:%d", svcFQDN, paxosPort.Port))) 238 239 }) 240 241 It("builds Conn. Credential during restoring from backup", func() { 242 originalPassword := "test-passw0rd" 243 encryptionKey := "encryptionKey" 244 viper.Set(constant.CfgKeyDPEncryptionKey, encryptionKey) 245 var ( 246 clusterDefObj = testapps.NewClusterDefFactoryWithConnCredential("conn-cred").GetObject() 247 clusterDef, cluster, synthesizedComponent = newClusterObjs(clusterDefObj) 248 ) 249 e := intctrlutil.NewEncryptor(encryptionKey) 250 ciphertext, _ := e.Encrypt([]byte(originalPassword)) 251 cluster.Annotations[constant.RestoreFromBackupAnnotationKey] = fmt.Sprintf(`{"%s":{"%s":"%s"}}`, 252 synthesizedComponent.Name, constant.ConnectionPassword, ciphertext) 253 credential := BuildConnCredential(clusterDef, cluster, synthesizedComponent) 254 Expect(credential).ShouldNot(BeNil()) 255 Expect(credential.StringData["RANDOM_PASSWD"]).Should(Equal(originalPassword)) 256 }) 257 258 It("builds StatefulSet correctly", func() { 259 reqCtx := newReqCtx() 260 _, cluster, synthesizedComponent := newClusterObjs(nil) 261 envConfigName := "test-env-config-name" 262 263 sts, err := BuildSts(reqCtx, cluster, synthesizedComponent, envConfigName) 264 Expect(err).Should(BeNil()) 265 Expect(sts).ShouldNot(BeNil()) 266 // test replicas = 0 267 newComponent := *synthesizedComponent 268 newComponent.Replicas = 0 269 sts, err = BuildSts(reqCtx, cluster, &newComponent, envConfigName) 270 Expect(err).Should(BeNil()) 271 Expect(sts).ShouldNot(BeNil()) 272 Expect(*sts.Spec.Replicas).Should(Equal(int32(0))) 273 Expect(sts.Spec.VolumeClaimTemplates[0].Labels[constant.VolumeTypeLabelKey]). 274 Should(Equal(string(appsv1alpha1.VolumeTypeData))) 275 // test workload type replication 276 replComponent := *synthesizedComponent 277 replComponent.Replicas = 2 278 replComponent.WorkloadType = appsv1alpha1.Replication 279 sts, err = BuildSts(reqCtx, cluster, &replComponent, envConfigName) 280 Expect(err).Should(BeNil()) 281 Expect(sts).ShouldNot(BeNil()) 282 Expect(*sts.Spec.Replicas).Should(BeEquivalentTo(2)) 283 // test extra envs 284 Expect(sts.Spec.Template.Spec.Containers).ShouldNot(BeEmpty()) 285 for _, container := range sts.Spec.Template.Spec.Containers { 286 isContainEnv := false 287 for _, env := range container.Env { 288 if env.Name == "mock-key" && env.Value == "mock-value" { 289 isContainEnv = true 290 break 291 } 292 } 293 Expect(isContainEnv).Should(BeTrue()) 294 } 295 }) 296 297 It("builds RSM correctly", func() { 298 reqCtx := newReqCtx() 299 _, cluster, synthesizedComponent := newClusterObjs(nil) 300 envConfigName := "test-env-config-name" 301 302 rsm, err := BuildRSM(reqCtx, cluster, synthesizedComponent, envConfigName) 303 Expect(err).Should(BeNil()) 304 Expect(rsm).ShouldNot(BeNil()) 305 306 By("set replicas = 0") 307 newComponent := *synthesizedComponent 308 newComponent.Replicas = 0 309 rsm, err = BuildRSM(reqCtx, cluster, &newComponent, envConfigName) 310 Expect(err).Should(BeNil()) 311 Expect(rsm).ShouldNot(BeNil()) 312 Expect(*rsm.Spec.Replicas).Should(Equal(int32(0))) 313 Expect(rsm.Spec.VolumeClaimTemplates[0].Labels[constant.VolumeTypeLabelKey]). 314 Should(Equal(string(appsv1alpha1.VolumeTypeData))) 315 316 By("set workload type to Replication") 317 replComponent := *synthesizedComponent 318 replComponent.Replicas = 2 319 replComponent.WorkloadType = appsv1alpha1.Replication 320 rsm, err = BuildRSM(reqCtx, cluster, &replComponent, envConfigName) 321 Expect(err).Should(BeNil()) 322 Expect(rsm).ShouldNot(BeNil()) 323 Expect(*rsm.Spec.Replicas).Should(BeEquivalentTo(2)) 324 // test extra envs 325 Expect(rsm.Spec.Template.Spec.Containers).ShouldNot(BeEmpty()) 326 for _, container := range rsm.Spec.Template.Spec.Containers { 327 isContainEnv := false 328 for _, env := range container.Env { 329 if env.Name == "mock-key" && env.Value == "mock-value" { 330 isContainEnv = true 331 break 332 } 333 } 334 Expect(isContainEnv).Should(BeTrue()) 335 } 336 337 // test service labels 338 expectLabelsExist := func(labels map[string]string) { 339 expectedLabels := map[string]string{ 340 constant.AppManagedByLabelKey: constant.AppName, 341 constant.AppNameLabelKey: replComponent.ClusterDefName, 342 constant.AppInstanceLabelKey: cluster.Name, 343 constant.KBAppComponentLabelKey: replComponent.Name, 344 constant.AppComponentLabelKey: replComponent.CompDefName, 345 } 346 Expect(labels).ShouldNot(BeNil()) 347 for k, ev := range expectedLabels { 348 v, ok := labels[k] 349 Expect(ok).Should(BeTrue()) 350 Expect(v).Should(Equal(ev)) 351 } 352 } 353 Expect(rsm.Spec.Service).ShouldNot(BeNil()) 354 expectLabelsExist(rsm.Spec.Service.Labels) 355 356 // test roles 357 Expect(rsm.Spec.Roles).Should(HaveLen(2)) 358 for _, roleName := range []string{constant.Primary, constant.Secondary} { 359 Expect(slices.IndexFunc(rsm.Spec.Roles, func(role workloads.ReplicaRole) bool { 360 return role.Name == roleName 361 })).Should(BeNumerically(">", -1)) 362 } 363 364 // test role probe 365 Expect(rsm.Spec.RoleProbe).ShouldNot(BeNil()) 366 367 // test member update strategy 368 Expect(rsm.Spec.MemberUpdateStrategy).ShouldNot(BeNil()) 369 Expect(*rsm.Spec.MemberUpdateStrategy).Should(BeEquivalentTo(workloads.SerialUpdateStrategy)) 370 371 By("set workload type to Consensus") 372 csComponent := *synthesizedComponent 373 csComponent.Replicas = 3 374 csComponent.WorkloadType = appsv1alpha1.Consensus 375 csComponent.CharacterType = "mysql" 376 csComponent.ConsensusSpec = appsv1alpha1.NewConsensusSetSpec() 377 csComponent.ConsensusSpec.UpdateStrategy = appsv1alpha1.BestEffortParallelStrategy 378 rsm, err = BuildRSM(reqCtx, cluster, &csComponent, envConfigName) 379 Expect(err).Should(BeNil()) 380 Expect(rsm).ShouldNot(BeNil()) 381 382 // test roles 383 Expect(rsm.Spec.Roles).Should(HaveLen(1)) 384 Expect(rsm.Spec.Roles[0].Name).Should(Equal(appsv1alpha1.DefaultLeader.Name)) 385 386 // test role probe 387 Expect(rsm.Spec.RoleProbe).ShouldNot(BeNil()) 388 389 // test member update strategy 390 Expect(rsm.Spec.MemberUpdateStrategy).ShouldNot(BeNil()) 391 Expect(*rsm.Spec.MemberUpdateStrategy).Should(BeEquivalentTo(workloads.BestEffortParallelUpdateStrategy)) 392 }) 393 394 It("builds PDB correctly", func() { 395 _, cluster, synthesizedComponent := newClusterObjs(nil) 396 pdb := BuildPDB(cluster, synthesizedComponent) 397 Expect(pdb).ShouldNot(BeNil()) 398 }) 399 400 It("builds BackupJob correctly", func() { 401 _, cluster, synthesizedComponent := newClusterObjs(nil) 402 backupJobKey := types.NamespacedName{ 403 Namespace: "default", 404 Name: "test-backup-job", 405 } 406 backupPolicyName := "test-backup-policy" 407 backupJob := BuildBackup(cluster, synthesizedComponent, backupPolicyName, backupJobKey, "snapshot") 408 Expect(backupJob).ShouldNot(BeNil()) 409 }) 410 411 It("builds ConfigMap with template correctly", func() { 412 config := map[string]string{} 413 _, cluster, synthesizedComponent := newClusterObjs(nil) 414 tplCfg := appsv1alpha1.ComponentConfigSpec{ 415 ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ 416 Name: "test-config-tpl", 417 TemplateRef: "test-config-tpl", 418 }, 419 ConfigConstraintRef: "test-config-constraint", 420 } 421 configmap := BuildConfigMapWithTemplate(cluster, synthesizedComponent, config, 422 "test-cm", tplCfg.ComponentTemplateSpec) 423 Expect(configmap).ShouldNot(BeNil()) 424 }) 425 426 It("builds config manager sidecar container correctly", func() { 427 _, cluster, synthesizedComponent := newClusterObjs(nil) 428 cfg := BuildEnvConfig(cluster, synthesizedComponent) 429 sidecarRenderedParam := &cfgcm.CfgManagerBuildParams{ 430 ManagerName: "cfgmgr", 431 SecreteName: "test-secret", 432 ComponentName: synthesizedComponent.Name, 433 CharacterType: synthesizedComponent.CharacterType, 434 EnvConfigName: cfg.Name, 435 Image: constant.KBToolsImage, 436 Args: []string{}, 437 Envs: []corev1.EnvVar{}, 438 Volumes: []corev1.VolumeMount{}, 439 Cluster: cluster, 440 } 441 configmap, err := BuildCfgManagerContainer(sidecarRenderedParam, synthesizedComponent) 442 Expect(err).Should(BeNil()) 443 Expect(configmap).ShouldNot(BeNil()) 444 Expect(configmap.SecurityContext).Should(BeNil()) 445 }) 446 447 It("builds config manager sidecar container correctly", func() { 448 _, cluster, synthesizedComponent := newClusterObjs(nil) 449 sidecarRenderedParam := &cfgcm.CfgManagerBuildParams{ 450 ManagerName: "cfgmgr", 451 CharacterType: "mysql", 452 SecreteName: "test-secret", 453 Image: constant.KBToolsImage, 454 ShareProcessNamespace: true, 455 Args: []string{}, 456 Envs: []corev1.EnvVar{}, 457 Volumes: []corev1.VolumeMount{}, 458 Cluster: cluster, 459 } 460 configmap, err := BuildCfgManagerContainer(sidecarRenderedParam, synthesizedComponent) 461 Expect(err).Should(BeNil()) 462 Expect(configmap).ShouldNot(BeNil()) 463 Expect(configmap.SecurityContext).ShouldNot(BeNil()) 464 Expect(configmap.SecurityContext.RunAsUser).ShouldNot(BeNil()) 465 Expect(*configmap.SecurityContext.RunAsUser).Should(BeEquivalentTo(int64(0))) 466 }) 467 468 It("builds restore job correctly", func() { 469 key := types.NamespacedName{Name: "restore", Namespace: "default"} 470 volumes := []corev1.Volume{} 471 volumeMounts := []corev1.VolumeMount{} 472 env := []corev1.EnvVar{} 473 component := &component.SynthesizedComponent{ 474 Name: mysqlCompName, 475 } 476 cluster := &appsv1alpha1.Cluster{ 477 ObjectMeta: metav1.ObjectMeta{Namespace: key.Namespace}, 478 Spec: appsv1alpha1.ClusterSpec{ 479 Tolerations: []corev1.Toleration{ 480 { 481 Key: "testKey", 482 Value: "testVaule", 483 Operator: corev1.TolerationOpExists, 484 }, 485 }, 486 }, 487 } 488 job, err := BuildRestoreJob(cluster, component, key.Name, "", []string{"sh"}, volumes, volumeMounts, env, nil) 489 Expect(err).Should(BeNil()) 490 Expect(job.Spec.Template.Spec.Tolerations[0].Key).Should(Equal("testKey")) 491 Expect(job).ShouldNot(BeNil()) 492 Expect(job.Name).Should(Equal(key.Name)) 493 }) 494 495 It("builds volume snapshot class correctly", func() { 496 className := "vsc-test" 497 driverName := "csi-driver-test" 498 obj := BuildVolumeSnapshotClass(className, driverName) 499 Expect(obj).ShouldNot(BeNil()) 500 Expect(obj.Name).Should(Equal(className)) 501 Expect(obj.Driver).Should(Equal(driverName)) 502 }) 503 504 It("builds cfg manager tools correctly", func() { 505 _, cluster, synthesizedComponent := newClusterObjs(nil) 506 cfgManagerParams := &cfgcm.CfgManagerBuildParams{ 507 ManagerName: constant.ConfigSidecarName, 508 SecreteName: component.GenerateConnCredential(cluster.Name), 509 EnvConfigName: component.GenerateComponentEnvName(cluster.Name, synthesizedComponent.Name), 510 Image: viper.GetString(constant.KBToolsImage), 511 Cluster: cluster, 512 ConfigLazyRenderedVolumes: make(map[string]corev1.VolumeMount), 513 } 514 toolContainers := []appsv1alpha1.ToolConfig{ 515 {Name: "test-tool", Image: "test-image", Command: []string{"sh"}}, 516 } 517 518 obj, err := BuildCfgManagerToolsContainer(cfgManagerParams, synthesizedComponent, toolContainers, map[string]cfgcm.ConfigSpecMeta{}) 519 Expect(err).Should(BeNil()) 520 Expect(obj).ShouldNot(BeEmpty()) 521 }) 522 523 It("builds serviceaccount correctly", func() { 524 _, cluster, _ := newClusterObjs(nil) 525 expectName := fmt.Sprintf("kb-%s", cluster.Name) 526 sa := BuildServiceAccount(cluster) 527 Expect(sa).ShouldNot(BeNil()) 528 Expect(sa.Name).Should(Equal(expectName)) 529 }) 530 531 It("builds rolebinding correctly", func() { 532 _, cluster, _ := newClusterObjs(nil) 533 expectName := fmt.Sprintf("kb-%s", cluster.Name) 534 rb := BuildRoleBinding(cluster) 535 Expect(rb).ShouldNot(BeNil()) 536 Expect(rb.Name).Should(Equal(expectName)) 537 }) 538 539 It("builds clusterrolebinding correctly", func() { 540 _, cluster, _ := newClusterObjs(nil) 541 expectName := fmt.Sprintf("kb-%s", cluster.Name) 542 crb := BuildClusterRoleBinding(cluster) 543 Expect(crb).ShouldNot(BeNil()) 544 Expect(crb.Name).Should(Equal(expectName)) 545 }) 546 }) 547 })