Skip to content

Commit 44d4afc

Browse files
authored
Add imagestream, deploymentconfig, hooks app back to oadp-e2e (#1993)
* parks-app-oadp * add the manifest.yaml * blah * fixes * all working * cleanup * fix curl for todolist * fix lint issue
1 parent 5c1e63f commit 44d4afc

File tree

7 files changed

+588
-74
lines changed

7 files changed

+588
-74
lines changed

tests/e2e/backup_restore_suite_test.go

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@ import (
2424
type VerificationFunction func(client.Client, string) error
2525

2626
type BackupRestoreCase struct {
27-
Namespace string
28-
Name string
29-
BackupRestoreType lib.BackupRestoreType
30-
PreBackupVerify VerificationFunction
31-
PostRestoreVerify VerificationFunction
32-
SkipVerifyLogs bool // TODO remove
33-
BackupTimeout time.Duration
27+
Namespace string
28+
Name string
29+
BackupRestoreType lib.BackupRestoreType
30+
PreBackupVerify VerificationFunction
31+
PostRestoreVerify VerificationFunction
32+
SkipVerifyLogs bool // TODO remove
33+
BackupTimeout time.Duration
34+
ExcludedResources []string // Resources to exclude from backup spec
35+
RestoreHooks *velero.RestoreHooks // Pre/post restore hooks (optional)
36+
IncludedResources []string // Resources to include in restore (optional)
37+
RestoreExcludedResources []string // Resources to exclude from restore (optional)
3438
}
3539

3640
type ApplicationBackupRestoreCase struct {
@@ -56,6 +60,18 @@ func todoListReady(preBackupState bool, twoVol bool, database string) Verificati
5660
})
5761
}
5862

