github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/configuration_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  	"github.com/1aal/kubeblocks/pkg/configuration/core"
    32  	"github.com/1aal/kubeblocks/pkg/constant"
    33  	"github.com/1aal/kubeblocks/pkg/controller/builder"
    34  	"github.com/1aal/kubeblocks/pkg/controller/component"
    35  	"github.com/1aal/kubeblocks/pkg/controller/configuration"
    36  	intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    37  	"github.com/1aal/kubeblocks/pkg/generics"
    38  	testapps "github.com/1aal/kubeblocks/pkg/testutil/apps"
    39  )
    40  
    41  const clusterDefName = "test-clusterdef"
    42  const clusterVersionName = "test-clusterversion"
    43  const clusterName = "test-cluster"
    44  const statefulCompDefName = "replicasets"
    45  const statefulCompName = "mysql"
    46  const statefulSetName = "mysql-statefulset"
    47  const configSpecName = "mysql-config-tpl"
    48  const configVolumeName = "mysql-config"
    49  const cmName = "mysql-tree-node-template-8.0"
    50  
    51  func mockConfigResource() (*corev1.ConfigMap, *appsv1alpha1.ConfigConstraint) {
    52  	By("Create a config template obj")
    53  	configmap := testapps.CreateCustomizedObj(&testCtx,
    54  		"resources/mysql-config-template.yaml", &corev1.ConfigMap{},
    55  		testCtx.UseDefaultNamespace(),
    56  		testapps.WithLabels(
    57  			constant.AppNameLabelKey, clusterName,
    58  			constant.AppInstanceLabelKey, clusterName,
    59  			constant.KBAppComponentLabelKey, statefulCompName,
    60  			constant.CMConfigurationTemplateNameLabelKey, configSpecName,
    61  			constant.CMConfigurationConstraintsNameLabelKey, cmName,
    62  			constant.CMConfigurationSpecProviderLabelKey, configSpecName,
    63  			constant.CMConfigurationTypeLabelKey, constant.ConfigInstanceType,
    64  		),
    65  		testapps.WithAnnotations(
    66  			constant.KBParameterUpdateSourceAnnotationKey, constant.ReconfigureManagerSource,
    67  			constant.ConfigurationRevision, "1",
    68  			constant.CMInsEnableRerenderTemplateKey, "true"))
    69  
    70  	By("Create a config constraint obj")
    71  	constraint := testapps.CreateCustomizedObj(&testCtx,
    72  		"resources/mysql-config-constraint.yaml",
    73  		&appsv1alpha1.ConfigConstraint{})
    74  
    75  	By("check config constraint")
    76  	Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(constraint), func(g Gomega, tpl *appsv1alpha1.ConfigConstraint) {
    77  		g.Expect(tpl.Status.Phase).Should(BeEquivalentTo(appsv1alpha1.AvailablePhase))
    78  	})).Should(Succeed())
    79  
    80  	By("Create a configuration obj")
    81  	// test-cluster-mysql-mysql-config-tpl
    82  	configuration := builder.NewConfigurationBuilder(testCtx.DefaultNamespace, core.GenerateComponentConfigurationName(clusterName, statefulCompName)).
    83  		ClusterRef(clusterName).
    84  		Component(statefulCompName).
    85  		AddConfigurationItem(appsv1alpha1.ComponentConfigSpec{
    86  			ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
    87  				Name:        configSpecName,
    88  				TemplateRef: configmap.Name,
    89  				Namespace:   configmap.Namespace,
    90  				VolumeName:  configVolumeName,
    91  			},
    92  			ConfigConstraintRef: constraint.Name,
    93  		}).
    94  		GetObject()
    95  	Expect(testCtx.CreateObj(testCtx.Ctx, configuration)).Should(Succeed())
    96  
    97  	return configmap, constraint
    98  }
    99  
   100  func mockReconcileResource() (*corev1.ConfigMap, *appsv1alpha1.ConfigConstraint, *appsv1alpha1.Cluster, *appsv1alpha1.ClusterVersion, *component.SynthesizedComponent) {
   101  	configmap, constraint := mockConfigResource()
   102  
   103  	By("Create a clusterDefinition obj")
   104  	clusterDefObj := testapps.NewClusterDefFactory(clusterDefName).
   105  		AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName).
   106  		AddConfigTemplate(configSpecName, configmap.Name, constraint.Name, testCtx.DefaultNamespace, configVolumeName).
   107  		AddLabels(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name,
   108  			core.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name).
   109  		Create(&testCtx).GetObject()
   110  
   111  	By("Create a clusterVersion obj")
   112  	clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()).
   113  		AddComponentVersion(statefulCompDefName).
   114  		AddLabels(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name,
   115  			core.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name).
   116  		Create(&testCtx).GetObject()
   117  
   118  	By("Creating a cluster")
   119  	clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName,
   120  		clusterDefObj.Name, clusterVersionObj.Name).
   121  		AddComponent(statefulCompName, statefulCompDefName).Create(&testCtx).GetObject()
   122  
   123  	container := *builder.NewContainerBuilder("mock-container").
   124  		AddVolumeMounts(corev1.VolumeMount{
   125  			Name:      configVolumeName,
   126  			MountPath: "/mnt/config",
   127  		}).GetObject()
   128  	_ = testapps.NewStatefulSetFactory(testCtx.DefaultNamespace, statefulSetName, clusterObj.Name, statefulCompName).
   129  		AddConfigmapVolume(configVolumeName, configmap.Name).
   130  		AddContainer(container).
   131  		AddAppNameLabel(clusterName).
   132  		AddAppInstanceLabel(clusterName).
   133  		AddAppComponentLabel(statefulCompName).
   134  		AddAnnotations(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name).
   135  		Create(&testCtx).GetObject()
   136  
   137  	synthesizedComp, err := component.BuildComponent(intctrlutil.RequestCtx{
   138  		Ctx: ctx,
   139  		Log: log.FromContext(ctx),
   140  	}, nil,
   141  		clusterObj,
   142  		clusterDefObj,
   143  		clusterDefObj.GetComponentDefByName(statefulCompDefName),
   144  		clusterObj.Spec.GetComponentByName(statefulCompName),
   145  		nil,
   146  		clusterVersionObj.Spec.GetDefNameMappingComponents()[statefulCompDefName])
   147  	Expect(err).ShouldNot(HaveOccurred())
   148  
   149  	return configmap, constraint, clusterObj, clusterVersionObj, synthesizedComp
   150  }
   151  
   152  func initConfiguration(resourceCtx *intctrlutil.ResourceCtx, synthesizedComponent *component.SynthesizedComponent, clusterObj *appsv1alpha1.Cluster, clusterVersionObj *appsv1alpha1.ClusterVersion) error {
   153  	return configuration.NewCreatePipeline(configuration.ReconcileCtx{
   154  		ResourceCtx: resourceCtx,
   155  		Component:   synthesizedComponent,
   156  		Cluster:     clusterObj,
   157  		ClusterVer:  clusterVersionObj,
   158  		PodSpec:     synthesizedComponent.PodSpec,
   159  	}).
   160  		Prepare().
   161  		UpdateConfiguration(). // reconcile Configuration
   162  		Configuration().       // sync Configuration
   163  		CreateConfigTemplate().
   164  		UpdateConfigRelatedObject().
   165  		UpdateConfigurationStatus().
   166  		Complete()
   167  }
   168  
   169  func cleanEnv() {
   170  	// must wait till resources deleted and no longer existed before the testcases start,
   171  	// otherwise if later it needs to create some new resource objects with the same name,
   172  	// in race conditions, it will find the existence of old objects, resulting failure to
   173  	// create the new objects.
   174  	By("clean resources")
   175  
   176  	// delete cluster(and all dependent sub-resources), clusterversion and clusterdef
   177  	testapps.ClearClusterResources(&testCtx)
   178  
   179  	// delete rest mocked objects
   180  	inNS := client.InNamespace(testCtx.DefaultNamespace)
   181  	ml := client.HasLabels{testCtx.TestObjLabelKey}
   182  	// non-namespaced
   183  	testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml)
   184  	// namespaced
   185  	testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ConfigMapSignature, true, inNS, ml)
   186  	testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.StatefulSetSignature, true, inNS, ml)
   187  	testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ConfigurationSignature, false, inNS, ml)
   188  }