diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index c28cc85d18..9de31461e8 100644 --- a/tests/e2e/backup_restore_suite_test.go +++ b/tests/e2e/backup_restore_suite_test.go @@ -25,6 +25,7 @@ type BackupRestoreCase struct { PostRestoreVerify VerificationFunction SkipVerifyLogs bool // TODO remove BackupTimeout time.Duration + LabelSelector map[string]string } type ApplicationBackupRestoreCase struct { @@ -110,7 +111,7 @@ func runApplicationBackupAndRestore(brCase ApplicationBackupRestoreCase, updateL log.Printf("Installing application for case %s", brCase.Name) err := lib.InstallApplication(dpaCR.Client, brCase.ApplicationTemplate) gomega.Expect(err).ToNot(gomega.HaveOccurred()) - if brCase.BackupRestoreType == lib.CSI || brCase.BackupRestoreType == lib.CSIDataMover { + if brCase.BackupRestoreType == lib.CSI || brCase.BackupRestoreType == lib.CSIDataMover || brCase.BackupRestoreType == lib.CSILabel { log.Printf("Creating pvc for case %s", brCase.Name) var pvcName string var pvcPath string @@ -163,7 +164,10 @@ func runApplicationBackupAndRestore(brCase ApplicationBackupRestoreCase, updateL } func runBackup(brCase BackupRestoreCase, backupName string) bool { - nsRequiresResticDCWorkaround, err := lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) + var nsRequiresResticDCWorkaround bool + var err error + + nsRequiresResticDCWorkaround, err = lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) gomega.Expect(err).ToNot(gomega.HaveOccurred()) if strings.Contains(brCase.Name, "twovol") { @@ -175,8 +179,22 @@ func runBackup(brCase BackupRestoreCase, backupName string) bool { // create backup log.Printf("Creating backup %s for case %s", backupName, brCase.Name) - err = lib.CreateBackupForNamespaces(dpaCR.Client, namespace, backupName, []string{brCase.Namespace}, brCase.BackupRestoreType == lib.RESTIC || brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover) - gomega.Expect(err).ToNot(gomega.HaveOccurred()) + if brCase.BackupRestoreType != lib.CSILabel { + err = lib.CreateBackupForNamespaces(dpaCR.Client, namespace, backupName, []string{brCase.Namespace}, brCase.BackupRestoreType == lib.RESTIC || brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + } + + if brCase.BackupRestoreType == lib.CSILabel { + // Extract the first key-value pair from LabelSelector + var labelKey, labelValue string + for k, v := range brCase.LabelSelector { + labelKey = k + labelValue = v + break // Take the first key-value pair + } + err = lib.CreateBackupForLabels(dpaCR.Client, namespace, backupName, labelKey, labelValue, brCase.BackupRestoreType == lib.RESTIC || brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + } // wait for backup to not be running gomega.Eventually(lib.IsBackupDone(dpaCR.Client, namespace, backupName), brCase.BackupTimeout, time.Second*10).Should(gomega.BeTrue()) @@ -321,6 +339,18 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() { } runApplicationBackupAndRestore(brCase, updateLastBRcase, updateLastInstallTime) }, + ginkgo.Entry("MySQL-label application CSI", ginkgo.FlakeAttempts(flakeAttempts), ApplicationBackupRestoreCase{ + ApplicationTemplate: "./sample-applications/mysql-persistent/mysql-persistent-csi.yaml", + BackupRestoreCase: BackupRestoreCase{ + Namespace: "mysql-persistent", + LabelSelector: map[string]string{"app": "todolist"}, + Name: "mysql-csi-label-e2e", + BackupRestoreType: lib.CSILabel, + PreBackupVerify: todoListReady(true, false, "mysql"), + PostRestoreVerify: todoListReady(false, false, "mysql"), + BackupTimeout: 20 * time.Minute, + }, + }, nil), ginkgo.Entry("MySQL application CSI", ginkgo.FlakeAttempts(flakeAttempts), ApplicationBackupRestoreCase{ ApplicationTemplate: "./sample-applications/mysql-persistent/mysql-persistent-csi.yaml", BackupRestoreCase: BackupRestoreCase{ diff --git a/tests/e2e/lib/backup.go b/tests/e2e/lib/backup.go index 2836b5e98b..e6f5a077f3 100755 --- a/tests/e2e/lib/backup.go +++ b/tests/e2e/lib/backup.go @@ -50,6 +50,26 @@ func CreateCustomBackupForNamespaces(ocClient client.Client, veleroNamespace, ba return ocClient.Create(context.Background(), &backup) } +func CreateBackupForLabels(ocClient client.Client, veleroNamespace, backupName string, labelKey, labelValue string, defaultVolumesToFsBackup bool, snapshotMoveData bool) error { + backup := velero.Backup{ + ObjectMeta: metav1.ObjectMeta{ + Name: backupName, + Namespace: veleroNamespace, + }, + Spec: velero.BackupSpec{ + IncludedNamespaces: []string{}, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + labelKey: labelValue, + }, + }, + DefaultVolumesToFsBackup: &defaultVolumesToFsBackup, + SnapshotMoveData: &snapshotMoveData, + }, + } + return ocClient.Create(context.Background(), &backup) +} + func GetBackup(c client.Client, namespace string, name string) (*velero.Backup, error) { backup := velero.Backup{} err := c.Get(context.Background(), client.ObjectKey{ diff --git a/tests/e2e/lib/dpa_helpers.go b/tests/e2e/lib/dpa_helpers.go index 71c4c8c008..9e56ebef07 100644 --- a/tests/e2e/lib/dpa_helpers.go +++ b/tests/e2e/lib/dpa_helpers.go @@ -29,6 +29,7 @@ const ( RESTIC BackupRestoreType = "restic" KOPIA BackupRestoreType = "kopia" NativeSnapshots BackupRestoreType = "native-snapshots" + CSILabel BackupRestoreType = "csi-label" ) type DpaCustomResource struct { diff --git a/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml b/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml new file mode 100644 index 0000000000..05fdc5bf08 --- /dev/null +++ b/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml @@ -0,0 +1,11 @@ +apiVersion: velero.io/v1 +kind: Backup +metadata: + name: mysql-persistent-labels + namespace: openshift-adp +spec: + labelSelector: + matchLabels: + app: todolist + storageLocation: dpa-sample-1 + ttl: 720h0m0s diff --git a/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml b/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml index 08cbf922f1..776de1f2bc 100644 --- a/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml +++ b/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml @@ -6,7 +6,7 @@ items: metadata: name: mysql-persistent labels: - app: mysql + app: todolist - apiVersion: v1 kind: ServiceAccount metadata: @@ -14,10 +14,13 @@ items: namespace: mysql-persistent labels: component: mysql-persistent + app: todolist - kind: SecurityContextConstraints apiVersion: security.openshift.io/v1 metadata: name: mysql-persistent-scc + labels: + app: todolist allowPrivilegeEscalation: true allowPrivilegedContainer: true runAsUser: @@ -41,7 +44,7 @@ items: name: mysql namespace: mysql-persistent labels: - app: mysql + app: todolist service: mysql spec: ports: @@ -49,7 +52,7 @@ items: name: mysql port: 3306 selector: - app: mysql + app: todolist - apiVersion: apps/v1 kind: Deployment metadata: @@ -59,17 +62,18 @@ items: namespace: mysql-persistent labels: e2e-app: "true" + app: todolist spec: selector: matchLabels: - app: mysql + app: todolist strategy: type: Recreate template: metadata: labels: e2e-app: "true" - app: mysql + app: todolist curl-tool: "true" spec: securityContext: @@ -192,6 +196,10 @@ items: metadata: name: todolist-route namespace: mysql-persistent + labels: + app: todolist + service: todolist + e2e-app: "true" spec: path: "/" to: diff --git a/tests/e2e/sample-applications/mysql-persistent/mysql-restore-labels.yaml b/tests/e2e/sample-applications/mysql-persistent/mysql-restore-labels.yaml new file mode 100644 index 0000000000..3fc1d26676 --- /dev/null +++ b/tests/e2e/sample-applications/mysql-persistent/mysql-restore-labels.yaml @@ -0,0 +1,8 @@ +apiVersion: velero.io/v1 +kind: Restore +metadata: + name: mysql-persistent-labels + namespace: openshift-adp +spec: + backupName: mysql-persistent-labels + restorePVs: true