363 lines
16 KiB
Go
363 lines
16 KiB
Go
/*
|
|
Copyright the Velero contributors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
package bslmgmt
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
"github.com/google/uuid"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
. "github.com/vmware-tanzu/velero/test/e2e"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/k8s"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/kibishii"
|
|
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/providers"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/velero"
|
|
)
|
|
|
|
const (
|
|
// Please make sure length of this namespace should be shorter,
|
|
// otherwise ResticRepositories name verification will be wrong
|
|
// when making combination of ResticRepositories name(max length is 63)
|
|
bslDeletionTestNs = "bsl-deletion"
|
|
)
|
|
|
|
// Test backup and restore of Kibishi using restic
|
|
|
|
func BslDeletionWithSnapshots() {
|
|
BslDeletionTest(true)
|
|
}
|
|
|
|
func BslDeletionWithRestic() {
|
|
BslDeletionTest(false)
|
|
}
|
|
func BslDeletionTest(useVolumeSnapshots bool) {
|
|
var (
|
|
err error
|
|
)
|
|
|
|
less := func(a, b string) bool { return a < b }
|
|
BeforeEach(func() {
|
|
if useVolumeSnapshots && VeleroCfg.CloudProvider == "kind" {
|
|
Skip("Volume snapshots not supported on kind")
|
|
}
|
|
var err error
|
|
flag.Parse()
|
|
UUIDgen, err = uuid.NewRandom()
|
|
Expect(err).To(Succeed())
|
|
if VeleroCfg.InstallVelero {
|
|
Expect(VeleroInstall(context.Background(), &VeleroCfg, useVolumeSnapshots)).To(Succeed())
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if !VeleroCfg.Debug {
|
|
By("Clean backups after test", func() {
|
|
DeleteBackups(context.Background(), *VeleroCfg.DefaultClient)
|
|
})
|
|
By(fmt.Sprintf("Delete sample workload namespace %s", bslDeletionTestNs), func() {
|
|
Expect(DeleteNamespace(context.Background(), *VeleroCfg.ClientToInstallVelero, bslDeletionTestNs,
|
|
true)).To(Succeed(), fmt.Sprintf("failed to delete the namespace %q",
|
|
bslDeletionTestNs))
|
|
})
|
|
if VeleroCfg.InstallVelero {
|
|
By("Uninstall Velero", func() {
|
|
Expect(VeleroUninstall(context.Background(), VeleroCfg.VeleroCLI,
|
|
VeleroCfg.VeleroNamespace)).To(Succeed())
|
|
})
|
|
}
|
|
}
|
|
|
|
})
|
|
|
|
When("kibishii is the sample workload", func() {
|
|
It("Local backups and restic repos (if Velero was installed with Restic) will be deleted once the corresponding backup storage location is deleted", func() {
|
|
if VeleroCfg.AdditionalBSLProvider == "" {
|
|
Skip("no additional BSL provider given, not running multiple BackupStorageLocation with unique credentials tests")
|
|
}
|
|
|
|
if VeleroCfg.AdditionalBSLBucket == "" {
|
|
Skip("no additional BSL bucket given, not running multiple BackupStorageLocation with unique credentials tests")
|
|
}
|
|
|
|
if VeleroCfg.AdditionalBSLCredentials == "" {
|
|
Skip("no additional BSL credentials given, not running multiple BackupStorageLocation with unique credentials tests")
|
|
}
|
|
|
|
By(fmt.Sprintf("Add an additional plugin for provider %s", VeleroCfg.AdditionalBSLProvider), func() {
|
|
Expect(VeleroAddPluginsForProvider(context.TODO(), VeleroCfg.VeleroCLI,
|
|
VeleroCfg.VeleroNamespace, VeleroCfg.AdditionalBSLProvider,
|
|
VeleroCfg.AddBSLPlugins, VeleroCfg.Features)).To(Succeed())
|
|
})
|
|
|
|
additionalBsl := fmt.Sprintf("bsl-%s", UUIDgen)
|
|
secretName := fmt.Sprintf("bsl-credentials-%s", UUIDgen)
|
|
secretKey := fmt.Sprintf("creds-%s", VeleroCfg.AdditionalBSLProvider)
|
|
files := map[string]string{
|
|
secretKey: VeleroCfg.AdditionalBSLCredentials,
|
|
}
|
|
|
|
By(fmt.Sprintf("Create Secret for additional BSL %s", additionalBsl), func() {
|
|
Expect(CreateSecretFromFiles(context.TODO(), *VeleroCfg.ClientToInstallVelero, VeleroCfg.VeleroNamespace, secretName, files)).To(Succeed())
|
|
})
|
|
|
|
By(fmt.Sprintf("Create additional BSL using credential %s", secretName), func() {
|
|
Expect(VeleroCreateBackupLocation(context.TODO(),
|
|
VeleroCfg.VeleroCLI,
|
|
VeleroCfg.VeleroNamespace,
|
|
additionalBsl,
|
|
VeleroCfg.AdditionalBSLProvider,
|
|
VeleroCfg.AdditionalBSLBucket,
|
|
VeleroCfg.AdditionalBSLPrefix,
|
|
VeleroCfg.AdditionalBSLConfig,
|
|
secretName,
|
|
secretKey,
|
|
)).To(Succeed())
|
|
})
|
|
|
|
backupName_1 := "backup1-" + UUIDgen.String()
|
|
backupName_2 := "backup2-" + UUIDgen.String()
|
|
oneHourTimeout, _ := context.WithTimeout(context.Background(), time.Minute*60)
|
|
|
|
backupLocation_1 := "default"
|
|
backupLocation_2 := additionalBsl
|
|
podName_1 := "kibishii-deployment-0"
|
|
podName_2 := "kibishii-deployment-1"
|
|
|
|
label_1 := "for=1"
|
|
// TODO remove when issue https://github.com/vmware-tanzu/velero/issues/4724 is fixed
|
|
//label_2 := "for!=1"
|
|
label_2 := "for=2"
|
|
By("Create namespace for sample workload", func() {
|
|
Expect(CreateNamespace(oneHourTimeout, *VeleroCfg.ClientToInstallVelero, bslDeletionTestNs)).To(Succeed())
|
|
})
|
|
|
|
By("Deploy sample workload of Kibishii", func() {
|
|
Expect(KibishiiPrepareBeforeBackup(oneHourTimeout, *VeleroCfg.ClientToInstallVelero, VeleroCfg.CloudProvider,
|
|
bslDeletionTestNs, VeleroCfg.RegistryCredentialFile, VeleroCfg.Features,
|
|
VeleroCfg.KibishiiDirectory, useVolumeSnapshots, DefaultKibishiiData)).To(Succeed())
|
|
})
|
|
|
|
// Restic can not backup PV only, so pod need to be labeled also
|
|
By("Label all 2 worker-pods of Kibishii", func() {
|
|
Expect(AddLabelToPod(context.Background(), podName_1, bslDeletionTestNs, label_1)).To(Succeed())
|
|
Expect(AddLabelToPod(context.Background(), "kibishii-deployment-1", bslDeletionTestNs, label_2)).To(Succeed())
|
|
})
|
|
|
|
By("Get all 2 PVCs of Kibishii and label them seprately ", func() {
|
|
pvc, err := GetPvcByPodName(context.Background(), bslDeletionTestNs, podName_1)
|
|
Expect(err).To(Succeed())
|
|
fmt.Println(pvc)
|
|
Expect(len(pvc)).To(Equal(1))
|
|
pvc1 := pvc[0]
|
|
pvc, err = GetPvcByPodName(context.Background(), bslDeletionTestNs, podName_2)
|
|
Expect(err).To(Succeed())
|
|
fmt.Println(pvc)
|
|
Expect(len(pvc)).To(Equal(1))
|
|
pvc2 := pvc[0]
|
|
Expect(AddLabelToPvc(context.Background(), pvc1, bslDeletionTestNs, label_1)).To(Succeed())
|
|
Expect(AddLabelToPvc(context.Background(), pvc2, bslDeletionTestNs, label_2)).To(Succeed())
|
|
})
|
|
|
|
var BackupCfg BackupConfig
|
|
BackupCfg.BackupName = backupName_1
|
|
BackupCfg.Namespace = bslDeletionTestNs
|
|
BackupCfg.BackupLocation = backupLocation_1
|
|
BackupCfg.UseVolumeSnapshots = useVolumeSnapshots
|
|
BackupCfg.Selector = label_1
|
|
By(fmt.Sprintf("Backup one of PV of sample workload by label-1 - Kibishii by the first BSL %s", backupLocation_1), func() {
|
|
// TODO currently, the upgrade case covers the upgrade path from 1.6 to main and the velero v1.6 doesn't support "debug" command
|
|
// TODO move to "runDebug" after we bump up to 1.7 in the upgrade case
|
|
Expect(VeleroBackupNamespace(oneHourTimeout, VeleroCfg.VeleroCLI,
|
|
VeleroCfg.VeleroNamespace, BackupCfg)).To(Succeed(), func() string {
|
|
RunDebug(context.Background(), VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, BackupCfg.BackupName, "")
|
|
return "Fail to backup workload"
|
|
})
|
|
})
|
|
|
|
BackupCfg.BackupName = backupName_2
|
|
BackupCfg.BackupLocation = backupLocation_2
|
|
BackupCfg.Selector = label_2
|
|
By(fmt.Sprintf("Back up the other one PV of sample workload with label-2 into the additional BSL %s", backupLocation_2), func() {
|
|
Expect(VeleroBackupNamespace(oneHourTimeout, VeleroCfg.VeleroCLI,
|
|
VeleroCfg.VeleroNamespace, BackupCfg)).To(Succeed(), func() string {
|
|
RunDebug(context.Background(), VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, BackupCfg.BackupName, "")
|
|
return "Fail to backup workload"
|
|
})
|
|
})
|
|
|
|
if useVolumeSnapshots {
|
|
if VeleroCfg.CloudProvider == "vsphere" {
|
|
// TODO - remove after upload progress monitoring is implemented
|
|
By("Waiting for vSphere uploads to complete", func() {
|
|
Expect(WaitForVSphereUploadCompletion(oneHourTimeout, time.Hour,
|
|
bslDeletionTestNs)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Snapshot CR in backup %s should be created", backupName_1), func() {
|
|
Expect(SnapshotCRsCountShouldBe(context.Background(), bslDeletionTestNs,
|
|
backupName_1, 1)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Snapshot CR in backup %s should be created", backupName_2), func() {
|
|
Expect(SnapshotCRsCountShouldBe(context.Background(), bslDeletionTestNs,
|
|
backupName_2, 1)).To(Succeed())
|
|
})
|
|
}
|
|
|
|
var snapshotCheckPoint SnapshotCheckPoint
|
|
snapshotCheckPoint.NamespaceBackedUp = bslDeletionTestNs
|
|
By(fmt.Sprintf("Snapshot of bsl %s should be created in cloud object store", backupLocation_1), func() {
|
|
snapshotCheckPoint, err = GetSnapshotCheckPoint(*VeleroCfg.ClientToInstallVelero, VeleroCfg, 1, bslDeletionTestNs, backupName_1, []string{podName_1})
|
|
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
|
|
Expect(SnapshotsShouldBeCreatedInCloud(VeleroCfg.CloudProvider,
|
|
VeleroCfg.CloudCredentialsFile, VeleroCfg.BSLBucket,
|
|
VeleroCfg.BSLConfig, backupName_1, snapshotCheckPoint)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Snapshot of bsl %s should be created in cloud object store", backupLocation_2), func() {
|
|
snapshotCheckPoint, err = GetSnapshotCheckPoint(*VeleroCfg.ClientToInstallVelero, VeleroCfg, 1, bslDeletionTestNs, backupName_2, []string{podName_2})
|
|
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
|
|
var BSLCredentials, BSLConfig string
|
|
if VeleroCfg.CloudProvider == "vsphere" {
|
|
BSLCredentials = VeleroCfg.AdditionalBSLCredentials
|
|
BSLConfig = VeleroCfg.AdditionalBSLConfig
|
|
} else { // Snapshotting with non-vSphere provider has nothing to do with BSL
|
|
BSLCredentials = VeleroCfg.CloudCredentialsFile
|
|
BSLConfig = VeleroCfg.BSLConfig
|
|
}
|
|
|
|
Expect(SnapshotsShouldBeCreatedInCloud(VeleroCfg.CloudProvider,
|
|
BSLCredentials, VeleroCfg.AdditionalBSLBucket,
|
|
BSLConfig, backupName_2, snapshotCheckPoint)).To(Succeed())
|
|
})
|
|
} else { // For Restics
|
|
By(fmt.Sprintf("Resticrepositories for BSL %s should be created in Velero namespace", backupLocation_1), func() {
|
|
Expect(BackupRepositoriesCountShouldBe(context.Background(),
|
|
VeleroCfg.VeleroNamespace, bslDeletionTestNs+"-"+backupLocation_1, 1)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Resticrepositories for BSL %s should be created in Velero namespace", backupLocation_2), func() {
|
|
Expect(BackupRepositoriesCountShouldBe(context.Background(),
|
|
VeleroCfg.VeleroNamespace, bslDeletionTestNs+"-"+backupLocation_2, 1)).To(Succeed())
|
|
})
|
|
}
|
|
|
|
By(fmt.Sprintf("Backup 1 %s should be created.", backupName_1), func() {
|
|
Expect(WaitForBackupToBeCreated(context.Background(), VeleroCfg.VeleroCLI,
|
|
backupName_1, 10*time.Minute)).To(Succeed())
|
|
})
|
|
|
|
By(fmt.Sprintf("Backup 2 %s should be created.", backupName_2), func() {
|
|
Expect(WaitForBackupToBeCreated(context.Background(), VeleroCfg.VeleroCLI,
|
|
backupName_2, 10*time.Minute)).To(Succeed())
|
|
})
|
|
|
|
backupsInBSL1, err := GetBackupsFromBsl(context.Background(), VeleroCfg.VeleroCLI, backupLocation_1)
|
|
Expect(err).To(Succeed())
|
|
backupsInBSL2, err := GetBackupsFromBsl(context.Background(), VeleroCfg.VeleroCLI, backupLocation_2)
|
|
Expect(err).To(Succeed())
|
|
backupsInBsl1AndBsl2 := append(backupsInBSL1, backupsInBSL2...)
|
|
|
|
By(fmt.Sprintf("Get all backups from 2 BSLs %s before deleting one of them", backupLocation_1), func() {
|
|
backupsBeforeDel, err := GetAllBackups(context.Background(), VeleroCfg.VeleroCLI)
|
|
Expect(err).To(Succeed())
|
|
Expect(cmp.Diff(backupsInBsl1AndBsl2, backupsBeforeDel, cmpopts.SortSlices(less))).Should(BeEmpty())
|
|
|
|
By(fmt.Sprintf("Backup1 %s should exist in cloud object store before bsl deletion", backupName_1), func() {
|
|
Expect(ObjectsShouldBeInBucket(VeleroCfg.CloudProvider, VeleroCfg.CloudCredentialsFile,
|
|
VeleroCfg.BSLBucket, VeleroCfg.BSLPrefix, VeleroCfg.BSLConfig,
|
|
backupName_1, BackupObjectsPrefix)).To(Succeed())
|
|
})
|
|
|
|
By(fmt.Sprintf("Delete one of backup locations - %s", backupLocation_1), func() {
|
|
Expect(DeleteBslResource(context.Background(), VeleroCfg.VeleroCLI, backupLocation_1)).To(Succeed())
|
|
Expect(WaitForBackupsToBeDeleted(context.Background(), VeleroCfg.VeleroCLI, backupsInBSL1, 10*time.Minute)).To(Succeed())
|
|
})
|
|
|
|
By("Get all backups from 2 BSLs after deleting one of them", func() {
|
|
backupsAfterDel, err := GetAllBackups(context.Background(), VeleroCfg.VeleroCLI)
|
|
Expect(err).To(Succeed())
|
|
// Default BSL is deleted, so backups in additional BSL should be left only
|
|
Expect(cmp.Diff(backupsInBSL2, backupsAfterDel, cmpopts.SortSlices(less))).Should(BeEmpty())
|
|
})
|
|
})
|
|
|
|
By(fmt.Sprintf("Backup1 %s should still exist in cloud object store after bsl deletion", backupName_1), func() {
|
|
Expect(ObjectsShouldBeInBucket(VeleroCfg.CloudProvider, VeleroCfg.CloudCredentialsFile,
|
|
VeleroCfg.BSLBucket, VeleroCfg.BSLPrefix, VeleroCfg.BSLConfig,
|
|
backupName_1, BackupObjectsPrefix)).To(Succeed())
|
|
})
|
|
|
|
// TODO: Choose additional BSL to be deleted as an new test case
|
|
// By(fmt.Sprintf("Backup %s should still exist in cloud object store", backupName_2), func() {
|
|
// Expect(ObjectsShouldBeInBucket(VeleroCfg.CloudProvider, VeleroCfg.AdditionalBSLCredentials,
|
|
// VeleroCfg.AdditionalBSLBucket, VeleroCfg.AdditionalBSLPrefix, VeleroCfg.AdditionalBSLConfig,
|
|
// backupName_2, BackupObjectsPrefix)).To(Succeed())
|
|
// })
|
|
|
|
if useVolumeSnapshots {
|
|
if VeleroCfg.CloudProvider == "vsphere" {
|
|
By(fmt.Sprintf("Snapshot in backup %s should still exist, because snapshot CR will be deleted 24 hours later if the status is a success", backupName_2), func() {
|
|
Expect(SnapshotCRsCountShouldBe(context.Background(), bslDeletionTestNs,
|
|
backupName_1, 1)).To(Succeed())
|
|
Expect(SnapshotCRsCountShouldBe(context.Background(), bslDeletionTestNs,
|
|
backupName_2, 1)).To(Succeed())
|
|
})
|
|
}
|
|
var snapshotCheckPoint SnapshotCheckPoint
|
|
snapshotCheckPoint.NamespaceBackedUp = bslDeletionTestNs
|
|
By(fmt.Sprintf("Snapshot should not be deleted in cloud object store after deleting bsl %s", backupLocation_1), func() {
|
|
|
|
snapshotCheckPoint, err = GetSnapshotCheckPoint(*VeleroCfg.ClientToInstallVelero, VeleroCfg, 1, bslDeletionTestNs, backupName_1, []string{podName_1})
|
|
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
|
|
Expect(SnapshotsShouldBeCreatedInCloud(VeleroCfg.CloudProvider,
|
|
VeleroCfg.CloudCredentialsFile, VeleroCfg.BSLBucket,
|
|
VeleroCfg.BSLConfig, backupName_1, snapshotCheckPoint)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Snapshot should not be deleted in cloud object store after deleting bsl %s", backupLocation_2), func() {
|
|
var BSLCredentials, BSLConfig string
|
|
if VeleroCfg.CloudProvider == "vsphere" {
|
|
BSLCredentials = VeleroCfg.AdditionalBSLCredentials
|
|
BSLConfig = VeleroCfg.AdditionalBSLConfig
|
|
} else {
|
|
BSLCredentials = VeleroCfg.CloudCredentialsFile
|
|
BSLConfig = VeleroCfg.BSLConfig
|
|
}
|
|
snapshotCheckPoint, err = GetSnapshotCheckPoint(*VeleroCfg.ClientToInstallVelero, VeleroCfg, 1, bslDeletionTestNs, backupName_2, []string{podName_2})
|
|
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
|
|
Expect(SnapshotsShouldBeCreatedInCloud(VeleroCfg.CloudProvider,
|
|
BSLCredentials, VeleroCfg.AdditionalBSLBucket,
|
|
BSLConfig, backupName_2, snapshotCheckPoint)).To(Succeed())
|
|
})
|
|
} else { // For Restic
|
|
By(fmt.Sprintf("Resticrepositories for BSL %s should be deleted in Velero namespace", backupLocation_1), func() {
|
|
Expect(BackupRepositoriesCountShouldBe(context.Background(),
|
|
VeleroCfg.VeleroNamespace, bslDeletionTestNs+"-"+backupLocation_1, 0)).To(Succeed())
|
|
})
|
|
By(fmt.Sprintf("Resticrepositories for BSL %s should still exist in Velero namespace", backupLocation_2), func() {
|
|
Expect(BackupRepositoriesCountShouldBe(context.Background(),
|
|
VeleroCfg.VeleroNamespace, bslDeletionTestNs+"-"+backupLocation_2, 1)).To(Succeed())
|
|
})
|
|
}
|
|
fmt.Printf("|| EXPECTED || - Backup deletion test completed successfully\n")
|
|
})
|
|
})
|
|
}
|