63+
func parksAppReady(preBackupState bool, twoVol bool, DCReadyCheck bool) VerificationFunction {
64+
return VerificationFunction(func(ocClient client.Client, namespace string) error {
65+
log.Printf("checking parksapp for the NAMESPACE: %s", namespace)
66+
if DCReadyCheck {
67+
gomega.Eventually(lib.IsDCReady(ocClient, namespace, "restify"), time.Minute*10, time.Second*10).Should(gomega.BeTrue())
68+
}
69+
gomega.Eventually(lib.AreApplicationPodsRunning(kubernetesClientForSuiteRun, namespace), time.Minute*9, time.Second*5).Should(gomega.BeTrue())
70+
err := lib.VerifyBackupRestoreData(runTimeClientForSuiteRun, kubernetesClientForSuiteRun, kubeConfig, artifact_dir, namespace, "restify", "restify", "restify", preBackupState, twoVol)
71+
return err
72+
})
73+
}
74+
5975
func waitOADPReadiness(backupRestoreType lib.BackupRestoreType) {
6076
err := dpaCR.CreateOrUpdate(dpaCR.Build(backupRestoreType))
6177
gomega.Expect(err).NotTo(gomega.HaveOccurred())
@@ -170,6 +186,7 @@ func runApplicationBackupAndRestore(brCase ApplicationBackupRestoreCase, updateL
170186
}
171187

172188
// Wait for namespace to be deleted
189+
log.Printf("Waiting for namespace %s to be deleted", brCase.Namespace)
173190
gomega.Eventually(lib.IsNamespaceDeleted(kubernetesClientForSuiteRun, brCase.Namespace), time.Minute*4, time.Second*5).Should(gomega.BeTrue())
174191

175192
updateLastInstallTime()
@@ -198,7 +215,12 @@ func runBackup(brCase BackupRestoreCase, backupName string) bool {
198215

199216
// create backup
200217
log.Printf("Creating backup %s for case %s", backupName, brCase.Name)
201-
err = lib.CreateBackupForNamespaces(dpaCR.Client, namespace, backupName, []string{brCase.Namespace}, brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover)
218+
if len(brCase.ExcludedResources) > 0 {
219+
log.Printf("Creating backup with excluded resources: %v", brCase.ExcludedResources)
220+
err = lib.CreateCustomBackupForNamespaces(dpaCR.Client, namespace, backupName, []string{brCase.Namespace}, nil, brCase.ExcludedResources, brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover)
221+
} else {
222+
err = lib.CreateBackupForNamespaces(dpaCR.Client, namespace, backupName, []string{brCase.Namespace}, brCase.BackupRestoreType == lib.KOPIA, brCase.BackupRestoreType == lib.CSIDataMover)
223+
}
202224
gomega.Expect(err).ToNot(gomega.HaveOccurred())
203225

204226
// wait for backup to not be running
@@ -226,7 +248,24 @@ func runBackup(brCase BackupRestoreCase, backupName string) bool {
226248

227249
func runRestore(brCase BackupRestoreCase, backupName, restoreName string, nsRequiresResticDCWorkaround bool) {
228250
log.Printf("Creating restore %s for case %s", restoreName, brCase.Name)
229-
err := lib.CreateRestoreFromBackup(dpaCR.Client, namespace, backupName, restoreName)
251+
var err error
252+
253+
// Use custom restore if hooks or resource filters are specified
254+
if brCase.RestoreHooks != nil || len(brCase.IncludedResources) > 0 || len(brCase.RestoreExcludedResources) > 0 {
255+
log.Printf("Creating custom restore with hooks and/or resource filters")
256+
if brCase.RestoreHooks != nil {
257+
log.Printf("Restore hooks configured: %d resource hook(s)", len(brCase.RestoreHooks.Resources))
258+
}
259+
if len(brCase.IncludedResources) > 0 {
260+
log.Printf("Included resources: %v", brCase.IncludedResources)
261+
}
262+
if len(brCase.RestoreExcludedResources) > 0 {
263+
log.Printf("Excluded resources: %v", brCase.RestoreExcludedResources)
264+
}
265+
err = lib.CreateCustomRestoreFromBackup(dpaCR.Client, namespace, backupName, restoreName, brCase.IncludedResources, brCase.RestoreExcludedResources, brCase.RestoreHooks)
266+
} else {
267+
err = lib.CreateRestoreFromBackup(dpaCR.Client, namespace, backupName, restoreName)
268+
}
230269
gomega.Expect(err).ToNot(gomega.HaveOccurred())
231270
gomega.Eventually(lib.IsRestoreDone(dpaCR.Client, namespace, restoreName), time.Minute*60, time.Second*10).Should(gomega.BeTrue())
232271
// TODO only log on fail?
@@ -329,22 +368,25 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() {
329368
// using kopia to collect more info (DaemonSet)
330369
waitOADPReadiness(lib.KOPIA)
331370

332-
log.Printf("Creating real DataProtectionTest before must-gather")
333-
bsls, err := dpaCR.ListBSLs()
334-
gomega.Expect(err).ToNot(gomega.HaveOccurred())
335-
336-
bslName := bsls.Items[0].Name
337-
err = lib.CreateUploadTestOnlyDPT(dpaCR.Client, dpaCR.Namespace, bslName)
338-
gomega.Expect(err).ToNot(gomega.HaveOccurred())
339-
371+
//DPT Test and MustGather should be paired together
340372
log.Printf("skipMustGather: %v", skipMustGather)
341373
if !skipMustGather {
374+
log.Printf("Creating real DataProtectionTest before must-gather")
375+
bsls, err := dpaCR.ListBSLs()
376+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
377+
378+
bslName := bsls.Items[0].Name
379+
err = lib.CreateUploadTestOnlyDPT(dpaCR.Client, dpaCR.Namespace, bslName)
380+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
381+
342382
log.Printf("Running OADP must-gather")
343383
err = lib.RunMustGather(artifact_dir, dpaCR.Client)
344384
gomega.Expect(err).ToNot(gomega.HaveOccurred())
385+
} else {
386+
log.Printf("Skipping MustGather and DataProtectionTest")
345387
}
346388

347-
err = dpaCR.Delete()
389+
err := dpaCR.Delete()
348390
gomega.Expect(err).ToNot(gomega.HaveOccurred())
349391
})
350392

@@ -455,6 +497,46 @@ var _ = ginkgo.Describe("Backup and restore tests", ginkgo.Ordered, func() {
455497
BackupTimeout: 20 * time.Minute,
456498
},
457499
}, nil),
500+
ginkgo.Entry("Parks application Native-Snapshots", ginkgo.FlakeAttempts(flakeAttempts), ginkgo.Label("aws", "azure", "gcp"), ApplicationBackupRestoreCase{
501+
ApplicationTemplate: "./sample-applications/parks-app/manifest.yaml",
502+
BackupRestoreCase: BackupRestoreCase{
503+
Namespace: "parks-app",
504+
Name: "mongo-parksapp-native-snapshots-e2e",
505+
BackupRestoreType: lib.NativeSnapshots,
506+
PreBackupVerify: parksAppReady(true, false, true),
507+
PostRestoreVerify: parksAppReady(false, false, false),
508+
BackupTimeout: 20 * time.Minute,
509+
ExcludedResources: []string{"jobs.batch", "events", "events.events.k8s.io", "buildconfigs.build.openshift.io", "builds.build.openshift.io"},
510+
RestoreHooks: &velero.RestoreHooks{
511+
Resources: []velero.RestoreResourceHookSpec{
512+
{
513+
Name: "wait for app to be ready",
514+
IncludedNamespaces: []string{"parks-app"},
515+
LabelSelector: &metav1.LabelSelector{
516+
MatchLabels: map[string]string{
517+
"app": "restify",
518+
},
519+
},
520+
PostHooks: []velero.RestoreResourceHook{
521+
{
522+
Exec: &velero.ExecRestoreHook{
523+
Container: "restify",
524+
Command: []string{
525+
"/bin/sh",
526+
"-c",
527+
"sleep 10\ncurl -f http://restify:8080/status || echo \"App not ready yet\"",
528+
},
529+
ExecTimeout: metav1.Duration{Duration: 1 * time.Minute},
530+
WaitTimeout: metav1.Duration{Duration: 5 * time.Minute},
531+
OnError: velero.HookErrorModeFail,
532+
},
533+
},
534+
},
535+
},
536+
},
537+
},
538+
},
539+
}, nil),
458540
)
459541
})
460542

