Merge pull request #8533 from blackpiglet/refactor_migration_e2e_release_1.15

[cherry-pick] Refactor the migration cases.
pull/8540/head
Wenkai Yin(尹文开) 2024-12-19 17:04:15 +08:00 committed by GitHub
commit 4376a89bc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 461 additions and 411 deletions

View File

@ -42,33 +42,31 @@ import (
// Options collects all the options for installing Velero into a Kubernetes cluster. // Options collects all the options for installing Velero into a Kubernetes cluster.
type Options struct { type Options struct {
Namespace string Namespace string
Image string Image string
BucketName string BucketName string
Prefix string Prefix string
ProviderName string ProviderName string
PodAnnotations flag.Map PodAnnotations flag.Map
PodLabels flag.Map PodLabels flag.Map
ServiceAccountAnnotations flag.Map ServiceAccountAnnotations flag.Map
ServiceAccountName string ServiceAccountName string
VeleroPodCPURequest string VeleroPodCPURequest string
VeleroPodMemRequest string VeleroPodMemRequest string
VeleroPodCPULimit string VeleroPodCPULimit string
VeleroPodMemLimit string VeleroPodMemLimit string
NodeAgentPodCPURequest string NodeAgentPodCPURequest string
NodeAgentPodMemRequest string NodeAgentPodMemRequest string
NodeAgentPodCPULimit string NodeAgentPodCPULimit string
NodeAgentPodMemLimit string NodeAgentPodMemLimit string
RestoreOnly bool RestoreOnly bool
SecretFile string SecretFile string
NoSecret bool NoSecret bool
DryRun bool DryRun bool
BackupStorageConfig flag.Map BackupStorageConfig flag.Map
VolumeSnapshotConfig flag.Map VolumeSnapshotConfig flag.Map
UseNodeAgent bool UseNodeAgent bool
PrivilegedNodeAgent bool PrivilegedNodeAgent bool
//TODO remove UseRestic when migration test out of using it
UseRestic bool
Wait bool Wait bool
UseVolumeSnapshots bool UseVolumeSnapshots bool
DefaultRepoMaintenanceFrequency time.Duration DefaultRepoMaintenanceFrequency time.Duration

View File

@ -575,9 +575,9 @@ var _ = Describe(
) )
var _ = Describe( var _ = Describe(
"Migrate resources between clusters by Restic", "Migrate resources between clusters by FileSystem backup",
Label("Migration", "Restic"), Label("Migration", "FSB"),
MigrationWithRestic, MigrationWithFS,
) )
var _ = Describe( var _ = Describe(
"Migrate resources between clusters by snapshot", "Migrate resources between clusters by snapshot",

View File

@ -17,388 +17,455 @@ package migration
import ( import (
"context" "context"
"flag"
"fmt" "fmt"
"strings" "strings"
"time" "time"
"github.com/google/uuid"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
. "github.com/vmware-tanzu/velero/test" "github.com/vmware-tanzu/velero/test"
framework "github.com/vmware-tanzu/velero/test/e2e/test"
util "github.com/vmware-tanzu/velero/test/util/csi" util "github.com/vmware-tanzu/velero/test/util/csi"
. "github.com/vmware-tanzu/velero/test/util/k8s" k8sutil "github.com/vmware-tanzu/velero/test/util/k8s"
. "github.com/vmware-tanzu/velero/test/util/kibishii" "github.com/vmware-tanzu/velero/test/util/kibishii"
. "github.com/vmware-tanzu/velero/test/util/providers" "github.com/vmware-tanzu/velero/test/util/providers"
. "github.com/vmware-tanzu/velero/test/util/velero" veleroutil "github.com/vmware-tanzu/velero/test/util/velero"
) )
var migrationNamespace string type migrationE2E struct {
var veleroCfg VeleroConfig framework.TestCase
useVolumeSnapshots bool
veleroCLI2Version test.VeleroCLI2Version
kibishiiData kibishii.KibishiiData
}
func MigrationWithSnapshots() { func MigrationWithSnapshots() {
veleroCfg = VeleroCfg for _, veleroCLI2Version := range veleroutil.GetVersionList(
for _, veleroCLI2Version := range GetVersionList(veleroCfg.MigrateFromVeleroCLI, veleroCfg.MigrateFromVeleroVersion) { test.VeleroCfg.MigrateFromVeleroCLI,
MigrationTest(true, veleroCLI2Version) test.VeleroCfg.MigrateFromVeleroVersion) {
framework.TestFunc(
&migrationE2E{
useVolumeSnapshots: true,
veleroCLI2Version: veleroCLI2Version,
},
)()
} }
} }
func MigrationWithRestic() { func MigrationWithFS() {
veleroCfg = VeleroCfg for _, veleroCLI2Version := range veleroutil.GetVersionList(
for _, veleroCLI2Version := range GetVersionList(veleroCfg.MigrateFromVeleroCLI, veleroCfg.MigrateFromVeleroVersion) { test.VeleroCfg.MigrateFromVeleroCLI,
MigrationTest(false, veleroCLI2Version) test.VeleroCfg.MigrateFromVeleroVersion) {
framework.TestFunc(
&migrationE2E{
useVolumeSnapshots: false,
veleroCLI2Version: veleroCLI2Version,
},
)()
} }
} }
func MigrationTest(useVolumeSnapshots bool, veleroCLI2Version VeleroCLI2Version) { func (m *migrationE2E) Init() error {
var ( By("Skip check", func() {
backupName, restoreName string if m.VeleroCfg.DefaultClusterContext == "" && m.VeleroCfg.StandbyClusterContext == "" {
backupScName, restoreScName string
kibishiiWorkerCount int
err error
)
BeforeEach(func() {
kibishiiWorkerCount = 3
veleroCfg = VeleroCfg
UUIDgen, err = uuid.NewRandom()
migrationNamespace = "migration-" + UUIDgen.String()
if useVolumeSnapshots && veleroCfg.CloudProvider == Kind {
Skip(fmt.Sprintf("Volume snapshots not supported on %s", Kind))
}
if veleroCfg.DefaultClusterContext == "" && veleroCfg.StandbyClusterContext == "" {
Skip("Migration test needs 2 clusters") Skip("Migration test needs 2 clusters")
} }
// need to uninstall Velero first in case of the affection of the existing global velero installation
if InstallVelero { if m.useVolumeSnapshots && m.VeleroCfg.CloudProvider == test.Kind {
By("Uninstall Velero", func() { Skip(fmt.Sprintf("Volume snapshots not supported on %s", test.Kind))
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*5) }
defer ctxCancel()
Expect(VeleroUninstall(ctx, veleroCfg)).To(Succeed()) if m.VeleroCfg.SnapshotMoveData && !m.useVolumeSnapshots {
}) Skip("FSB migration test is not needed in data mover scenario")
} }
}) })
AfterEach(func() {
if CurrentSpecReport().Failed() && veleroCfg.FailFast { By("Call the base E2E init", func() {
fmt.Println("Test case failed and fail fast is enabled. Skip resource clean up.") Expect(m.TestCase.Init()).To(Succeed())
})
m.kibishiiData = *kibishii.DefaultKibishiiData
m.kibishiiData.ExpectedNodes = 3
m.CaseBaseName = "migration-" + m.UUIDgen
m.BackupName = m.CaseBaseName + "-backup"
m.RestoreName = m.CaseBaseName + "-restore"
m.NSIncluded = &[]string{m.CaseBaseName}
m.RestoreArgs = []string{
"create", "--namespace", m.VeleroCfg.VeleroNamespace,
"restore", m.RestoreName,
"--from-backup", m.BackupName, "--wait",
}
// Message output by ginkgo
m.TestMsg = &framework.TestMSG{
Desc: "Test migration workload on two clusters",
FailedMSG: "Fail to test migrate between two clusters",
Text: "Test back up on default cluster, restore on standby cluster",
}
// Need to uninstall Velero on the default cluster.
if test.InstallVelero {
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*5)
defer ctxCancel()
Expect(veleroutil.VeleroUninstall(ctx, m.VeleroCfg)).To(Succeed())
}
return nil
}
func (m *migrationE2E) Backup() error {
OriginVeleroCfg := m.VeleroCfg
var err error
if m.veleroCLI2Version.VeleroCLI == "" {
//Assume tag of velero server image is identical to velero CLI version
//Download velero CLI if it's empty according to velero CLI version
By(
fmt.Sprintf("Install the expected version Velero CLI %s",
m.veleroCLI2Version.VeleroVersion),
func() {
// "self" represents 1.14.x and future versions
if m.veleroCLI2Version.VeleroVersion == "self" {
m.veleroCLI2Version.VeleroCLI = m.VeleroCfg.VeleroCLI
} else {
OriginVeleroCfg, err = veleroutil.SetImagesToDefaultValues(
OriginVeleroCfg,
m.veleroCLI2Version.VeleroVersion,
)
Expect(err).To(Succeed(),
"Fail to set images for the migrate-from Velero installation.")
m.veleroCLI2Version.VeleroCLI, err = veleroutil.InstallVeleroCLI(
m.veleroCLI2Version.VeleroVersion)
Expect(err).To(Succeed())
}
},
)
}
By(fmt.Sprintf("Install Velero on default cluster (%s)", m.VeleroCfg.DefaultClusterContext),
func() {
Expect(k8sutil.KubectlConfigUseContext(
m.Ctx, m.VeleroCfg.DefaultClusterContext)).To(Succeed())
OriginVeleroCfg.MigrateFromVeleroVersion = m.veleroCLI2Version.VeleroVersion
OriginVeleroCfg.VeleroCLI = m.veleroCLI2Version.VeleroCLI
OriginVeleroCfg.ClientToInstallVelero = OriginVeleroCfg.DefaultClient
OriginVeleroCfg.ClusterToInstallVelero = m.VeleroCfg.DefaultClusterName
OriginVeleroCfg.ServiceAccountNameToInstall = m.VeleroCfg.DefaultCLSServiceAccountName
OriginVeleroCfg.UseVolumeSnapshots = m.useVolumeSnapshots
OriginVeleroCfg.UseNodeAgent = !m.useVolumeSnapshots
version, err := veleroutil.GetVeleroVersion(m.Ctx, OriginVeleroCfg.VeleroCLI, true)
Expect(err).To(Succeed(), "Fail to get Velero version")
OriginVeleroCfg.VeleroVersion = version
if OriginVeleroCfg.SnapshotMoveData {
OriginVeleroCfg.UseNodeAgent = true
}
Expect(veleroutil.VeleroInstall(m.Ctx, &OriginVeleroCfg, false)).To(Succeed())
if m.veleroCLI2Version.VeleroVersion != "self" {
Expect(veleroutil.CheckVeleroVersion(
m.Ctx,
OriginVeleroCfg.VeleroCLI,
OriginVeleroCfg.MigrateFromVeleroVersion,
)).To(Succeed())
}
},
)
By("Create namespace for sample workload", func() {
Expect(k8sutil.CreateNamespace(
m.Ctx,
*m.VeleroCfg.DefaultClient,
m.CaseBaseName,
)).To(Succeed(),
fmt.Sprintf("Failed to create namespace %s to install Kibishii workload",
m.CaseBaseName))
})
By("Deploy sample workload of Kibishii", func() {
Expect(kibishii.KibishiiPrepareBeforeBackup(
m.Ctx,
*OriginVeleroCfg.DefaultClient,
OriginVeleroCfg.CloudProvider,
m.CaseBaseName,
OriginVeleroCfg.RegistryCredentialFile,
OriginVeleroCfg.Features,
OriginVeleroCfg.KibishiiDirectory,
OriginVeleroCfg.UseVolumeSnapshots,
&m.kibishiiData,
)).To(Succeed())
})
By(fmt.Sprintf("Backup namespace %s", m.CaseBaseName), func() {
m.BackupArgs = []string{
"create", "--namespace", m.VeleroCfg.VeleroNamespace,
"backup", m.BackupName,
"--include-namespaces", strings.Join(*m.NSIncluded, ","),
"--wait",
}
if m.useVolumeSnapshots {
m.BackupArgs = append(m.BackupArgs, "--snapshot-volumes=true")
} else { } else {
By(fmt.Sprintf("Uninstall Velero on cluster %s", veleroCfg.DefaultClusterContext), func() { m.BackupArgs = append(m.BackupArgs, "--default-volumes-to-fs-backup")
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*5)
defer ctxCancel()
Expect(KubectlConfigUseContext(context.Background(), veleroCfg.DefaultClusterContext)).To(Succeed())
veleroCfg.ClientToInstallVelero = veleroCfg.DefaultClient
veleroCfg.ClusterToInstallVelero = veleroCfg.DefaultClusterName
Expect(VeleroUninstall(ctx, veleroCfg)).To(Succeed())
By(fmt.Sprintf("Delete sample workload namespace %s", migrationNamespace), func() {
Expect(
DeleteNamespace(
context.Background(),
*veleroCfg.DefaultClient,
migrationNamespace,
true),
).To(Succeed())
})
})
By(fmt.Sprintf("Uninstall Velero on cluster %s", veleroCfg.StandbyClusterContext), func() {
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*5)
defer ctxCancel()
Expect(KubectlConfigUseContext(context.Background(), veleroCfg.StandbyClusterContext)).To(Succeed())
veleroCfg.ClientToInstallVelero = veleroCfg.StandbyClient
veleroCfg.ClusterToInstallVelero = veleroCfg.StandbyClusterName
By("Delete StorageClasses created by E2E")
Expect(
DeleteStorageClass(
ctx,
*veleroCfg.ClientToInstallVelero,
StorageClassName,
),
).To(Succeed())
Expect(
DeleteStorageClass(
ctx,
*veleroCfg.ClientToInstallVelero,
StorageClassName2,
),
).To(Succeed())
if strings.EqualFold(veleroCfg.Features, FeatureCSI) &&
veleroCfg.UseVolumeSnapshots {
By("Delete VolumeSnapshotClass created by E2E")
Expect(
KubectlDeleteByFile(
ctx,
fmt.Sprintf("../testdata/volume-snapshot-class/%s.yaml", veleroCfg.CloudProvider),
),
).To(Succeed())
}
Expect(VeleroUninstall(ctx, veleroCfg)).To(Succeed())
By(fmt.Sprintf("Delete sample workload namespace %s", migrationNamespace), func() {
Expect(
DeleteNamespace(
context.Background(),
*veleroCfg.StandbyClient,
migrationNamespace,
true,
),
).To(Succeed())
})
})
By(fmt.Sprintf("Switch to default KubeConfig context %s", veleroCfg.DefaultClusterContext), func() {
Expect(KubectlConfigUseContext(context.Background(), veleroCfg.DefaultClusterContext)).To(Succeed())
veleroCfg.ClientToInstallVelero = veleroCfg.DefaultClient
veleroCfg.ClusterToInstallVelero = veleroCfg.DefaultClusterName
})
} }
})
When("kibishii is the sample workload", func() {
It("should be successfully backed up and restored to the default BackupStorageLocation", func() {
var backupNames []string
if veleroCfg.SnapshotMoveData {
if !useVolumeSnapshots {
Skip("FSB migration test is not needed in data mover scenario")
}
}
oneHourTimeout, ctxCancel := context.WithTimeout(context.Background(), time.Minute*60)
defer ctxCancel()
flag.Parse()
UUIDgen, err = uuid.NewRandom()
Expect(err).To(Succeed())
supportUploaderType, err := IsSupportUploaderType(veleroCLI2Version.VeleroVersion)
Expect(err).To(Succeed())
OriginVeleroCfg := veleroCfg if OriginVeleroCfg.SnapshotMoveData {
if veleroCLI2Version.VeleroCLI == "" { m.BackupArgs = append(m.BackupArgs, "--snapshot-move-data")
//Assume tag of velero server image is identical to velero CLI version }
//Download velero CLI if it's empty according to velero CLI version
By(fmt.Sprintf("Install the expected version Velero CLI (%s) for installing Velero",
veleroCLI2Version.VeleroVersion), func() {
//"self" represents 1.14.x and future versions
if veleroCLI2Version.VeleroVersion == "self" {
veleroCLI2Version.VeleroCLI = veleroCfg.VeleroCLI
} else {
OriginVeleroCfg, err = SetImagesToDefaultValues(
OriginVeleroCfg,
veleroCLI2Version.VeleroVersion,
)
Expect(err).To(Succeed(), "Fail to set images for the migrate-from Velero installation.")
veleroCLI2Version.VeleroCLI, err = InstallVeleroCLI(veleroCLI2Version.VeleroVersion) Expect(veleroutil.VeleroBackupExec(
Expect(err).To(Succeed()) m.Ctx,
} OriginVeleroCfg.VeleroCLI,
}) OriginVeleroCfg.VeleroNamespace,
} m.BackupName,
m.BackupArgs,
By(fmt.Sprintf("Install Velero in cluster-A (%s) to backup workload", veleroCfg.DefaultClusterContext), func() { )).To(Succeed(), func() string {
Expect(KubectlConfigUseContext(context.Background(), veleroCfg.DefaultClusterContext)).To(Succeed()) veleroutil.RunDebug(
OriginVeleroCfg.MigrateFromVeleroVersion = veleroCLI2Version.VeleroVersion context.Background(),
OriginVeleroCfg.VeleroCLI = veleroCLI2Version.VeleroCLI OriginVeleroCfg.VeleroCLI,
OriginVeleroCfg.ClientToInstallVelero = OriginVeleroCfg.DefaultClient OriginVeleroCfg.VeleroNamespace,
OriginVeleroCfg.ClusterToInstallVelero = veleroCfg.DefaultClusterName m.BackupName,
OriginVeleroCfg.ServiceAccountNameToInstall = veleroCfg.DefaultCLSServiceAccountName "",
OriginVeleroCfg.UseVolumeSnapshots = useVolumeSnapshots )
OriginVeleroCfg.UseNodeAgent = !useVolumeSnapshots return "Failed to backup resources"
version, err := GetVeleroVersion(oneHourTimeout, OriginVeleroCfg.VeleroCLI, true)
Expect(err).To(Succeed(), "Fail to get Velero version")
OriginVeleroCfg.VeleroVersion = version
if OriginVeleroCfg.SnapshotMoveData {
OriginVeleroCfg.UseNodeAgent = true
}
Expect(VeleroInstall(context.Background(), &OriginVeleroCfg, false)).To(Succeed())
if veleroCLI2Version.VeleroVersion != "self" {
Expect(CheckVeleroVersion(context.Background(), OriginVeleroCfg.VeleroCLI,
OriginVeleroCfg.MigrateFromVeleroVersion)).To(Succeed())
}
})
backupName = "backup-" + UUIDgen.String()
backupScName = backupName + "-sc"
restoreName = "restore-" + UUIDgen.String()
restoreScName = restoreName + "-sc"
By("Create namespace for sample workload", func() {
Expect(CreateNamespace(oneHourTimeout, *veleroCfg.DefaultClient, migrationNamespace)).To(Succeed(),
fmt.Sprintf("Failed to create namespace %s to install Kibishii workload", migrationNamespace))
})
KibishiiData := *DefaultKibishiiData
By("Deploy sample workload of Kibishii", func() {
KibishiiData.ExpectedNodes = kibishiiWorkerCount
Expect(KibishiiPrepareBeforeBackup(oneHourTimeout, *veleroCfg.DefaultClient, veleroCfg.CloudProvider,
migrationNamespace, veleroCfg.RegistryCredentialFile, veleroCfg.Features,
veleroCfg.KibishiiDirectory, useVolumeSnapshots, &KibishiiData)).To(Succeed())
})
By(fmt.Sprintf("Backup namespace %s", migrationNamespace), func() {
var BackupStorageClassCfg BackupConfig
BackupStorageClassCfg.BackupName = backupScName
BackupStorageClassCfg.IncludeResources = "StorageClass"
BackupStorageClassCfg.IncludeClusterResources = true
//TODO Remove UseRestic parameter once minor version is 1.10 or upper
BackupStorageClassCfg.UseResticIfFSBackup = !supportUploaderType
Expect(VeleroBackupNamespace(context.Background(), OriginVeleroCfg.VeleroCLI,
OriginVeleroCfg.VeleroNamespace, BackupStorageClassCfg)).To(Succeed(), func() string {
RunDebug(context.Background(), veleroCfg.VeleroCLI, veleroCfg.VeleroNamespace, BackupStorageClassCfg.BackupName, "")
return "Fail to backup workload"
})
backupNames = append(backupNames, BackupStorageClassCfg.BackupName)
var BackupCfg BackupConfig
BackupCfg.BackupName = backupName
BackupCfg.Namespace = migrationNamespace
BackupCfg.UseVolumeSnapshots = useVolumeSnapshots
BackupCfg.BackupLocation = ""
BackupCfg.Selector = ""
BackupCfg.DefaultVolumesToFsBackup = !useVolumeSnapshots
//TODO Remove UseRestic parameter once minor version is 1.10 or upper
BackupCfg.UseResticIfFSBackup = !supportUploaderType
BackupCfg.SnapshotMoveData = OriginVeleroCfg.SnapshotMoveData
Expect(VeleroBackupNamespace(context.Background(), OriginVeleroCfg.VeleroCLI,
OriginVeleroCfg.VeleroNamespace, BackupCfg)).To(Succeed(), func() string {
RunDebug(context.Background(), OriginVeleroCfg.VeleroCLI, OriginVeleroCfg.VeleroNamespace, BackupCfg.BackupName, "")
return "Fail to backup workload"
})
backupNames = append(backupNames, BackupCfg.BackupName)
})
if useVolumeSnapshots {
// Only wait for the snapshots.backupdriver.cnsdp.vmware.com
// when the vSphere plugin is used.
if veleroCfg.HasVspherePlugin {
By("Waiting for vSphere uploads to complete", func() {
Expect(WaitForVSphereUploadCompletion(context.Background(), time.Hour,
migrationNamespace, kibishiiWorkerCount)).To(Succeed())
})
}
var snapshotCheckPoint SnapshotCheckPoint
snapshotCheckPoint.NamespaceBackedUp = migrationNamespace
if OriginVeleroCfg.SnapshotMoveData {
//VolumeSnapshotContent should be deleted after data movement
_, err := util.CheckVolumeSnapshotCR(*veleroCfg.DefaultClient, map[string]string{"namespace": migrationNamespace}, 0)
Expect(err).NotTo(HaveOccurred(), "VSC count is not as expected 0")
} else {
// the snapshots of AWS may be still in pending status when do the restore, wait for a while
// to avoid this https://github.com/vmware-tanzu/velero/issues/1799
// TODO remove this after https://github.com/vmware-tanzu/velero/issues/3533 is fixed
if veleroCfg.CloudProvider == Azure && strings.EqualFold(veleroCfg.Features, FeatureCSI) || veleroCfg.CloudProvider == AWS {
By("Sleep 5 minutes to avoid snapshot recreated by unknown reason ", func() {
time.Sleep(5 * time.Minute)
})
}
By("Snapshot should be created in cloud object store with retain policy", func() {
snapshotCheckPoint, err = GetSnapshotCheckPoint(*veleroCfg.DefaultClient, veleroCfg, kibishiiWorkerCount,
migrationNamespace, backupName, GetKibishiiPVCNameList(kibishiiWorkerCount))
Expect(err).NotTo(HaveOccurred(), "Fail to get snapshot checkpoint")
Expect(CheckSnapshotsInProvider(
veleroCfg,
backupName,
snapshotCheckPoint,
false,
)).To(Succeed())
})
}
}
By(fmt.Sprintf("Install Velero in cluster-B (%s) to restore workload", veleroCfg.StandbyClusterContext), func() {
//Ensure workload of "migrationNamespace" existed in cluster-A
ns, err := GetNamespace(context.Background(), *veleroCfg.DefaultClient, migrationNamespace)
Expect(ns.Name).To(Equal(migrationNamespace))
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("get namespace in source cluster err: %v", err))
//Ensure cluster-B is the target cluster
Expect(KubectlConfigUseContext(context.Background(), veleroCfg.StandbyClusterContext)).To(Succeed())
_, err = GetNamespace(context.Background(), *veleroCfg.StandbyClient, migrationNamespace)
Expect(err).To(HaveOccurred(), fmt.Sprintf("get namespace in dst cluster successfully, it's not as expected: %s", migrationNamespace))
fmt.Println(err)
Expect(strings.Contains(fmt.Sprint(err), "namespaces \""+migrationNamespace+"\" not found")).Should(BeTrue())
veleroCfg.ClientToInstallVelero = veleroCfg.StandbyClient
veleroCfg.ClusterToInstallVelero = veleroCfg.StandbyClusterName
veleroCfg.ServiceAccountNameToInstall = veleroCfg.StandbyCLSServiceAccountName
veleroCfg.UseNodeAgent = !useVolumeSnapshots
veleroCfg.UseRestic = false
if veleroCfg.SnapshotMoveData {
veleroCfg.UseNodeAgent = true
// For SnapshotMoveData pipelines, we should use standby cluster setting for Velero installation
// In nightly CI, StandbyClusterPlugins is set properly if pipeline is for SnapshotMoveData.
veleroCfg.Plugins = veleroCfg.StandbyClusterPlugins
veleroCfg.ObjectStoreProvider = veleroCfg.StandbyClusterObjectStoreProvider
}
By("Install StorageClass for E2E.")
Expect(InstallStorageClasses(veleroCfg.StandbyClusterCloudProvider)).To(Succeed())
if strings.EqualFold(veleroCfg.Features, FeatureCSI) &&
veleroCfg.UseVolumeSnapshots {
By("Install VolumeSnapshotClass for E2E.")
Expect(
KubectlApplyByFile(
context.Background(),
fmt.Sprintf("../testdata/volume-snapshot-class/%s.yaml", veleroCfg.StandbyClusterCloudProvider),
),
).To(Succeed())
}
Expect(VeleroInstall(context.Background(), &veleroCfg, true)).To(Succeed())
})
By(fmt.Sprintf("Waiting for backups sync to Velero in cluster-B (%s)", veleroCfg.StandbyClusterContext), func() {
Expect(WaitForBackupToBeCreated(context.Background(), backupName, 5*time.Minute, &veleroCfg)).To(Succeed())
Expect(WaitForBackupToBeCreated(context.Background(), backupScName, 5*time.Minute, &veleroCfg)).To(Succeed())
})
By(fmt.Sprintf("Restore %s", migrationNamespace), func() {
if OriginVeleroCfg.SnapshotMoveData {
cmName := "datamover-storage-class-config"
labels := map[string]string{"velero.io/change-storage-class": "RestoreItemAction",
"velero.io/plugin-config": ""}
data := map[string]string{KibishiiStorageClassName: StorageClassName}
By(fmt.Sprintf("Create ConfigMap %s in namespace %s", cmName, veleroCfg.VeleroNamespace), func() {
_, err := CreateConfigMap(veleroCfg.StandbyClient.ClientGo, veleroCfg.VeleroNamespace, cmName, labels, data)
Expect(err).To(Succeed(), fmt.Sprintf("failed to create configmap in the namespace %q", veleroCfg.VeleroNamespace))
})
} else {
Expect(VeleroRestore(context.Background(), veleroCfg.VeleroCLI,
veleroCfg.VeleroNamespace, restoreScName, backupScName, "StorageClass")).To(Succeed(), func() string {
RunDebug(context.Background(), veleroCfg.VeleroCLI,
veleroCfg.VeleroNamespace, "", restoreName)
return "Fail to restore workload"
})
}
Expect(VeleroRestore(context.Background(), veleroCfg.VeleroCLI,
veleroCfg.VeleroNamespace, restoreName, backupName, "")).To(Succeed(), func() string {
RunDebug(context.Background(), veleroCfg.VeleroCLI,
veleroCfg.VeleroNamespace, "", restoreName)
return "Fail to restore workload"
})
})
By(fmt.Sprintf("Verify workload %s after restore ", migrationNamespace), func() {
Expect(KibishiiVerifyAfterRestore(*veleroCfg.StandbyClient, migrationNamespace,
oneHourTimeout, &KibishiiData, "")).To(Succeed(), "Fail to verify workload after restore")
})
// TODO: delete backup created by case self, not all
By("Clean backups after test", func() {
veleroCfg.ClientToInstallVelero = veleroCfg.DefaultClient
Expect(DeleteBackups(context.Background(), backupNames, &veleroCfg)).To(Succeed())
})
}) })
}) })
if m.useVolumeSnapshots {
// Only wait for the snapshots.backupdriver.cnsdp.vmware.com
// when the vSphere plugin is used.
if OriginVeleroCfg.HasVspherePlugin {
By("Waiting for vSphere uploads to complete", func() {
Expect(
veleroutil.WaitForVSphereUploadCompletion(
context.Background(),
time.Hour,
m.CaseBaseName,
m.kibishiiData.ExpectedNodes,
),
).To(Succeed())
})
}
var snapshotCheckPoint test.SnapshotCheckPoint
snapshotCheckPoint.NamespaceBackedUp = m.CaseBaseName
if OriginVeleroCfg.SnapshotMoveData {
//VolumeSnapshotContent should be deleted after data movement
_, err := util.CheckVolumeSnapshotCR(
*m.VeleroCfg.DefaultClient,
map[string]string{"namespace": m.CaseBaseName},
0,
)
By("Check the VSC account", func() {
Expect(err).NotTo(HaveOccurred(), "VSC count is not as expected 0")
})
} else {
// the snapshots of AWS may be still in pending status when do the restore.
// wait for a while to avoid this https://github.com/vmware-tanzu/velero/issues/1799
if OriginVeleroCfg.CloudProvider == test.Azure &&
strings.EqualFold(OriginVeleroCfg.Features, test.FeatureCSI) ||
OriginVeleroCfg.CloudProvider == test.AWS {
By("Sleep 5 minutes to avoid snapshot recreated by unknown reason ", func() {
time.Sleep(5 * time.Minute)
})
}
By("Snapshot should be created in cloud object store with retain policy", func() {
snapshotCheckPoint, err = veleroutil.GetSnapshotCheckPoint(
*OriginVeleroCfg.DefaultClient,
OriginVeleroCfg,
m.kibishiiData.ExpectedNodes,
m.CaseBaseName,
m.BackupName,
kibishii.GetKibishiiPVCNameList(m.kibishiiData.ExpectedNodes),
)
Expect(err).NotTo(HaveOccurred(), "Fail to get snapshot checkpoint")
Expect(providers.CheckSnapshotsInProvider(
OriginVeleroCfg,
m.BackupName,
snapshotCheckPoint,
false,
)).To(Succeed())
})
}
}
return nil
}
func (m *migrationE2E) Restore() error {
StandbyVeleroCfg := m.VeleroCfg
By("Install Velero in standby cluster.", func() {
// Ensure cluster-B is the target cluster
Expect(k8sutil.KubectlConfigUseContext(
m.Ctx, m.VeleroCfg.StandbyClusterContext)).To(Succeed())
// Check the workload namespace not exist in standby cluster.
_, err := k8sutil.GetNamespace(
m.Ctx, *m.VeleroCfg.StandbyClient, m.CaseBaseName)
Expect(err).To(HaveOccurred(), fmt.Sprintf(
"get namespace in dst cluster successfully, it's not as expected: %s", m.CaseBaseName))
Expect(strings.Contains(fmt.Sprint(err), "namespaces \""+m.CaseBaseName+"\" not found")).
Should(BeTrue())
By("Install StorageClass for E2E.")
Expect(veleroutil.InstallStorageClasses(
m.VeleroCfg.StandbyClusterCloudProvider)).To(Succeed())
if strings.EqualFold(m.VeleroCfg.Features, test.FeatureCSI) &&
m.VeleroCfg.UseVolumeSnapshots {
By("Install VolumeSnapshotClass for E2E.")
Expect(
k8sutil.KubectlApplyByFile(
m.Ctx,
fmt.Sprintf("../testdata/volume-snapshot-class/%s.yaml",
m.VeleroCfg.StandbyClusterCloudProvider),
),
).To(Succeed())
}
StandbyVeleroCfg.ClientToInstallVelero = m.VeleroCfg.StandbyClient
StandbyVeleroCfg.ClusterToInstallVelero = m.VeleroCfg.StandbyClusterName
StandbyVeleroCfg.ServiceAccountNameToInstall = m.VeleroCfg.StandbyCLSServiceAccountName
StandbyVeleroCfg.UseNodeAgent = !m.useVolumeSnapshots
if StandbyVeleroCfg.SnapshotMoveData {
StandbyVeleroCfg.UseNodeAgent = true
// For SnapshotMoveData pipelines, we should use standby cluster setting
// for Velero installation.
// In nightly CI, StandbyClusterPlugins is set properly
// if pipeline is for SnapshotMoveData.
StandbyVeleroCfg.Plugins = m.VeleroCfg.StandbyClusterPlugins
StandbyVeleroCfg.ObjectStoreProvider = m.VeleroCfg.StandbyClusterObjectStoreProvider
}
Expect(veleroutil.VeleroInstall(
context.Background(), &StandbyVeleroCfg, true)).To(Succeed())
})
By("Waiting for backups sync to Velero in standby cluster", func() {
Expect(veleroutil.WaitForBackupToBeCreated(
m.Ctx, m.BackupName, 5*time.Minute, &StandbyVeleroCfg)).To(Succeed())
})
By(fmt.Sprintf("Restore %s", m.CaseBaseName), func() {
if m.VeleroCfg.SnapshotMoveData {
cmName := "datamover-storage-class-config"
labels := map[string]string{"velero.io/change-storage-class": "RestoreItemAction",
"velero.io/plugin-config": ""}
data := map[string]string{kibishii.KibishiiStorageClassName: test.StorageClassName}
By(fmt.Sprintf("Create ConfigMap %s in namespace %s",
cmName, StandbyVeleroCfg.VeleroNamespace), func() {
_, err := k8sutil.CreateConfigMap(
StandbyVeleroCfg.StandbyClient.ClientGo,
StandbyVeleroCfg.VeleroNamespace,
cmName,
labels,
data,
)
Expect(err).To(Succeed(), fmt.Sprintf(
"failed to create ConfigMap in the namespace %q",
StandbyVeleroCfg.VeleroNamespace))
})
}
Expect(veleroutil.VeleroRestore(
m.Ctx,
StandbyVeleroCfg.VeleroCLI,
StandbyVeleroCfg.VeleroNamespace,
m.RestoreName,
m.BackupName,
"",
)).To(Succeed(), func() string {
veleroutil.RunDebug(
m.Ctx, StandbyVeleroCfg.VeleroCLI,
StandbyVeleroCfg.VeleroNamespace, "", m.RestoreName)
return "Fail to restore workload"
})
})
return nil
}
func (m *migrationE2E) Verify() error {
By(fmt.Sprintf("Verify workload %s after restore on standby cluster", m.CaseBaseName), func() {
Expect(kibishii.KibishiiVerifyAfterRestore(
*m.VeleroCfg.StandbyClient,
m.CaseBaseName,
m.Ctx,
&m.kibishiiData,
"",
)).To(Succeed(), "Fail to verify workload after restore")
})
return nil
}
func (m *migrationE2E) Clean() error {
By("Clean resource on default cluster.", func() {
Expect(m.TestCase.Clean()).To(Succeed())
})
By("Clean resource on standby cluster.", func() {
Expect(k8sutil.KubectlConfigUseContext(
m.Ctx, m.VeleroCfg.StandbyClusterContext)).To(Succeed())
m.VeleroCfg.ClientToInstallVelero = m.VeleroCfg.StandbyClient
m.VeleroCfg.ClusterToInstallVelero = m.VeleroCfg.StandbyClusterName
By("Delete StorageClasses created by E2E")
Expect(
k8sutil.DeleteStorageClass(
m.Ctx,
*m.VeleroCfg.ClientToInstallVelero,
test.StorageClassName,
),
).To(Succeed())
Expect(
k8sutil.DeleteStorageClass(
m.Ctx,
*m.VeleroCfg.ClientToInstallVelero,
test.StorageClassName2,
),
).To(Succeed())
if strings.EqualFold(m.VeleroCfg.Features, test.FeatureCSI) &&
m.VeleroCfg.UseVolumeSnapshots {
By("Delete VolumeSnapshotClass created by E2E")
Expect(
k8sutil.KubectlDeleteByFile(
m.Ctx,
fmt.Sprintf("../testdata/volume-snapshot-class/%s.yaml",
m.VeleroCfg.StandbyClusterCloudProvider),
),
).To(Succeed())
}
Expect(veleroutil.VeleroUninstall(m.Ctx, m.VeleroCfg)).To(Succeed())
Expect(
k8sutil.DeleteNamespace(
m.Ctx,
*m.VeleroCfg.StandbyClient,
m.CaseBaseName,
true,
),
).To(Succeed())
})
By("Switch to default KubeConfig context", func() {
Expect(k8sutil.KubectlConfigUseContext(
m.Ctx,
m.VeleroCfg.DefaultClusterContext,
)).To(Succeed())
})
return nil
} }

