github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/apis/workloads/v1alpha1/replicatedstatemachine_webhook_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 v1alpha1 21 22 import ( 23 . "github.com/onsi/ginkgo/v2" 24 . "github.com/onsi/gomega" 25 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 29 "github.com/1aal/kubeblocks/pkg/constant" 30 ) 31 32 var _ = Describe("ReplicatedStateMachine Webhook", func() { 33 Context("spec validation", func() { 34 const name = "test-replicated-state-machine" 35 var rsm *ReplicatedStateMachine 36 37 BeforeEach(func() { 38 commonLabels := map[string]string{ 39 constant.AppManagedByLabelKey: constant.AppName, 40 constant.AppNameLabelKey: "ClusterDefName", 41 constant.AppComponentLabelKey: "CompDefName", 42 constant.AppInstanceLabelKey: "clusterName", 43 constant.KBAppComponentLabelKey: "componentName", 44 } 45 replicas := int32(1) 46 rsm = &ReplicatedStateMachine{ 47 ObjectMeta: metav1.ObjectMeta{ 48 Name: name, 49 Namespace: testCtx.DefaultNamespace, 50 }, 51 Spec: ReplicatedStateMachineSpec{ 52 Replicas: &replicas, 53 Selector: &metav1.LabelSelector{ 54 MatchLabels: commonLabels, 55 }, 56 Service: &corev1.Service{}, 57 RoleProbe: &RoleProbe{ 58 CustomHandler: []Action{ 59 { 60 Image: "foo", 61 Command: []string{"bar"}, 62 }, 63 }, 64 }, 65 Template: corev1.PodTemplateSpec{ 66 ObjectMeta: metav1.ObjectMeta{ 67 Labels: commonLabels, 68 }, 69 Spec: corev1.PodSpec{ 70 Containers: []corev1.Container{ 71 { 72 Name: "foo", 73 Image: "bar", 74 }, 75 }, 76 }, 77 }, 78 }, 79 } 80 }) 81 82 It("should return an error if no leader set", func() { 83 rsm.Spec.Roles = []ReplicaRole{ 84 { 85 Name: "leader", 86 IsLeader: false, 87 AccessMode: ReadWriteMode, 88 }, 89 } 90 err := k8sClient.Create(ctx, rsm) 91 Expect(err).ShouldNot(BeNil()) 92 Expect(err.Error()).Should(ContainSubstring("leader is required")) 93 }) 94 95 It("should return an error if servicePort not provided", func() { 96 rsm.Spec.Roles = []ReplicaRole{ 97 { 98 Name: "leader", 99 IsLeader: true, 100 AccessMode: ReadWriteMode, 101 }, 102 } 103 err := k8sClient.Create(ctx, rsm) 104 Expect(err).ShouldNot(BeNil()) 105 Expect(err.Error()).Should(ContainSubstring("servicePort must provide")) 106 }) 107 108 It("should succeed if spec is well defined", func() { 109 rsm.Spec.Roles = []ReplicaRole{ 110 { 111 Name: "leader", 112 IsLeader: true, 113 AccessMode: ReadWriteMode, 114 }, 115 } 116 rsm.Spec.Service.Spec.Ports = []corev1.ServicePort{ 117 { 118 Name: "foo", 119 Protocol: "tcp", 120 Port: 12345, 121 }, 122 } 123 Expect(k8sClient.Create(ctx, rsm)).Should(Succeed()) 124 Expect(k8sClient.Delete(ctx, rsm)).Should(Succeed()) 125 }) 126 }) 127 })