From ea413ce9365b83152c07dbdd40a451af98bdf3ff Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 6 Aug 2025 10:19:26 -0600 Subject: [PATCH 1/6] create a test case for match labels Signed-off-by: Wesley Hayutin --- tests/e2e/backup_restore_suite_test.go | 40 +++++++++++++------ tests/e2e/lib/backup.go | 20 ++++++++++ .../mysql-persistent/mysql-backup-labels.yaml | 11 +++++ .../mysql-restore-labels.yaml | 8 ++++ 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml create mode 100644 tests/e2e/sample-applications/mysql-persistent/mysql-restore-labels.yaml diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index c28cc85d18..eb198d5020 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 { @@ -163,20 +164,35 @@ func runApplicationBackupAndRestore(brCase ApplicationBackupRestoreCase, updateL } func runBackup(brCase BackupRestoreCase, backupName string) bool { - nsRequiresResticDCWorkaround, err := lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) - gomega.Expect(err).ToNot(gomega.HaveOccurred()) + var nsRequiresResticDCWorkaround bool + var err error - if strings.Contains(brCase.Name, "twovol") { - volumeSyncDelay := 30 * time.Second - log.Printf("Sleeping for %v to allow volume to be in sync with /tmp/log/ for case %s", volumeSyncDelay, brCase.Name) - // TODO this should be a function, not an arbitrary sleep - time.Sleep(volumeSyncDelay) - } + if brCase.Namespace != "" { + nsRequiresResticDCWorkaround, err = lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) - // 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 strings.Contains(brCase.Name, "twovol") { + volumeSyncDelay := 30 * time.Second + log.Printf("Sleeping for %v to allow volume to be in sync with /tmp/log/ for case %s", volumeSyncDelay, brCase.Name) + // TODO this should be a function, not an arbitrary sleep + time.Sleep(volumeSyncDelay) + } + + // 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()) + } else { + // 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, []string{}, 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()) diff --git a/tests/e2e/lib/backup.go b/tests/e2e/lib/backup.go index 2836b5e98b..075781cbcc 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, namespaces []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/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..b353d0f5de --- /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: mysql + storageLocation: dpa-sample-1 + ttl: 720h0m0s 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 From d1b8ddd59e86697ce3f8d1f01d2157ef99ff8583 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 6 Aug 2025 11:32:46 -0600 Subject: [PATCH 2/6] udpate labels --- tests/e2e/backup_restore_suite_test.go | 12 ++++++++++++ .../mysql-persistent/mysql-backup-labels.yaml | 2 +- .../mysql-persistent/mysql-persistent-csi.yaml | 15 ++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index eb198d5020..281e62a426 100644 --- a/tests/e2e/backup_restore_suite_test.go +++ b/tests/e2e/backup_restore_suite_test.go @@ -337,6 +337,18 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() { } runApplicationBackupAndRestore(brCase, updateLastBRcase, updateLastInstallTime) }, + ginkgo.Entry("MySQL application label CSI", ginkgo.FlakeAttempts(flakeAttempts), ApplicationBackupRestoreCase{ + ApplicationTemplate: "./sample-applications/mysql-persistent/mysql-persistent-csi.yaml", + BackupRestoreCase: BackupRestoreCase{ + Namespace: "", + LabelSelector: map[string]string{"app": "mysql"}, + Name: "mysql-csi-label-e2e", + BackupRestoreType: lib.CSI, + 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/sample-applications/mysql-persistent/mysql-backup-labels.yaml b/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml index b353d0f5de..05fdc5bf08 100644 --- a/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml +++ b/tests/e2e/sample-applications/mysql-persistent/mysql-backup-labels.yaml @@ -6,6 +6,6 @@ metadata: spec: labelSelector: matchLabels: - app: mysql + 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..fa7070b1db 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,6 +14,7 @@ items: namespace: mysql-persistent labels: component: mysql-persistent + app: todolist - kind: SecurityContextConstraints apiVersion: security.openshift.io/v1 metadata: @@ -41,7 +42,7 @@ items: name: mysql namespace: mysql-persistent labels: - app: mysql + app: todolist service: mysql spec: ports: @@ -49,7 +50,7 @@ items: name: mysql port: 3306 selector: - app: mysql + app: todolist - apiVersion: apps/v1 kind: Deployment metadata: @@ -62,14 +63,14 @@ items: 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 +193,10 @@ items: metadata: name: todolist-route namespace: mysql-persistent + labels: + app: todolist + service: todolist + e2e-app: "true" spec: path: "/" to: From ad735881ed9f5cb29ebad8eca4279182d86f57a8 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 6 Aug 2025 12:14:17 -0600 Subject: [PATCH 3/6] properly break out the label case --- tests/e2e/backup_restore_suite_test.go | 32 ++++++++++++++------------ tests/e2e/lib/dpa_helpers.go | 1 + 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index 281e62a426..26b9fbd089 100644 --- a/tests/e2e/backup_restore_suite_test.go +++ b/tests/e2e/backup_restore_suite_test.go @@ -167,22 +167,24 @@ func runBackup(brCase BackupRestoreCase, backupName string) bool { var nsRequiresResticDCWorkaround bool var err error - if brCase.Namespace != "" { - nsRequiresResticDCWorkaround, err = lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) - gomega.Expect(err).ToNot(gomega.HaveOccurred()) + nsRequiresResticDCWorkaround, err = lib.NamespaceRequiresResticDCWorkaround(dpaCR.Client, brCase.Namespace) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) - if strings.Contains(brCase.Name, "twovol") { - volumeSyncDelay := 30 * time.Second - log.Printf("Sleeping for %v to allow volume to be in sync with /tmp/log/ for case %s", volumeSyncDelay, brCase.Name) - // TODO this should be a function, not an arbitrary sleep - time.Sleep(volumeSyncDelay) - } + if strings.Contains(brCase.Name, "twovol") { + volumeSyncDelay := 30 * time.Second + log.Printf("Sleeping for %v to allow volume to be in sync with /tmp/log/ for case %s", volumeSyncDelay, brCase.Name) + // TODO this should be a function, not an arbitrary sleep + time.Sleep(volumeSyncDelay) + } - // create backup - log.Printf("Creating backup %s for case %s", backupName, brCase.Name) + // create backup + log.Printf("Creating backup %s for case %s", backupName, brCase.Name) + 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()) - } else { + } + + if brCase.BackupRestoreType == lib.CSILabel { // Extract the first key-value pair from LabelSelector var labelKey, labelValue string for k, v := range brCase.LabelSelector { @@ -337,13 +339,13 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() { } runApplicationBackupAndRestore(brCase, updateLastBRcase, updateLastInstallTime) }, - ginkgo.Entry("MySQL application label CSI", ginkgo.FlakeAttempts(flakeAttempts), ApplicationBackupRestoreCase{ + ginkgo.Entry("MySQL-label application CSI", ginkgo.FlakeAttempts(flakeAttempts), ApplicationBackupRestoreCase{ ApplicationTemplate: "./sample-applications/mysql-persistent/mysql-persistent-csi.yaml", BackupRestoreCase: BackupRestoreCase{ - Namespace: "", + Namespace: "mysql-persistent", LabelSelector: map[string]string{"app": "mysql"}, Name: "mysql-csi-label-e2e", - BackupRestoreType: lib.CSI, + BackupRestoreType: lib.CSILabel, PreBackupVerify: todoListReady(true, false, "mysql"), PostRestoreVerify: todoListReady(false, false, "mysql"), BackupTimeout: 20 * time.Minute, 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 { From d5fb9fb83a943ffe314af864413f1a5a5113b6f9 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 6 Aug 2025 12:53:06 -0600 Subject: [PATCH 4/6] remove namespaces param from createbackupforlabeles function --- tests/e2e/backup_restore_suite_test.go | 2 +- tests/e2e/lib/backup.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index 26b9fbd089..594ad88d2b 100644 --- a/tests/e2e/backup_restore_suite_test.go +++ b/tests/e2e/backup_restore_suite_test.go @@ -192,7 +192,7 @@ func runBackup(brCase BackupRestoreCase, backupName string) bool { labelValue = v break // Take the first key-value pair } - err = lib.CreateBackupForLabels(dpaCR.Client, namespace, backupName, []string{}, labelKey, labelValue, brCase.BackupRestoreType == lib.RESTIC || brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover) + 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()) } diff --git a/tests/e2e/lib/backup.go b/tests/e2e/lib/backup.go index 075781cbcc..e6f5a077f3 100755 --- a/tests/e2e/lib/backup.go +++ b/tests/e2e/lib/backup.go @@ -50,7 +50,7 @@ func CreateCustomBackupForNamespaces(ocClient client.Client, veleroNamespace, ba return ocClient.Create(context.Background(), &backup) } -func CreateBackupForLabels(ocClient client.Client, veleroNamespace, backupName string, namespaces []string, labelKey, labelValue string, defaultVolumesToFsBackup bool, snapshotMoveData bool) error { +func CreateBackupForLabels(ocClient client.Client, veleroNamespace, backupName string, labelKey, labelValue string, defaultVolumesToFsBackup bool, snapshotMoveData bool) error { backup := velero.Backup{ ObjectMeta: metav1.ObjectMeta{ Name: backupName, From 72a081c044bc2a0f4b4edbad7b536b3984697159 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Thu, 7 Aug 2025 12:17:35 -0600 Subject: [PATCH 5/6] fix label and pvc Signed-off-by: Wesley Hayutin --- tests/e2e/backup_restore_suite_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/backup_restore_suite_test.go b/tests/e2e/backup_restore_suite_test.go index 594ad88d2b..9de31461e8 100644 --- a/tests/e2e/backup_restore_suite_test.go +++ b/tests/e2e/backup_restore_suite_test.go @@ -111,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 @@ -343,7 +343,7 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() { ApplicationTemplate: "./sample-applications/mysql-persistent/mysql-persistent-csi.yaml", BackupRestoreCase: BackupRestoreCase{ Namespace: "mysql-persistent", - LabelSelector: map[string]string{"app": "mysql"}, + LabelSelector: map[string]string{"app": "todolist"}, Name: "mysql-csi-label-e2e", BackupRestoreType: lib.CSILabel, PreBackupVerify: todoListReady(true, false, "mysql"), From 5677a21d00ea9a2127a90d2f312383de9ee071f5 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Thu, 7 Aug 2025 14:33:13 -0600 Subject: [PATCH 6/6] missed a few labels Signed-off-by: Wesley Hayutin --- .../mysql-persistent/mysql-persistent-csi.yaml | 3 +++ 1 file changed, 3 insertions(+) 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 fa7070b1db..776de1f2bc 100644 --- a/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml +++ b/tests/e2e/sample-applications/mysql-persistent/mysql-persistent-csi.yaml @@ -19,6 +19,8 @@ items: apiVersion: security.openshift.io/v1 metadata: name: mysql-persistent-scc + labels: + app: todolist allowPrivilegeEscalation: true allowPrivilegedContainer: true runAsUser: @@ -60,6 +62,7 @@ items: namespace: mysql-persistent labels: e2e-app: "true" + app: todolist spec: selector: matchLabels: