github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/builder/builder_replicated_state_machine_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 builder 21 22 import ( 23 . "github.com/onsi/ginkgo/v2" 24 . "github.com/onsi/gomega" 25 26 apps "k8s.io/api/apps/v1" 27 corev1 "k8s.io/api/core/v1" 28 "k8s.io/apimachinery/pkg/api/resource" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/util/intstr" 31 32 workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1" 33 ) 34 35 var _ = Describe("replicated_state_machine builder", func() { 36 It("should work well", func() { 37 const ( 38 name = "foo" 39 ns = "default" 40 selectorKey1, selectorValue1 = "foo-1", "bar-1" 41 selectorKey2, selectorValue2 = "foo-2", "bar-2" 42 selectorKey3, selectorValue3 = "foo-3", "bar-3" 43 selectorKey4, selectorValue4 = "foo-4", "bar-4" 44 serviceName = "foo" 45 replicas = int32(5) 46 port = int32(12345) 47 policy = apps.OrderedReadyPodManagement 48 ) 49 selectors := map[string]string{selectorKey4: selectorValue4} 50 role := workloads.ReplicaRole{ 51 Name: "foo", 52 AccessMode: workloads.ReadWriteMode, 53 IsLeader: true, 54 CanVote: true, 55 } 56 reconfiguration := workloads.MembershipReconfiguration{ 57 SwitchoverAction: &workloads.Action{ 58 Image: name, 59 Command: []string{"bar"}, 60 }, 61 } 62 pod := NewPodBuilder(ns, "foo"). 63 AddContainer(corev1.Container{ 64 Name: "foo", 65 Image: "bar", 66 Ports: []corev1.ContainerPort{ 67 { 68 Name: "foo", 69 Protocol: corev1.ProtocolTCP, 70 ContainerPort: port, 71 }, 72 }, 73 }).GetObject() 74 template := corev1.PodTemplateSpec{ 75 ObjectMeta: pod.ObjectMeta, 76 Spec: pod.Spec, 77 } 78 vcs := []corev1.PersistentVolumeClaim{ 79 { 80 ObjectMeta: metav1.ObjectMeta{ 81 Name: "foo-1", 82 Namespace: ns, 83 }, 84 Spec: corev1.PersistentVolumeClaimSpec{ 85 VolumeName: "foo-1", 86 Resources: corev1.ResourceRequirements{ 87 Requests: corev1.ResourceList{ 88 corev1.ResourceCPU: resource.MustParse("500m"), 89 }, 90 }, 91 }, 92 }, 93 } 94 vc := corev1.PersistentVolumeClaim{ 95 ObjectMeta: metav1.ObjectMeta{ 96 Name: "foo-2", 97 Namespace: ns, 98 }, 99 Spec: corev1.PersistentVolumeClaimSpec{ 100 VolumeName: "foo-2", 101 Resources: corev1.ResourceRequirements{ 102 Requests: corev1.ResourceList{ 103 corev1.ResourceCPU: resource.MustParse("600m"), 104 }, 105 }, 106 }, 107 } 108 partition, maxUnavailable := int32(3), intstr.FromInt(2) 109 strategy := apps.StatefulSetUpdateStrategy{ 110 Type: apps.RollingUpdateStatefulSetStrategyType, 111 RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ 112 Partition: &partition, 113 MaxUnavailable: &maxUnavailable, 114 }, 115 } 116 strategyType := apps.OnDeleteStatefulSetStrategyType 117 delay := int32(10) 118 roleProbe := workloads.RoleProbe{InitialDelaySeconds: delay} 119 actions := []workloads.Action{ 120 { 121 Image: "foo-1", 122 Command: []string{"bar-1"}, 123 }, 124 } 125 action := workloads.Action{ 126 Image: "foo-2", 127 Command: []string{"bar-2"}, 128 } 129 memberUpdateStrategy := workloads.BestEffortParallelUpdateStrategy 130 service := &corev1.Service{ 131 Spec: corev1.ServiceSpec{ 132 Ports: []corev1.ServicePort{ 133 { 134 Name: "foo", 135 Protocol: corev1.ProtocolTCP, 136 Port: port, 137 }, 138 }, 139 }, 140 } 141 alternativeServices := []corev1.Service{ 142 { 143 ObjectMeta: metav1.ObjectMeta{ 144 Name: "bar", 145 }, 146 Spec: corev1.ServiceSpec{ 147 Ports: []corev1.ServicePort{ 148 { 149 Name: "bar", 150 Protocol: corev1.ProtocolTCP, 151 Port: port, 152 }, 153 }, 154 }, 155 }, 156 } 157 paused := true 158 credential := workloads.Credential{ 159 Username: workloads.CredentialVar{Value: "foo"}, 160 Password: workloads.CredentialVar{Value: "bar"}, 161 } 162 rsm := NewReplicatedStateMachineBuilder(ns, name). 163 SetReplicas(replicas). 164 AddMatchLabel(selectorKey1, selectorValue1). 165 AddMatchLabels(selectorKey2, selectorValue2, selectorKey3, selectorValue3). 166 AddMatchLabelsInMap(selectors). 167 SetServiceName(serviceName). 168 SetRoles([]workloads.ReplicaRole{role}). 169 SetMembershipReconfiguration(&reconfiguration). 170 SetTemplate(template). 171 SetVolumeClaimTemplates(vcs...). 172 AddVolumeClaimTemplates(vc). 173 SetPodManagementPolicy(policy). 174 SetUpdateStrategy(strategy). 175 SetUpdateStrategyType(strategyType). 176 SetRoleProbe(&roleProbe). 177 SetCustomHandler(actions). 178 AddCustomHandler(action). 179 SetMemberUpdateStrategy(&memberUpdateStrategy). 180 SetService(service). 181 SetAlternativeServices(alternativeServices). 182 SetPaused(paused). 183 SetCredential(credential). 184 GetObject() 185 186 Expect(rsm.Name).Should(Equal(name)) 187 Expect(rsm.Namespace).Should(Equal(ns)) 188 Expect(rsm.Spec.Replicas).ShouldNot(BeNil()) 189 Expect(*rsm.Spec.Replicas).Should(Equal(replicas)) 190 Expect(rsm.Spec.Selector).ShouldNot(BeNil()) 191 Expect(rsm.Spec.Selector.MatchLabels).Should(HaveLen(4)) 192 Expect(rsm.Spec.Selector.MatchLabels[selectorKey1]).Should(Equal(selectorValue1)) 193 Expect(rsm.Spec.Selector.MatchLabels[selectorKey2]).Should(Equal(selectorValue2)) 194 Expect(rsm.Spec.Selector.MatchLabels[selectorKey3]).Should(Equal(selectorValue3)) 195 Expect(rsm.Spec.Selector.MatchLabels[selectorKey4]).Should(Equal(selectorValue4)) 196 Expect(rsm.Spec.ServiceName).Should(Equal(serviceName)) 197 Expect(rsm.Spec.Roles).Should(HaveLen(1)) 198 Expect(rsm.Spec.Roles[0]).Should(Equal(role)) 199 Expect(rsm.Spec.MembershipReconfiguration).ShouldNot(BeNil()) 200 Expect(*rsm.Spec.MembershipReconfiguration).Should(Equal(reconfiguration)) 201 Expect(rsm.Spec.Template).Should(Equal(template)) 202 Expect(rsm.Spec.VolumeClaimTemplates).Should(HaveLen(2)) 203 Expect(rsm.Spec.VolumeClaimTemplates[0]).Should(Equal(vcs[0])) 204 Expect(rsm.Spec.VolumeClaimTemplates[1]).Should(Equal(vc)) 205 Expect(rsm.Spec.PodManagementPolicy).Should(Equal(policy)) 206 Expect(rsm.Spec.UpdateStrategy.Type).Should(Equal(strategyType)) 207 Expect(rsm.Spec.UpdateStrategy.RollingUpdate).ShouldNot(BeNil()) 208 Expect(rsm.Spec.UpdateStrategy.RollingUpdate.Partition).ShouldNot(BeNil()) 209 Expect(*rsm.Spec.UpdateStrategy.RollingUpdate.Partition).Should(Equal(partition)) 210 Expect(rsm.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable).ShouldNot(BeNil()) 211 Expect(rsm.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable).ShouldNot(Equal(maxUnavailable)) 212 Expect(rsm.Spec.RoleProbe).ShouldNot(BeNil()) 213 Expect(rsm.Spec.RoleProbe.InitialDelaySeconds).Should(Equal(delay)) 214 Expect(rsm.Spec.RoleProbe.CustomHandler).Should(HaveLen(2)) 215 Expect(rsm.Spec.RoleProbe.CustomHandler[0]).Should(Equal(actions[0])) 216 Expect(rsm.Spec.RoleProbe.CustomHandler[1]).Should(Equal(action)) 217 Expect(rsm.Spec.MemberUpdateStrategy).ShouldNot(BeNil()) 218 Expect(*rsm.Spec.MemberUpdateStrategy).Should(Equal(memberUpdateStrategy)) 219 Expect(rsm.Spec.Service).ShouldNot(BeNil()) 220 Expect(rsm.Spec.Service).Should(BeEquivalentTo(service)) 221 Expect(rsm.Spec.AlternativeServices).ShouldNot(BeNil()) 222 Expect(rsm.Spec.AlternativeServices).Should(Equal(alternativeServices)) 223 Expect(rsm.Spec.Paused).Should(Equal(paused)) 224 Expect(rsm.Spec.Credential).ShouldNot(BeNil()) 225 Expect(*rsm.Spec.Credential).Should(Equal(credential)) 226 }) 227 })