From e5c671db527bf152eff8701faccc4dd0f99f2e16 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Robles Date: Wed, 27 Jan 2021 09:15:20 +0200 Subject: [PATCH] ocp4/e2e: Link test failure with sub-tests Currently, there is a "context" object which contains a lot of the information the tests need to run. This used to include the test framework helper instance which one would normally use to output logs or mark the test as failed. Unfortunately, this only took into account the main test helper instance, and so it wasn't entirely clear in what part of the test did the failure happen. This removes this limitation by passing in the helper instance along with every function that requires it. This way, we can pass the sub-test metadata, which will show on what sub-test did the failure happen. Note that this PR also increases the manual remediation timeout... MachineConfigs take a long time to apply unfortunately... Signed-off-by: Juan Antonio Osorio Robles --- tests/ocp4e2e/e2e_test.go | 48 +++++------ tests/ocp4e2e/helpers.go | 170 +++++++++++++++++++------------------- 2 files changed, 108 insertions(+), 110 deletions(-) diff --git a/tests/ocp4e2e/e2e_test.go b/tests/ocp4e2e/e2e_test.go index 1544f2419b99..f9637b6fbcc2 100644 --- a/tests/ocp4e2e/e2e_test.go +++ b/tests/ocp4e2e/e2e_test.go @@ -8,19 +8,19 @@ import ( func TestE2e(t *testing.T) { ctx := newE2EContext(t) t.Run("Parameter setup and validation", func(t *testing.T) { - ctx.assertRootdir() - ctx.assertProfile() - ctx.assertContentImage() - ctx.assertKubeClient() + ctx.assertRootdir(t) + ctx.assertProfile(t) + ctx.assertContentImage(t) + ctx.assertKubeClient(t) }) t.Run("Operator setup", func(t *testing.T) { - ctx.ensureNamespaceExistsAndSet() + ctx.ensureNamespaceExistsAndSet(t) if ctx.installOperator { - ctx.ensureCatalogSourceExists() - ctx.ensureOperatorGroupExists() - ctx.ensureSubscriptionExists() - ctx.waitForOperatorToBeReady() + ctx.ensureCatalogSourceExists(t) + ctx.ensureOperatorGroupExists(t) + ctx.ensureSubscriptionExists(t) + ctx.waitForOperatorToBeReady(t) } else { t.Logf("Skipping operator install as requested") } @@ -28,8 +28,8 @@ func TestE2e(t *testing.T) { }) t.Run("Prereqs setup", func(t *testing.T) { - ctx.ensureTestProfileBundle() - ctx.ensureTestSettings() + ctx.ensureTestProfileBundle(t) + ctx.ensureTestSettings(t) }) // Remediations @@ -53,32 +53,32 @@ func TestE2e(t *testing.T) { t.Run("Run first compliance scan", func(t *testing.T) { // Create suite and auto-apply remediations - suite = ctx.createBindingForProfile() - ctx.waitForComplianceSuite(suite) - numberOfRemediations = ctx.getRemediationsForSuite(suite) - numberOfFailuresInit = ctx.getFailuresForSuite(suite) - numberOfCheckResultsInit, manualRemediations = ctx.verifyCheckResultsForSuite(suite, false) - numberOfInvalidResults = ctx.getInvalidResultsFromSuite(suite) + suite = ctx.createBindingForProfile(t) + ctx.waitForComplianceSuite(t, suite) + numberOfRemediations = ctx.getRemediationsForSuite(t, suite) + numberOfFailuresInit = ctx.getFailuresForSuite(t, suite) + numberOfCheckResultsInit, manualRemediations = ctx.verifyCheckResultsForSuite(t, suite, false) + numberOfInvalidResults = ctx.getInvalidResultsFromSuite(t, suite) }) if numberOfRemediations > 0 || len(manualRemediations) > 0 { if len(manualRemediations) > 0 { t.Run("Apply manual remediations", func(t *testing.T) { - ctx.applyManualRemediations(manualRemediations) + ctx.applyManualRemediations(t, manualRemediations) }) } t.Run("Wait for Remediations to apply", func(t *testing.T) { // Lets wait for the MachineConfigs to start applying time.Sleep(30 * time.Second) - ctx.waitForMachinePoolUpdate("master") - ctx.waitForMachinePoolUpdate("worker") + ctx.waitForMachinePoolUpdate(t, "master") + ctx.waitForMachinePoolUpdate(t, "worker") }) t.Run("Run second compliance scan", func(t *testing.T) { - ctx.doRescan(suite) - ctx.waitForComplianceSuite(suite) - numberOfFailuresEnd = ctx.getFailuresForSuite(suite) - numberOfCheckResultsEnd, _ = ctx.verifyCheckResultsForSuite(suite, true) + ctx.doRescan(t, suite) + ctx.waitForComplianceSuite(t, suite) + numberOfFailuresEnd = ctx.getFailuresForSuite(t, suite) + numberOfCheckResultsEnd, _ = ctx.verifyCheckResultsForSuite(t, suite, true) }) t.Run("We should have the same number of check results in each scan", func(t *testing.T) { diff --git a/tests/ocp4e2e/helpers.go b/tests/ocp4e2e/helpers.go index 3243b512c1e5..ad9b65241fb2 100644 --- a/tests/ocp4e2e/helpers.go +++ b/tests/ocp4e2e/helpers.go @@ -52,7 +52,7 @@ const ( apiPollInterval = 5 * time.Second testProfilebundleName = "e2e" autoApplySettingsName = "auto-apply-debug" - manualRemediationsTimeout = 20 * time.Minute + manualRemediationsTimeout = 30 * time.Minute ) // RuleTest is the definition of the structure rule-specific e2e tests should have @@ -84,7 +84,6 @@ type e2econtext struct { installOperator bool dynclient dynclient.Client restMapper *restmapper.DeferredDiscoveryRESTMapper - t *testing.T } func init() { @@ -120,7 +119,6 @@ func newE2EContext(t *testing.T) *e2econtext { benchmarkRoot: benchmarkRoot, product: product, installOperator: installOperator, - t: t, } } @@ -141,64 +139,64 @@ func getBenchmarkRootFromProductSpec(productpath string) (string, error) { return path.Join(productpath, benchmarkRelative.Path), nil } -func (ctx *e2econtext) assertRootdir() { +func (ctx *e2econtext) assertRootdir(t *testing.T) { dirinfo, err := os.Stat(ctx.rootdir) if os.IsNotExist(err) { - ctx.t.Fatal("$ROOT_DIR points to an unexistent directory") + t.Fatal("$ROOT_DIR points to an unexistent directory") } if err != nil { - ctx.t.Fatal(err) + t.Fatal(err) } if !dirinfo.IsDir() { - ctx.t.Fatal("$ROOT_DIR must be a directory") + t.Fatal("$ROOT_DIR must be a directory") } } -func (ctx *e2econtext) assertProfile() { +func (ctx *e2econtext) assertProfile(t *testing.T) { if ctx.Profile == "" { - ctx.t.Fatal("a profile must be given with the `-profile` flag") + t.Fatal("a profile must be given with the `-profile` flag") } _, err := os.Stat(ctx.profilepath) if os.IsNotExist(err) { - ctx.t.Fatalf("The profile path %s points to an unexistent file", ctx.profilepath) + t.Fatalf("The profile path %s points to an unexistent file", ctx.profilepath) } if err != nil { - ctx.t.Fatal(err) + t.Fatal(err) } } -func (ctx *e2econtext) assertContentImage() { +func (ctx *e2econtext) assertContentImage(t *testing.T) { if ctx.ContentImage == "" { - ctx.t.Fatal("A content image must be provided with the `-content-image` flag") + t.Fatal("A content image must be provided with the `-content-image` flag") } } -func (ctx *e2econtext) assertKubeClient() { +func (ctx *e2econtext) assertKubeClient(t *testing.T) { // Get a config to talk to the apiserver cfg, err := config.GetConfig() if err != nil { - ctx.t.Fatal(err) + t.Fatal(err) } // create the kubeclient (temporarily) kubeclient, err := kubernetes.NewForConfig(cfg) if err != nil { - ctx.t.Fatal(err.Error()) + t.Fatal(err.Error()) } // create dynamic client scheme := runtime.NewScheme() if err := cgoscheme.AddToScheme(scheme); err != nil { - ctx.t.Fatalf("failed to add cgo scheme to runtime scheme: %s", err) + t.Fatalf("failed to add cgo scheme to runtime scheme: %s", err) } if err := extscheme.AddToScheme(scheme); err != nil { - ctx.t.Fatalf("failed to add api extensions scheme to runtime scheme: %s", err) + t.Fatalf("failed to add api extensions scheme to runtime scheme: %s", err) } if err := cmpapis.AddToScheme(scheme); err != nil { - ctx.t.Fatalf("failed to add cmpliance scheme to runtime scheme: %s", err) + t.Fatalf("failed to add cmpliance scheme to runtime scheme: %s", err) } if err := mcfg.Install(scheme); err != nil { - ctx.t.Fatalf("failed to add MachineConfig scheme to runtime scheme: %s", err) + t.Fatalf("failed to add MachineConfig scheme to runtime scheme: %s", err) } cachedDiscoveryClient := cached.NewMemCacheClient(kubeclient.Discovery()) @@ -207,7 +205,7 @@ func (ctx *e2econtext) assertKubeClient() { ctx.dynclient, err = dynclient.New(cfg, dynclient.Options{Scheme: scheme, Mapper: ctx.restMapper}) if err != nil { - ctx.t.Fatalf("failed to build the dynamic client: %s", err) + t.Fatalf("failed to build the dynamic client: %s", err) } } @@ -217,28 +215,28 @@ func (ctx *e2econtext) resetClientMappings() { // Makes sure that the namespace where the test will run exists. Doesn't fail // if it already does. -func (ctx *e2econtext) ensureNamespaceExistsAndSet() { +func (ctx *e2econtext) ensureNamespaceExistsAndSet(t *testing.T) { path := path.Join(ctx.resourcespath, namespacePath) - obj := ctx.ensureObjectExists(path) + obj := ctx.ensureObjectExists(t, path) // Ensures that we don't depend on a specific namespace in the code, // but we can instead change the namespace depending on the resource // file ctx.OperatorNamespacedName.Namespace = obj.GetName() } -func (ctx *e2econtext) ensureCatalogSourceExists() { +func (ctx *e2econtext) ensureCatalogSourceExists(t *testing.T) { path := path.Join(ctx.resourcespath, catalogSourcePath) - ctx.ensureObjectExists(path) + ctx.ensureObjectExists(t, path) } -func (ctx *e2econtext) ensureOperatorGroupExists() { +func (ctx *e2econtext) ensureOperatorGroupExists(t *testing.T) { path := path.Join(ctx.resourcespath, operatorGroupPath) - ctx.ensureObjectExists(path) + ctx.ensureObjectExists(t, path) } -func (ctx *e2econtext) ensureSubscriptionExists() { +func (ctx *e2econtext) ensureSubscriptionExists(t *testing.T) { path := path.Join(ctx.resourcespath, subscriptionPath) - ctx.ensureObjectExists(path) + ctx.ensureObjectExists(t, path) } // Makes sure that an object from the given file path exists in the cluster. @@ -246,29 +244,29 @@ func (ctx *e2econtext) ensureSubscriptionExists() { // Note that this assumes that the object's manifest already contains // the Namespace reference. // If all went well, this will return the reference to the object that was created. -func (ctx *e2econtext) ensureObjectExists(path string) *unstructured.Unstructured { +func (ctx *e2econtext) ensureObjectExists(t *testing.T, path string) *unstructured.Unstructured { obj, err := readObjFromYAMLFilePath(path) if err != nil { - ctx.t.Fatalf("failed to decode object from '%s' spec: %s", path, err) + t.Fatalf("failed to decode object from '%s' spec: %s", path, err) } err = ctx.dynclient.Create(goctx.TODO(), obj) if err != nil && !apierrors.IsAlreadyExists(err) { - ctx.t.Fatalf("failed to create object from '%s': %s", path, err) + t.Fatalf("failed to create object from '%s': %s", path, err) } return obj } -func (ctx *e2econtext) waitForOperatorToBeReady() { +func (ctx *e2econtext) waitForOperatorToBeReady(t *testing.T) { bo := backoff.WithMaxRetries(backoff.NewConstantBackOff(apiPollInterval), 30) retryFunc := func() error { od := &appsv1.Deployment{} err := ctx.dynclient.Get(goctx.TODO(), ctx.OperatorNamespacedName, od) if err != nil { - return err + return fmt.Errorf("getting deployment: %w", err) } if len(od.Status.Conditions) == 0 { return fmt.Errorf("No conditions for deployment yet") @@ -286,11 +284,11 @@ func (ctx *e2econtext) waitForOperatorToBeReady() { err := backoff.RetryNotify(retryFunc, bo, notifyFunc) if err != nil { - ctx.t.Fatalf("Operator deployment was never created: %s", err) + t.Fatalf("Operator deployment was never created: %s", err) } } -func (ctx *e2econtext) ensureTestProfileBundle() { +func (ctx *e2econtext) ensureTestProfileBundle(t *testing.T) { key := types.NamespacedName{ Name: testProfilebundleName, Namespace: ctx.OperatorNamespacedName.Namespace, @@ -322,11 +320,11 @@ func (ctx *e2econtext) ensureTestProfileBundle() { fmt.Printf("Couldn't ensure test PB exists after %s: %s\n", d.String(), err) }) if err != nil { - ctx.t.Fatalf("failed to ensure test PB: %s", err) + t.Fatalf("failed to ensure test PB: %s", err) } } -func (ctx *e2econtext) ensureTestSettings() { +func (ctx *e2econtext) ensureTestSettings(t *testing.T) { defaultkey := types.NamespacedName{ Name: "default", Namespace: ctx.OperatorNamespacedName.Namespace, @@ -341,7 +339,7 @@ func (ctx *e2econtext) ensureTestSettings() { fmt.Printf("Couldn't get default scanSettings after %s: %s\n", d.String(), err) }) if err != nil { - ctx.t.Fatalf("failed to get default scanSettings: %s", err) + t.Fatalf("failed to get default scanSettings: %s", err) } // Ensure auto-apply @@ -372,7 +370,7 @@ func (ctx *e2econtext) ensureTestSettings() { fmt.Printf("Couldn't ensure auto-apply scansettings after %s: %s\n", d.String(), err) }) if err != nil { - ctx.t.Fatalf("failed to ensure auto-apply scanSettings: %s", err) + t.Fatalf("failed to ensure auto-apply scanSettings: %s", err) } } @@ -380,7 +378,7 @@ func (ctx *e2econtext) getPrefixedProfileName() string { return testProfilebundleName + "-" + ctx.Profile } -func (ctx *e2econtext) createBindingForProfile() string { +func (ctx *e2econtext) createBindingForProfile(t *testing.T) string { binding := &cmpv1alpha1.ScanSettingBinding{ ObjectMeta: metav1.ObjectMeta{ Name: ctx.getPrefixedProfileName(), @@ -407,12 +405,12 @@ func (ctx *e2econtext) createBindingForProfile() string { fmt.Printf("Couldn't create binding after %s: %s\n", d.String(), err) }) if err != nil { - ctx.t.Fatalf("failed to create binding: %s", err) + t.Fatalf("failed to create binding: %s", err) } return binding.Name } -func (ctx *e2econtext) waitForComplianceSuite(suiteName string) { +func (ctx *e2econtext) waitForComplianceSuite(t *testing.T, suiteName string) { key := types.NamespacedName{Name: suiteName, Namespace: ctx.OperatorNamespacedName.Namespace} // aprox. 15 min bo := backoff.WithMaxRetries(backoff.NewConstantBackOff(apiPollInterval), 180) @@ -434,18 +432,18 @@ func (ctx *e2econtext) waitForComplianceSuite(suiteName string) { } if scanstatus.Result == cmpv1alpha1.ResultError { // If there was an error, we can stop already. - ctx.t.Fatalf("There was an unexpected error in the scan '%s': %s", + t.Fatalf("There was an unexpected error in the scan '%s': %s", scanstatus.Name, scanstatus.ErrorMessage) } } return nil }, bo) if err != nil { - ctx.t.Fatalf("The Compliance Suite '%s' didn't get to DONE phase: %s", key.Name, err) + t.Fatalf("The Compliance Suite '%s' didn't get to DONE phase: %s", key.Name, err) } } -func (ctx *e2econtext) waitForMachinePoolUpdate(name string) error { +func (ctx *e2econtext) waitForMachinePoolUpdate(t *testing.T, name string) error { mcKey := types.NamespacedName{Name: name} var lastErr error @@ -453,18 +451,18 @@ func (ctx *e2econtext) waitForMachinePoolUpdate(name string) error { pool := &mcfgv1.MachineConfigPool{} lastErr = ctx.dynclient.Get(goctx.TODO(), mcKey, pool) if lastErr != nil { - ctx.t.Logf("Could not get the pool %s post update. Retrying.", name) + t.Logf("Could not get the pool %s post update. Retrying.", name) return false, nil } // Check if the pool has finished updating yet. if (pool.Status.UpdatedMachineCount == pool.Status.MachineCount) && (pool.Status.UnavailableMachineCount == 0) { - ctx.t.Logf("The pool %s has updated", name) + t.Logf("The pool %s has updated", name) return true, nil } - ctx.t.Logf("The pool %s has not updated yet. updated %d/%d unavailable %d", + t.Logf("The pool %s has not updated yet. updated %d/%d unavailable %d", name, pool.Status.UpdatedMachineCount, pool.Status.MachineCount, pool.Status.UnavailableMachineCount) @@ -484,7 +482,7 @@ func (ctx *e2econtext) waitForMachinePoolUpdate(name string) error { return nil } -func (ctx *e2econtext) doRescan(s string) { +func (ctx *e2econtext) doRescan(t *testing.T, s string) { scanList := &cmpv1alpha1.ComplianceScanList{} labelSelector, _ := labels.Parse(cmpv1alpha1.SuiteLabel + "=" + s) opts := &client.ListOptions{ @@ -492,10 +490,10 @@ func (ctx *e2econtext) doRescan(s string) { } err := ctx.dynclient.List(goctx.TODO(), scanList, opts) if err != nil { - ctx.t.Fatalf("Couldn't get scan list") + t.Fatalf("Couldn't get scan list") } if len(scanList.Items) == 0 { - ctx.t.Fatal("This suite didn't contain scans") + t.Fatal("This suite didn't contain scans") } for _, scan := range scanList.Items { updatedScan := scan.DeepCopy() @@ -513,7 +511,7 @@ func (ctx *e2econtext) doRescan(s string) { fmt.Printf("Couldn't rescan after %s: %s\n", d.String(), err) }) if err != nil { - ctx.t.Fatalf("failed rescan: %s", err) + t.Fatalf("failed rescan: %s", err) } } var lastErr error @@ -533,16 +531,16 @@ func (ctx *e2econtext) doRescan(s string) { // timeout error if err != nil { - ctx.t.Fatalf("Timed out waiting for scan to be reset: %s", err) + t.Fatalf("Timed out waiting for scan to be reset: %s", err) } // An actual error at the end of the run if lastErr != nil { - ctx.t.Fatalf("Error occured while waiting for scan to be reset: %s", lastErr) + t.Fatalf("Error occured while waiting for scan to be reset: %s", lastErr) } } -func (ctx *e2econtext) getRemediationsForSuite(s string) int { +func (ctx *e2econtext) getRemediationsForSuite(t *testing.T, s string) int { remList := &cmpv1alpha1.ComplianceRemediationList{} labelSelector, _ := labels.Parse(cmpv1alpha1.SuiteLabel + "=" + s) opts := &client.ListOptions{ @@ -550,20 +548,20 @@ func (ctx *e2econtext) getRemediationsForSuite(s string) int { } err := ctx.dynclient.List(goctx.TODO(), remList, opts) if err != nil { - ctx.t.Fatalf("Couldn't get remediation list") + t.Fatalf("Couldn't get remediation list") } if len(remList.Items) > 0 { - ctx.t.Logf("Remediations from ComplianceSuite: %s", s) + t.Logf("Remediations from ComplianceSuite: %s", s) } else { - ctx.t.Log("This suite didn't generate remediations") + t.Log("This suite didn't generate remediations") } for _, rem := range remList.Items { - ctx.t.Logf("- %s", rem.Name) + t.Logf("- %s", rem.Name) } return len(remList.Items) } -func (ctx *e2econtext) getFailuresForSuite(s string) int { +func (ctx *e2econtext) getFailuresForSuite(t *testing.T, s string) int { failList := &cmpv1alpha1.ComplianceCheckResultList{} matchLabels := dynclient.MatchingLabels{ cmpv1alpha1.SuiteLabel: s, @@ -571,19 +569,19 @@ func (ctx *e2econtext) getFailuresForSuite(s string) int { } err := ctx.dynclient.List(goctx.TODO(), failList, matchLabels) if err != nil { - ctx.t.Fatalf("Couldn't get check result list") + t.Fatalf("Couldn't get check result list") } if len(failList.Items) > 0 { - ctx.t.Logf("Failures from ComplianceSuite: %s", s) + t.Logf("Failures from ComplianceSuite: %s", s) } for _, rem := range failList.Items { - ctx.t.Logf("- %s", rem.Name) + t.Logf("- %s", rem.Name) } return len(failList.Items) } // This returns the number of results that are either CheckResultError or CheckResultNoResult -func (ctx *e2econtext) getInvalidResultsFromSuite(s string) int { +func (ctx *e2econtext) getInvalidResultsFromSuite(t *testing.T, s string) int { ret := 0 errList := &cmpv1alpha1.ComplianceCheckResultList{} matchLabels := dynclient.MatchingLabels{ @@ -592,13 +590,13 @@ func (ctx *e2econtext) getInvalidResultsFromSuite(s string) int { } err := ctx.dynclient.List(goctx.TODO(), errList, matchLabels) if err != nil { - ctx.t.Fatalf("Couldn't get result list") + t.Fatalf("Couldn't get result list") } if len(errList.Items) > 0 { - ctx.t.Logf("Errors from ComplianceSuite: %s", s) + t.Logf("Errors from ComplianceSuite: %s", s) } for _, check := range errList.Items { - ctx.t.Logf("unexpected Error result - %s", check.Name) + t.Logf("unexpected Error result - %s", check.Name) } ret = len(errList.Items) @@ -609,19 +607,19 @@ func (ctx *e2econtext) getInvalidResultsFromSuite(s string) int { } err = ctx.dynclient.List(goctx.TODO(), noneList, matchLabels) if err != nil { - ctx.t.Fatalf("Couldn't get result list") + t.Fatalf("Couldn't get result list") } if len(noneList.Items) > 0 { - ctx.t.Logf("None result from ComplianceSuite: %s", s) + t.Logf("None result from ComplianceSuite: %s", s) } for _, check := range noneList.Items { - ctx.t.Logf("unexpected None result - %s", check.Name) + t.Logf("unexpected None result - %s", check.Name) } return ret + len(noneList.Items) } -func (ctx *e2econtext) verifyCheckResultsForSuite(s string, afterRemediations bool) (int, []string) { +func (ctx *e2econtext) verifyCheckResultsForSuite(t *testing.T, s string, afterRemediations bool) (int, []string) { manualRemediationSet := map[string]bool{} resList := &cmpv1alpha1.ComplianceCheckResultList{} matchLabels := dynclient.MatchingLabels{ @@ -629,18 +627,18 @@ func (ctx *e2econtext) verifyCheckResultsForSuite(s string, afterRemediations bo } err := ctx.dynclient.List(goctx.TODO(), resList, matchLabels) if err != nil { - ctx.t.Fatalf("Couldn't get result list") + t.Fatalf("Couldn't get result list") } if len(resList.Items) > 0 { - ctx.t.Logf("Results from ComplianceSuite: %s", s) + t.Logf("Results from ComplianceSuite: %s", s) } else { - ctx.t.Logf("There were no results for the ComplianceSuite: %s", s) + t.Logf("There were no results for the ComplianceSuite: %s", s) } for _, check := range resList.Items { - ctx.t.Logf("Result - Name: %s - Status: %s - Severity: %s", check.Name, check.Status, check.Severity) - manualRem, err := ctx.verifyRule(check, afterRemediations) + t.Logf("Result - Name: %s - Status: %s - Severity: %s", check.Name, check.Status, check.Severity) + manualRem, err := ctx.verifyRule(t, check, afterRemediations) if err != nil { - ctx.t.Error(err) + t.Error(err) } if manualRem != "" { manualRemediationSet[manualRem] = true @@ -655,7 +653,7 @@ func (ctx *e2econtext) verifyCheckResultsForSuite(s string, afterRemediations bo return len(resList.Items), manualRemediations } -func (ctx *e2econtext) verifyRule(result cmpv1alpha1.ComplianceCheckResult, afterRemediations bool) (string, error) { +func (ctx *e2econtext) verifyRule(t *testing.T, result cmpv1alpha1.ComplianceCheckResult, afterRemediations bool) (string, error) { ruleName, err := ctx.getRuleFolderNameFromResult(result) if err != nil { return "", err @@ -708,7 +706,7 @@ func (ctx *e2econtext) verifyRule(result cmpv1alpha1.ComplianceCheckResult, afte } } - ctx.t.Logf("Rule %s matched expected result", ruleName) + t.Logf("Rule %s matched expected result", ruleName) return remPath, nil } @@ -768,34 +766,34 @@ func (ctx *e2econtext) getRuleFolderNameFromResult(result cmpv1alpha1.Compliance return strings.ReplaceAll(prefixRemoved, "-", "_"), nil } -func (ctx *e2econtext) applyManualRemediations(rems []string) { +func (ctx *e2econtext) applyManualRemediations(t *testing.T, rems []string) { var wg sync.WaitGroup cmdctx, cancel := context.WithTimeout(context.Background(), manualRemediationsTimeout) defer cancel() for _, rem := range rems { wg.Add(1) - go ctx.runManualRemediation(cmdctx, &wg, rem) + go ctx.runManualRemediation(t, cmdctx, &wg, rem) } wg.Wait() } -func (ctx *e2econtext) runManualRemediation(cmdctx goctx.Context, wg *sync.WaitGroup, rem string) { +func (ctx *e2econtext) runManualRemediation(t *testing.T, cmdctx goctx.Context, wg *sync.WaitGroup, rem string) { defer wg.Done() - ctx.t.Logf("Running manual remediation '%s'", rem) + t.Logf("Running manual remediation '%s'", rem) cmd := exec.CommandContext(cmdctx, rem) cmd.Env = os.Environ() out, err := cmd.CombinedOutput() if cmdctx.Err() == context.DeadlineExceeded { - ctx.t.Errorf("Command '%s' timed out", rem) + t.Errorf("Command '%s' timed out", rem) return } if err != nil { - ctx.t.Errorf("Failed applying remediation '%s': %s\n%s", rem, err, out) + t.Errorf("Failed applying remediation '%s': %s\n%s", rem, err, out) } }