github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/operations/vertical_scaling_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 operations 21 22 import ( 23 "time" 24 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 29 corev1 "k8s.io/api/core/v1" 30 "k8s.io/apimachinery/pkg/api/resource" 31 "sigs.k8s.io/controller-runtime/pkg/client" 32 33 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 34 "github.com/1aal/kubeblocks/pkg/constant" 35 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 36 "github.com/1aal/kubeblocks/pkg/generics" 37 testapps "github.com/1aal/kubeblocks/pkg/testutil/apps" 38 testk8s "github.com/1aal/kubeblocks/pkg/testutil/k8s" 39 ) 40 41 var _ = Describe("VerticalScaling OpsRequest", func() { 42 43 var ( 44 randomStr = testCtx.GetRandomStr() 45 clusterDefinitionName = "cluster-definition-for-ops-" + randomStr 46 clusterVersionName = "clusterversion-for-ops-" + randomStr 47 clusterName = "cluster-for-ops-" + randomStr 48 ) 49 cleanEnv := func() { 50 // must wait till resources deleted and no longer existed before the testcases start, 51 // otherwise if later it needs to create some new resource objects with the same name, 52 // in race conditions, it will find the existence of old objects, resulting failure to 53 // create the new objects. 54 By("clean resources") 55 56 // delete cluster(and all dependent sub-resources), clusterversion and clusterdef 57 testapps.ClearClusterResources(&testCtx) 58 59 // delete rest resources 60 inNS := client.InNamespace(testCtx.DefaultNamespace) 61 ml := client.HasLabels{testCtx.TestObjLabelKey} 62 // namespaced 63 testapps.ClearResources(&testCtx, generics.OpsRequestSignature, inNS, ml) 64 } 65 66 BeforeEach(cleanEnv) 67 68 AfterEach(cleanEnv) 69 70 Context("Test OpsRequest", func() { 71 72 testVerticalScaling := func(verticalScaling []appsv1alpha1.VerticalScaling) { 73 By("init operations resources ") 74 reqCtx := intctrlutil.RequestCtx{Ctx: ctx} 75 opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) 76 77 By("create VerticalScaling ops") 78 ops := testapps.NewOpsRequestObj("vertical-scaling-ops-"+randomStr, testCtx.DefaultNamespace, 79 clusterName, appsv1alpha1.VerticalScalingType) 80 81 ops.Spec.VerticalScalingList = verticalScaling 82 opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) 83 By("test save last configuration and OpsRequest phase is Running") 84 _, err := GetOpsManager().Do(reqCtx, k8sClient, opsRes) 85 Expect(err).ShouldNot(HaveOccurred()) 86 Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(ops))).Should(Equal(appsv1alpha1.OpsCreatingPhase)) 87 88 By("test vertical scale action function") 89 vsHandler := verticalScalingHandler{} 90 Expect(vsHandler.Action(reqCtx, k8sClient, opsRes)).Should(Succeed()) 91 _, _, err = vsHandler.ReconcileAction(reqCtx, k8sClient, opsRes) 92 Expect(err).ShouldNot(HaveOccurred()) 93 } 94 95 It("vertical scaling by resource", func() { 96 verticalScaling := []appsv1alpha1.VerticalScaling{ 97 { 98 ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, 99 ResourceRequirements: corev1.ResourceRequirements{ 100 Requests: corev1.ResourceList{ 101 corev1.ResourceCPU: resource.MustParse("400m"), 102 corev1.ResourceMemory: resource.MustParse("300Mi"), 103 }, 104 Limits: corev1.ResourceList{ 105 corev1.ResourceCPU: resource.MustParse("400m"), 106 corev1.ResourceMemory: resource.MustParse("300Mi"), 107 }, 108 }, 109 }, 110 } 111 testVerticalScaling(verticalScaling) 112 }) 113 114 It("vertical scaling by class", func() { 115 verticalScaling := []appsv1alpha1.VerticalScaling{ 116 { 117 ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, 118 ClassDefRef: &appsv1alpha1.ClassDefRef{ 119 Class: testapps.Class1c1gName, 120 }, 121 }, 122 } 123 testVerticalScaling(verticalScaling) 124 }) 125 126 It("cancel vertical scaling opsRequest", func() { 127 By("init operations resources with CLusterDefinition/ClusterVersion/Hybrid components Cluster/consensus Pods") 128 reqCtx := intctrlutil.RequestCtx{Ctx: ctx} 129 opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) 130 podList := initConsensusPods(ctx, k8sClient, opsRes, clusterName) 131 132 By("create VerticalScaling ops") 133 ops := testapps.NewOpsRequestObj("vertical-scaling-ops-"+randomStr, testCtx.DefaultNamespace, 134 clusterName, appsv1alpha1.VerticalScalingType) 135 ops.Spec.VerticalScalingList = []appsv1alpha1.VerticalScaling{ 136 { 137 ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, 138 ResourceRequirements: corev1.ResourceRequirements{ 139 Limits: corev1.ResourceList{ 140 corev1.ResourceCPU: resource.MustParse("400m"), 141 corev1.ResourceMemory: resource.MustParse("300Mi"), 142 }, 143 }, 144 }, 145 } 146 opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) 147 148 By("mock opsRequest is Running") 149 mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp) 150 Expect(testapps.ChangeObjStatus(&testCtx, opsRes.OpsRequest, func() { 151 opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsRunningPhase 152 opsRes.OpsRequest.Status.StartTimestamp = metav1.Time{Time: time.Now()} 153 })).ShouldNot(HaveOccurred()) 154 // wait 1 second for checking progress 155 time.Sleep(time.Second) 156 reCreatePod := func(pod *corev1.Pod) { 157 pod.Kind = constant.PodKind 158 testk8s.MockPodIsTerminating(ctx, testCtx, pod) 159 testk8s.RemovePodFinalizer(ctx, testCtx, pod) 160 testapps.MockConsensusComponentStsPod(&testCtx, nil, clusterName, consensusComp, pod.Name, "leader", "ReadWrite") 161 } 162 163 By("mock podList[0] rolling update successfully by re-creating it") 164 reCreatePod(&podList[0]) 165 166 By("reconcile opsRequest status") 167 _, err := GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) 168 Expect(err).ShouldNot(HaveOccurred()) 169 170 By("the progress status of pod[0] should be Succeed ") 171 progressDetails := opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails 172 progressDetail := findStatusProgressDetail(progressDetails, getProgressObjectKey("", podList[0].Name)) 173 Expect(progressDetail.Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) 174 175 By("cancel verticalScaling opsRequest") 176 cancelOpsRequest(reqCtx, opsRes, opsRes.OpsRequest.Status.StartTimestamp.Time) 177 178 By("mock podList[0] rolled back successfully by re-creating it") 179 reCreatePod(&podList[0]) 180 181 By("reconcile opsRequest status after canceling opsRequest and component is Running after rolling update") 182 mockConsensusCompToRunning(opsRes) 183 _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) 184 Expect(err).ShouldNot(HaveOccurred()) 185 186 By("expect for cancelling opsRequest successfully") 187 opsRequest := opsRes.OpsRequest 188 Expect(opsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsCancelledPhase)) 189 Expect(opsRequest.Status.Progress).Should(Equal("1/1")) 190 progressDetails = opsRequest.Status.Components[consensusComp].ProgressDetails 191 Expect(len(progressDetails)).Should(Equal(1)) 192 progressDetail = findStatusProgressDetail(progressDetails, getProgressObjectKey("", podList[0].Name)) 193 Expect(progressDetail.Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) 194 Expect(progressDetail.Message).Should(ContainSubstring("with rollback")) 195 }) 196 }) 197 })