View File

@ -91,8 +91,9 @@ func TestFuncWithMultiIt(tests []VeleroBackupRestoreTest) func() {
} }
func TestIt(test VeleroBackupRestoreTest) error { func TestIt(test VeleroBackupRestoreTest) error {
test.Init() It("Run E2E test case", func() {
It(test.GetTestMsg().Text, func() { Expect(test.Init()).To(Succeed())
Expect(RunTestCase(test)).To(Succeed(), test.GetTestMsg().FailedMSG) Expect(RunTestCase(test)).To(Succeed(), test.GetTestMsg().FailedMSG)
}) })
return nil return nil
@ -213,6 +214,7 @@ func RunTestCase(test VeleroBackupRestoreTest) error {
if test == nil { if test == nil {
return errors.New("No case should be tested") return errors.New("No case should be tested")
} }
fmt.Println("Running case: ", test.GetTestMsg().Text)
test.Start() test.Start()
defer test.GetTestCase().CtxCancel() defer test.GetTestCase().CtxCancel()

View File

@ -138,13 +138,7 @@ func BackupUpgradeRestoreTest(useVolumeSnapshots bool, veleroCLI2Version VeleroC
tmpCfgForOldVeleroInstall.VeleroVersion = version tmpCfgForOldVeleroInstall.VeleroVersion = version
tmpCfgForOldVeleroInstall.UseVolumeSnapshots = useVolumeSnapshots tmpCfgForOldVeleroInstall.UseVolumeSnapshots = useVolumeSnapshots
if supportUploaderType { tmpCfgForOldVeleroInstall.UseNodeAgent = !useVolumeSnapshots
tmpCfgForOldVeleroInstall.UseRestic = false
tmpCfgForOldVeleroInstall.UseNodeAgent = !useVolumeSnapshots
} else {
tmpCfgForOldVeleroInstall.UseRestic = !useVolumeSnapshots
tmpCfgForOldVeleroInstall.UseNodeAgent = false
}
Expect(VeleroInstall(context.Background(), &tmpCfgForOldVeleroInstall, false)).To(Succeed()) Expect(VeleroInstall(context.Background(), &tmpCfgForOldVeleroInstall, false)).To(Succeed())
Expect(CheckVeleroVersion(context.Background(), tmpCfgForOldVeleroInstall.VeleroCLI, Expect(CheckVeleroVersion(context.Background(), tmpCfgForOldVeleroInstall.VeleroCLI,
@ -230,7 +224,6 @@ func BackupUpgradeRestoreTest(useVolumeSnapshots bool, veleroCLI2Version VeleroC
By(fmt.Sprintf("Upgrade Velero by CLI %s", tmpCfg.VeleroCLI), func() { By(fmt.Sprintf("Upgrade Velero by CLI %s", tmpCfg.VeleroCLI), func() {
tmpCfg.GCFrequency = "" tmpCfg.GCFrequency = ""
tmpCfg.UseRestic = false
tmpCfg.UseNodeAgent = !useVolumeSnapshots tmpCfg.UseNodeAgent = !useVolumeSnapshots
Expect(err).To(Succeed()) Expect(err).To(Succeed())
if supportUploaderType { if supportUploaderType {

View File

@ -113,8 +113,8 @@ func GetVolumeSnapshotContentNameByPod(client TestClient, podName, namespace, ba
if len(pvList) != 1 { if len(pvList) != 1 {
return "", errors.New(fmt.Sprintf("Only 1 PV of PVC %s pod %s should be found under namespace %s", pvcList[0], podName, namespace)) return "", errors.New(fmt.Sprintf("Only 1 PV of PVC %s pod %s should be found under namespace %s", pvcList[0], podName, namespace))
} }
pv_value, err := GetPersistentVolume(context.Background(), client, "", pvList[0]) pvValue, err := GetPersistentVolume(context.Background(), client, "", pvList[0])
fmt.Println(pv_value.Annotations["pv.kubernetes.io/provisioned-by"]) fmt.Println(pvValue.Annotations["pv.kubernetes.io/provisioned-by"])
if err != nil { if err != nil {
return "", err return "", err
} }
@ -148,14 +148,10 @@ func CheckVolumeSnapshotCR(client TestClient, index map[string]string, expectedC
if len(apiVersion) == 0 { if len(apiVersion) == 0 {
return nil, errors.New("Fail to get APIVersion") return nil, errors.New("Fail to get APIVersion")
} }
// if apiVersion[0] == "v1beta1" {
// if snapshotContentNameList, err = GetCsiSnapshotHandle(client, apiVersion[0], index); err != nil {
// return nil, errors.Wrap(err, "Fail to get Azure CSI snapshot content")
// }
// } else
if apiVersion[0] == "v1" { if apiVersion[0] == "v1" {
if snapshotContentNameList, err = GetCsiSnapshotHandle(client, apiVersion[0], index); err != nil { if snapshotContentNameList, err = GetCsiSnapshotHandle(client, apiVersion[0], index); err != nil {
return nil, errors.Wrap(err, "Fail to get Azure CSI snapshot content") return nil, errors.Wrap(err, "Fail to get CSI snapshot content")
} }
} else { } else {
return nil, errors.New("API version is invalid") return nil, errors.New("API version is invalid")

View File

@ -271,9 +271,6 @@ func installVeleroServer(ctx context.Context, cli, cloudProvider string, options
if len(options.Image) > 0 { if len(options.Image) > 0 {
args = append(args, "--image", options.Image) args = append(args, "--image", options.Image)
} }
if options.UseRestic {
args = append(args, "--use-restic")
}
if options.UseNodeAgent { if options.UseNodeAgent {
args = append(args, "--use-node-agent") args = append(args, "--use-node-agent")
} }

View File

@ -255,10 +255,7 @@ func getProviderVeleroInstallOptions(veleroCfg *VeleroConfig,
io.DefaultVolumesToFsBackup = veleroCfg.DefaultVolumesToFsBackup io.DefaultVolumesToFsBackup = veleroCfg.DefaultVolumesToFsBackup
io.UseVolumeSnapshots = veleroCfg.UseVolumeSnapshots io.UseVolumeSnapshots = veleroCfg.UseVolumeSnapshots
if !veleroCfg.UseRestic { io.UseNodeAgent = veleroCfg.UseNodeAgent
io.UseNodeAgent = veleroCfg.UseNodeAgent
}
io.UseRestic = veleroCfg.UseRestic
io.Image = veleroCfg.VeleroImage io.Image = veleroCfg.VeleroImage
io.Namespace = veleroCfg.VeleroNamespace io.Namespace = veleroCfg.VeleroNamespace
io.UploaderType = veleroCfg.UploaderType io.UploaderType = veleroCfg.UploaderType