tests/e2e/lib/apps.go

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func InstallApplication(ocClient client.Client, file string) error {
4949

5050
func InstallApplicationWithRetries(ocClient client.Client, file string, retries int) error {
5151
template, err := os.ReadFile(file)
52+
log.Printf("Installing application with retries: %s", template)
5253
if err != nil {
5354
return err
5455
}
@@ -423,53 +424,97 @@ func RunMustGather(artifact_dir string, clusterClient client.Client) error {
423424
func VerifyBackupRestoreData(ocClient client.Client, kubeClient *kubernetes.Clientset, kubeConfig *rest.Config, artifactDir string, namespace string, routeName string, serviceName string, app string, prebackupState bool, twoVol bool) error {
424425
log.Printf("Verifying backup/restore data of %s", app)
425426
appEndpointURL, proxyPodParams, err := getAppEndpointURLAndProxyParams(ocClient, kubeClient, kubeConfig, namespace, serviceName, routeName)
427+
log.Printf("App endpoint URL: %s", appEndpointURL)
426428
if err != nil {
427429
return err
428430
}
429431

430-
// Construct request parameters for the "todo-incomplete" endpoint
431-
requestParamsTodoIncomplete := getRequestParameters(appEndpointURL+"/todo-incomplete", proxyPodParams, GET, nil)
432+
respData := ""
433+
var errResp string
432434

433435
if prebackupState {
434436
// Clean up existing backup file
435437
RemoveFileIfExists(artifactDir + "/backup-data.txt")
436438

437-
// Make requests and update data before backup
438-
dataBeforeCurl, errResp, err := MakeRequest(*requestParamsTodoIncomplete)
439-
if err != nil {
440-
if errResp != "" {
441-
log.Printf("Request response error msg: %s\n", errResp)
439+
// todolist
440+
if namespace == "mysql-persistent" || namespace == "mongo-persistent" {
441+
// Construct request parameters for the "todo-incomplete" endpoint
442+
responseParams := getRequestParameters(appEndpointURL+"/todo-incomplete", proxyPodParams, GET, nil)
443+
dataBeforeCurl, errResp, err := MakeRequest(*responseParams)
444+
if err != nil {
445+
if errResp != "" {
446+
log.Printf("Request response error msg: %s\n", errResp)
447+
}
448+
return err
449+
}
450+
log.Printf("Data before the curl request: \n %s\n", dataBeforeCurl)
451+
452+
// Make two post requests to the "todo" endpoint
453+
postPayload := `{"description": "` + time.Now().String() + `"}`
454+
requestParams := getRequestParameters(appEndpointURL+"/todo", proxyPodParams, POST, &postPayload)
455+
log.Printf("requestParams: %v\n", requestParams)
456+
MakeRequest(*requestParams)
457+
458+
postPayload = `{"description": "` + time.Now().Weekday().String() + `"}`
459+
requestParams = getRequestParameters(appEndpointURL+"/todo", proxyPodParams, POST, &postPayload)
460+
MakeRequest(*requestParams)
461+
respData, errResp, err = MakeRequest(*responseParams)
462+
if err != nil {
463+
if errResp != "" {
464+
log.Printf("Request response error msg: %s\n", errResp)
465+
}
466+
return err
442467
}
443-
return err
444468
}
445-
log.Printf("Data before the curl request: \n %s\n", dataBeforeCurl)
446-
447-
// Make two post requests to the "todo" endpoint
448-
postPayload := `{"description": "` + time.Now().String() + `"}`
449-
requestParams := getRequestParameters(appEndpointURL+"/todo", proxyPodParams, POST, &postPayload)
450-
MakeRequest(*requestParams)
451-
452-
postPayload = `{"description": "` + time.Now().Weekday().String() + `"}`
453-
requestParams = getRequestParameters(appEndpointURL+"/todo", proxyPodParams, POST, &postPayload)
454-
MakeRequest(*requestParams)
455-
}
456-
457-
// Make request to the "todo-incomplete" endpoint
458-
respData, errResp, err := MakeRequest(*requestParamsTodoIncomplete)
459-
if err != nil {
460-
if errResp != "" {
461-
log.Printf("Request response error msg: %s\n", errResp)
469+
// parks-app
470+
if namespace == "parks-app" {
471+
// POST with no body - equivalent to: curl -X POST http://restify/clicks
472+
postParams := getRequestParameters(appEndpointURL+"/clicks", proxyPodParams, POST, nil)
473+
responseParams := getRequestParameters(appEndpointURL+"/clicks", proxyPodParams, GET, nil)
474+
log.Printf("postParams: %v\n", postParams)
475+
// 2 clicks
476+
MakeRequest(*postParams)
477+
MakeRequest(*postParams)
478+
respData, errResp, err = MakeRequest(*responseParams)
479+
if err != nil {
480+
if errResp != "" {
481+
log.Printf("Request response error msg: %s\n", errResp)
482+
}
483+
return err
484+
}
462485
}
463-
return err
464-
}
465486

466-
if prebackupState {
467487
// Write data to backup file
468-
log.Printf("Writing data to backupFile (backup-data.txt): \n %s\n", respData)
488+
log.Printf("Writing data to backupFile %s /backup-data.txt: \n %s\n", artifactDir, respData)
469489
if err := os.WriteFile(artifactDir+"/backup-data.txt", []byte(respData), 0644); err != nil {
470490
return err
471491
}
472492
} else {
493+
//restore check
494+
495+
if namespace == "mysql-persistent" || namespace == "mongo-persistent" {
496+
// Make request to the "todo-incomplete" endpoint
497+
requestParamsTodoIncomplete := getRequestParameters(appEndpointURL+"/todo-incomplete", proxyPodParams, GET, nil)
498+
respData, errResp, err = MakeRequest(*requestParamsTodoIncomplete)
499+
if err != nil {
500+
if errResp != "" {
501+
log.Printf("Request response error msg: %s\n", errResp)
502+
}
503+
return err
504+
}
505+
}
506+
if namespace == "parks-app" {
507+
// Make request to the "clicks" endpoint
508+
responseParams := getRequestParameters(appEndpointURL+"/clicks", proxyPodParams, GET, nil)
509+
respData, errResp, err = MakeRequest(*responseParams)
510+
if err != nil {
511+
if errResp != "" {
512+
log.Printf("Request response error msg: %s\n", errResp)
513+
}
514+
return err
515+
}
516+
}
517+
473518
// Compare data with backup file after restore
474519
backupData, err := os.ReadFile(artifactDir + "/backup-data.txt")
475520
if err != nil {

0 commit comments

Comments
 (0)