github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/config_util_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 configuration 21 22 import ( 23 . "github.com/onsi/ginkgo/v2" 24 . "github.com/onsi/gomega" 25 26 corev1 "k8s.io/api/core/v1" 27 "sigs.k8s.io/controller-runtime/pkg/client" 28 "sigs.k8s.io/controller-runtime/pkg/log" 29 30 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 31 cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core" 32 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 33 "github.com/1aal/kubeblocks/pkg/generics" 34 testapps "github.com/1aal/kubeblocks/pkg/testutil/apps" 35 testutil "github.com/1aal/kubeblocks/pkg/testutil/k8s" 36 ) 37 38 var _ = Describe("ConfigWrapper util test", func() { 39 const clusterDefName = "test-clusterdef" 40 const clusterVersionName = "test-clusterversion" 41 const statefulCompDefName = "replicasets" 42 const configSpecName = "mysql-config-tpl" 43 const configVolumeName = "mysql-config" 44 45 var ( 46 // ctrl *gomock.Controller 47 // mockClient *mock_client.MockClient 48 k8sMockClient *testutil.K8sClientMockHelper 49 50 reqCtx = intctrlutil.RequestCtx{ 51 Ctx: ctx, 52 Log: log.FromContext(ctx).WithValues("reconfigure_for_test", testCtx.DefaultNamespace), 53 } 54 ) 55 56 var ( 57 configMapObj *corev1.ConfigMap 58 configConstraintObj *appsv1alpha1.ConfigConstraint 59 clusterDefObj *appsv1alpha1.ClusterDefinition 60 clusterVersionObj *appsv1alpha1.ClusterVersion 61 ) 62 63 cleanEnv := func() { 64 // must wait till resources deleted and no longer existed before the testcases start, 65 // otherwise if later it needs to create some new resource objects with the same name, 66 // in race conditions, it will find the existence of old objects, resulting failure to 67 // create the new objects. 68 By("clean resources") 69 70 // delete rest mocked objects 71 inNS := client.InNamespace(testCtx.DefaultNamespace) 72 ml := client.HasLabels{testCtx.TestObjLabelKey} 73 // namespaced 74 testapps.ClearResources(&testCtx, generics.ConfigMapSignature, inNS, ml) 75 // non-namespaced 76 testapps.ClearResources(&testCtx, generics.ClusterVersionSignature, ml) 77 testapps.ClearResources(&testCtx, generics.ClusterDefinitionSignature, ml) 78 testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) 79 } 80 81 BeforeEach(func() { 82 cleanEnv() 83 84 // Add any setup steps that needs to be executed before each test 85 k8sMockClient = testutil.NewK8sMockClient() 86 87 By("creating a cluster") 88 configMapObj = testapps.CreateCustomizedObj(&testCtx, 89 "resources/mysql-config-template.yaml", &corev1.ConfigMap{}, 90 testCtx.UseDefaultNamespace()) 91 92 configConstraintObj = testapps.CreateCustomizedObj(&testCtx, 93 "resources/mysql-config-constraint.yaml", 94 &appsv1alpha1.ConfigConstraint{}) 95 96 By("Create a clusterDefinition obj") 97 clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). 98 AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). 99 AddConfigTemplate(configSpecName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, configVolumeName). 100 Create(&testCtx).GetObject() 101 102 By("Create a clusterVersion obj") 103 clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). 104 AddComponentVersion(statefulCompDefName). 105 Create(&testCtx).GetObject() 106 }) 107 108 AfterEach(func() { 109 // Add any teardown steps that needs to be executed after each test 110 cleanEnv() 111 112 k8sMockClient.Finish() 113 }) 114 115 Context("clusterdefinition CR test", func() { 116 It("Should success without error", func() { 117 availableTPL := configConstraintObj.DeepCopy() 118 availableTPL.Status.Phase = appsv1alpha1.CCAvailablePhase 119 120 k8sMockClient.MockPatchMethod(testutil.WithSucceed()) 121 k8sMockClient.MockListMethod(testutil.WithSucceed()) 122 k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSequenceResult( 123 map[client.ObjectKey][]testutil.MockGetReturned{ 124 client.ObjectKeyFromObject(configMapObj): {{ 125 Object: nil, 126 Err: cfgcore.MakeError("failed to get cc object"), 127 }, { 128 Object: configMapObj, 129 Err: nil, 130 }}, 131 client.ObjectKeyFromObject(configConstraintObj): {{ 132 Object: nil, 133 Err: cfgcore.MakeError("failed to get cc object"), 134 }, { 135 Object: configConstraintObj, 136 Err: nil, 137 }, { 138 Object: availableTPL, 139 Err: nil, 140 }}, 141 }, 142 ), testutil.WithAnyTimes())) 143 144 _, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 145 Expect(err).ShouldNot(Succeed()) 146 Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) 147 148 _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 149 Expect(err).ShouldNot(Succeed()) 150 Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) 151 152 _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 153 Expect(err).ShouldNot(Succeed()) 154 Expect(err.Error()).Should(ContainSubstring("status not ready")) 155 156 ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 157 Expect(err).Should(Succeed()) 158 Expect(ok).Should(BeTrue()) 159 160 ok, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterDefObj) 161 Expect(err).Should(Succeed()) 162 Expect(ok).Should(BeTrue()) 163 164 _, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterDefObj) 165 Expect(err).Should(Succeed()) 166 167 err = DeleteConfigMapFinalizer(k8sMockClient.Client(), reqCtx, clusterDefObj) 168 Expect(err).Should(Succeed()) 169 }) 170 }) 171 172 Context("clusterdefinition CR test without config Constraints", func() { 173 It("Should success without error", func() { 174 // remove ConfigConstraintRef 175 _, err := handleConfigTemplate(clusterDefObj, func(templates []appsv1alpha1.ComponentConfigSpec) (bool, error) { 176 return true, nil 177 }, func(component *appsv1alpha1.ClusterComponentDefinition) error { 178 if len(component.ConfigSpecs) == 0 { 179 return nil 180 } 181 for i := range component.ConfigSpecs { 182 tpl := &component.ConfigSpecs[i] 183 tpl.ConfigConstraintRef = "" 184 } 185 return nil 186 }) 187 Expect(err).Should(Succeed()) 188 189 availableTPL := configConstraintObj.DeepCopy() 190 availableTPL.Status.Phase = appsv1alpha1.CCAvailablePhase 191 192 k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSequenceResult( 193 map[client.ObjectKey][]testutil.MockGetReturned{ 194 client.ObjectKeyFromObject(configMapObj): {{ 195 Object: nil, 196 Err: cfgcore.MakeError("failed to get cc object"), 197 }, { 198 Object: configMapObj, 199 Err: nil, 200 }}}, 201 ), testutil.WithAnyTimes())) 202 203 _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 204 Expect(err).ShouldNot(Succeed()) 205 Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) 206 207 ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) 208 Expect(err).Should(Succeed()) 209 Expect(ok).Should(BeTrue()) 210 }) 211 }) 212 213 updateAVTemplates := func() { 214 var tpls []appsv1alpha1.ComponentConfigSpec 215 _, err := handleConfigTemplate(clusterDefObj, func(templates []appsv1alpha1.ComponentConfigSpec) (bool, error) { 216 tpls = templates 217 return true, nil 218 }) 219 Expect(err).Should(Succeed()) 220 221 if len(clusterVersionObj.Spec.ComponentVersions) == 0 { 222 return 223 } 224 225 // mock clusterVersionObj config templates 226 clusterVersionObj.Spec.ComponentVersions[0].ConfigSpecs = tpls 227 } 228 229 Context("clusterversion CR test", func() { 230 It("Should success without error", func() { 231 updateAVTemplates() 232 availableTPL := configConstraintObj.DeepCopy() 233 availableTPL.Status.Phase = appsv1alpha1.CCAvailablePhase 234 235 k8sMockClient.MockPatchMethod(testutil.WithSucceed()) 236 k8sMockClient.MockListMethod(testutil.WithSucceed()) 237 k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSequenceResult( 238 map[client.ObjectKey][]testutil.MockGetReturned{ 239 client.ObjectKeyFromObject(configMapObj): {{ 240 Object: nil, 241 Err: cfgcore.MakeError("failed to get cc object"), 242 }, { 243 Object: configMapObj, 244 Err: nil, 245 }}, 246 client.ObjectKeyFromObject(configConstraintObj): {{ 247 Object: nil, 248 Err: cfgcore.MakeError("failed to get cc object"), 249 }, { 250 Object: configConstraintObj, 251 Err: nil, 252 }, { 253 Object: availableTPL, 254 Err: nil, 255 }}, 256 }, 257 ), testutil.WithAnyTimes())) 258 259 _, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) 260 Expect(err).ShouldNot(Succeed()) 261 Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) 262 263 _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) 264 Expect(err).ShouldNot(Succeed()) 265 Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) 266 267 _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) 268 Expect(err).ShouldNot(Succeed()) 269 Expect(err.Error()).Should(ContainSubstring("status not ready")) 270 271 ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) 272 Expect(err).Should(Succeed()) 273 Expect(ok).Should(BeTrue()) 274 275 ok, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterVersionObj) 276 Expect(err).Should(Succeed()) 277 Expect(ok).Should(BeTrue()) 278 279 _, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterVersionObj) 280 Expect(err).Should(Succeed()) 281 282 err = DeleteConfigMapFinalizer(k8sMockClient.Client(), reqCtx, clusterVersionObj) 283 Expect(err).Should(Succeed()) 284 }) 285 }) 286 287 })