github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/cluster_status_event_handler_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 apps
    21  
    22  import (
    23  	"context"
    24  
    25  	. "github.com/onsi/ginkgo/v2"
    26  	. "github.com/onsi/gomega"
    27  
    28  	corev1 "k8s.io/api/core/v1"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  
    31  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    32  	workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1"
    33  	"github.com/1aal/kubeblocks/pkg/constant"
    34  	intctrlutil "github.com/1aal/kubeblocks/pkg/generics"
    35  	testapps "github.com/1aal/kubeblocks/pkg/testutil/apps"
    36  )
    37  
    38  var _ = Describe("test cluster Failed/Abnormal phase", func() {
    39  
    40  	var (
    41  		ctx                = context.Background()
    42  		clusterName        = ""
    43  		clusterDefName     = ""
    44  		clusterVersionName = ""
    45  	)
    46  
    47  	setupResourceNames := func() {
    48  		suffix := testCtx.GetRandomStr()
    49  		clusterName = "cluster-for-status-" + suffix
    50  		clusterDefName = "clusterdef-for-status-" + suffix
    51  		clusterVersionName = "cluster-version-for-status-" + suffix
    52  	}
    53  
    54  	cleanEnv := func() {
    55  		// must wait till resources deleted and no longer existed before the testcases start,
    56  		// otherwise if later it needs to create some new resource objects with the same name,
    57  		// in race conditions, it will find the existence of old objects, resulting failure to
    58  		// create the new objects.
    59  		By("clean resources")
    60  
    61  		if clusterName != "" {
    62  			testapps.ClearClusterResources(&testCtx)
    63  
    64  			inNS := client.InNamespace(testCtx.DefaultNamespace)
    65  			ml := client.HasLabels{testCtx.TestObjLabelKey}
    66  			// testapps.ClearResources(&testCtx, intctrlutil.StatefulSetSignature, inNS, ml)
    67  			// testapps.ClearResources(&testCtx, intctrlutil.DeploymentSignature, inNS, ml)
    68  			testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.PodSignature, true, inNS, ml)
    69  		}
    70  
    71  		// reset all resource names
    72  		setupResourceNames()
    73  	}
    74  	BeforeEach(cleanEnv)
    75  
    76  	AfterEach(cleanEnv)
    77  
    78  	const statefulMySQLCompType = "stateful"
    79  	const statefulMySQLCompName = "stateful"
    80  
    81  	const consensusMySQLCompType = "consensus"
    82  	const consensusMySQLCompName = "consensus"
    83  
    84  	const statelessCompType = "stateless"
    85  	const statelessCompName = "nginx"
    86  
    87  	createClusterDef := func() {
    88  		_ = testapps.NewClusterDefFactory(clusterDefName).
    89  			AddComponentDef(testapps.StatefulMySQLComponent, statefulMySQLCompType).
    90  			AddComponentDef(testapps.ConsensusMySQLComponent, consensusMySQLCompType).
    91  			AddComponentDef(testapps.StatelessNginxComponent, statelessCompType).
    92  			Create(&testCtx)
    93  	}
    94  
    95  	createClusterVersion := func() {
    96  		_ = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName).
    97  			AddComponentVersion(statefulMySQLCompType).AddContainerShort(testapps.DefaultMySQLContainerName, testapps.ApeCloudMySQLImage).
    98  			AddComponentVersion(consensusMySQLCompType).AddContainerShort(testapps.DefaultMySQLContainerName, testapps.ApeCloudMySQLImage).
    99  			AddComponentVersion(statelessCompType).AddContainerShort(testapps.DefaultNginxContainerName, testapps.NginxImage).
   100  			Create(&testCtx)
   101  	}
   102  
   103  	createCluster := func() *appsv1alpha1.Cluster {
   104  		return testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, clusterVersionName).
   105  			AddComponent(statefulMySQLCompName, statefulMySQLCompType).SetReplicas(3).
   106  			AddComponent(consensusMySQLCompName, consensusMySQLCompType).SetReplicas(3).
   107  			AddComponent(statelessCompName, statelessCompType).SetReplicas(3).
   108  			Create(&testCtx).GetObject()
   109  	}
   110  
   111  	Context("test cluster Failed/Abnormal phase", func() {
   112  		It("test cluster Failed/Abnormal phase", func() {
   113  			By("create cluster related resources")
   114  			createClusterDef()
   115  			createClusterVersion()
   116  			// cluster := createCluster()
   117  			createCluster()
   118  
   119  			// wait for cluster's status to become stable so that it won't interfere with later tests
   120  			Eventually(testapps.CheckObj(&testCtx, client.ObjectKey{Name: clusterName, Namespace: testCtx.DefaultNamespace},
   121  				func(g Gomega, fetched *appsv1alpha1.Cluster) {
   122  					g.Expect(fetched.Generation).To(BeEquivalentTo(1))
   123  					g.Expect(fetched.Status.ObservedGeneration).To(BeEquivalentTo(1))
   124  					g.Expect(fetched.Status.Phase).To(Equal(appsv1alpha1.CreatingClusterPhase))
   125  				})).Should(Succeed())
   126  
   127  			By("watch normal event")
   128  			event := &corev1.Event{
   129  				Count:   1,
   130  				Type:    corev1.EventTypeNormal,
   131  				Message: "create pod failed because the pvc is deleting",
   132  			}
   133  			Expect(handleEventForClusterStatus(ctx, k8sClient, clusterRecorder, event)).Should(Succeed())
   134  
   135  			By("watch warning event from StatefulSet, but mismatch condition ")
   136  			// wait for StatefulSet created by cluster controller
   137  			workloadName := clusterName + "-" + statefulMySQLCompName
   138  			kd := constant.RSMKind
   139  			Eventually(testapps.CheckObj(&testCtx, client.ObjectKey{Name: workloadName, Namespace: testCtx.DefaultNamespace},
   140  				func(g Gomega, fetched *workloads.ReplicatedStateMachine) {
   141  					g.Expect(fetched.Generation).To(BeEquivalentTo(1))
   142  				})).Should(Succeed())
   143  
   144  			stsInvolvedObject := corev1.ObjectReference{
   145  				Name:      workloadName,
   146  				Kind:      kd,
   147  				Namespace: testCtx.DefaultNamespace,
   148  			}
   149  			event.InvolvedObject = stsInvolvedObject
   150  			event.Type = corev1.EventTypeWarning
   151  			Expect(handleEventForClusterStatus(ctx, k8sClient, clusterRecorder, event)).Should(Succeed())
   152  		})
   153  	})
   154  })