github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/dataprotection/backup/deleter_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 backup
    21  
    22  import (
    23  	. "github.com/onsi/ginkgo/v2"
    24  	. "github.com/onsi/gomega"
    25  
    26  	batchv1 "k8s.io/api/batch/v1"
    27  	"sigs.k8s.io/controller-runtime/pkg/client"
    28  
    29  	dpv1alpha1 "github.com/1aal/kubeblocks/apis/dataprotection/v1alpha1"
    30  	"github.com/1aal/kubeblocks/pkg/constant"
    31  	ctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    32  	"github.com/1aal/kubeblocks/pkg/generics"
    33  	testapps "github.com/1aal/kubeblocks/pkg/testutil/apps"
    34  	testdp "github.com/1aal/kubeblocks/pkg/testutil/dataprotection"
    35  	viper "github.com/1aal/kubeblocks/pkg/viperx"
    36  )
    37  
    38  var _ = Describe("Backup Deleter Test", func() {
    39  	const (
    40  		backupRepoPVCName = "backup-repo-pvc"
    41  		backupPath        = "/backup/test-backup"
    42  		backupVSName      = "backup-vs"
    43  		backupPVCName     = "backup-pvc"
    44  	)
    45  
    46  	buildDeleter := func() *Deleter {
    47  		return &Deleter{
    48  			RequestCtx: ctrlutil.RequestCtx{
    49  				Log:      logger,
    50  				Ctx:      testCtx.Ctx,
    51  				Recorder: recorder,
    52  			},
    53  			Scheme: testEnv.Scheme,
    54  			Client: testCtx.Cli,
    55  		}
    56  	}
    57  
    58  	cleanEnv := func() {
    59  		By("clean resources")
    60  		inNS := client.InNamespace(testCtx.DefaultNamespace)
    61  		testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.BackupSignature, true, inNS)
    62  		testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.JobSignature, true, inNS)
    63  		testapps.ClearResources(&testCtx, generics.VolumeSnapshotSignature, inNS)
    64  	}
    65  
    66  	BeforeEach(func() {
    67  		cleanEnv()
    68  		viper.Set(constant.KBToolsImage, testdp.KBToolImage)
    69  	})
    70  
    71  	AfterEach(func() {
    72  		cleanEnv()
    73  		viper.Set(constant.KBToolsImage, "")
    74  	})
    75  
    76  	Context("delete backup file", func() {
    77  		var (
    78  			backup  *dpv1alpha1.Backup
    79  			deleter *Deleter
    80  		)
    81  
    82  		BeforeEach(func() {
    83  			backup = testdp.NewFakeBackup(&testCtx, nil)
    84  			deleter = buildDeleter()
    85  		})
    86  
    87  		It("should success when backup status PVC is empty", func() {
    88  			Expect(backup.Status.PersistentVolumeClaimName).Should(Equal(""))
    89  			status, err := deleter.DeleteBackupFiles(backup)
    90  			Expect(err).ShouldNot(HaveOccurred())
    91  			Expect(status).Should(Equal(DeletionStatusSucceeded))
    92  		})
    93  
    94  		It("should success when backup status path is empty", func() {
    95  			backup.Status.PersistentVolumeClaimName = backupRepoPVCName
    96  			Expect(backup.Status.Path).Should(Equal(""))
    97  			status, err := deleter.DeleteBackupFiles(backup)
    98  			Expect(err).ShouldNot(HaveOccurred())
    99  			Expect(status).Should(Equal(DeletionStatusSucceeded))
   100  		})
   101  
   102  		It("should success when PVC does not exist", func() {
   103  			backup.Status.PersistentVolumeClaimName = backupRepoPVCName
   104  			backup.Status.Path = backupPath
   105  			status, err := deleter.DeleteBackupFiles(backup)
   106  			Expect(err).ShouldNot(HaveOccurred())
   107  			Expect(status).Should(Equal(DeletionStatusSucceeded))
   108  		})
   109  
   110  		It("should create job to delete backup file", func() {
   111  			By("mock backup repo PVC")
   112  			backupRepoPVC := testdp.NewFakePVC(&testCtx, backupRepoPVCName)
   113  
   114  			By("delete backup file")
   115  			backup.Status.PersistentVolumeClaimName = backupRepoPVC.Name
   116  			backup.Status.Path = backupPath
   117  			status, err := deleter.DeleteBackupFiles(backup)
   118  			Expect(err).ShouldNot(HaveOccurred())
   119  			Expect(status).Should(Equal(DeletionStatusDeleting))
   120  
   121  			By("check job exist")
   122  			job := &batchv1.Job{}
   123  			key := BuildDeleteBackupFilesJobKey(backup)
   124  			Eventually(testapps.CheckObjExists(&testCtx, key, job, true)).Should(Succeed())
   125  
   126  			By("delete backup with job running")
   127  			backupKey := client.ObjectKeyFromObject(backup)
   128  			Eventually(testapps.CheckObj(&testCtx, backupKey, func(g Gomega, fetched *dpv1alpha1.Backup) {
   129  				status, err := deleter.DeleteBackupFiles(fetched)
   130  				Expect(err).ShouldNot(HaveOccurred())
   131  				Expect(status).Should(Equal(DeletionStatusDeleting))
   132  			})).Should(Succeed())
   133  
   134  			By("delete backup with job succeed")
   135  			testdp.ReplaceK8sJobStatus(&testCtx, key, batchv1.JobComplete)
   136  			Eventually(testapps.CheckObj(&testCtx, backupKey, func(g Gomega, fetched *dpv1alpha1.Backup) {
   137  				status, err := deleter.DeleteBackupFiles(fetched)
   138  				Expect(err).ShouldNot(HaveOccurred())
   139  				Expect(status).Should(Equal(DeletionStatusSucceeded))
   140  			})).Should(Succeed())
   141  
   142  			By("delete backup with job failed")
   143  			testdp.ReplaceK8sJobStatus(&testCtx, key, batchv1.JobFailed)
   144  			Eventually(testapps.CheckObj(&testCtx, backupKey, func(g Gomega, fetched *dpv1alpha1.Backup) {
   145  				status, err := deleter.DeleteBackupFiles(fetched)
   146  				Expect(err).Should(HaveOccurred())
   147  				Expect(status).Should(Equal(DeletionStatusFailed))
   148  			})).Should(Succeed())
   149  		})
   150  
   151  		It("delete backup with backup repo", func() {
   152  			backup.Status.BackupRepoName = testdp.BackupRepoName
   153  			status, err := deleter.DeleteBackupFiles(backup)
   154  			Expect(err).ShouldNot(HaveOccurred())
   155  			Expect(status).Should(Equal(DeletionStatusSucceeded))
   156  		})
   157  	})
   158  
   159  	Context("delete volume snapshots", func() {
   160  		var (
   161  			backup  *dpv1alpha1.Backup
   162  			deleter *Deleter
   163  		)
   164  
   165  		BeforeEach(func() {
   166  			backup = testdp.NewFakeBackup(&testCtx, nil)
   167  			deleter = buildDeleter()
   168  		})
   169  
   170  		It("should success when volume snapshot does not exist", func() {
   171  			Expect(deleter.DeleteVolumeSnapshots(backup)).Should(Succeed())
   172  		})
   173  
   174  		It("should success when volume snapshot exist", func() {
   175  			By("mock volume snapshot")
   176  			vs := testdp.NewVolumeSnapshotFactory(testCtx.DefaultNamespace, backupVSName).
   177  				SetSourcePVCName(backupPVCName).
   178  				AddLabelsInMap(BuildBackupWorkloadLabels(backup)).
   179  				Create(&testCtx).GetObject()
   180  			Eventually(testapps.CheckObjExists(&testCtx,
   181  				client.ObjectKeyFromObject(vs), vs, true)).Should(Succeed())
   182  
   183  			By("delete volume snapshot")
   184  			Expect(deleter.DeleteVolumeSnapshots(backup)).Should(Succeed())
   185  
   186  			By("check volume snapshot deleted")
   187  			Eventually(testapps.CheckObjExists(&testCtx,
   188  				client.ObjectKeyFromObject(vs), vs, false)).Should(Succeed())
   189  		})
   190  	})
   191  })