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  })