Skip to content

Commit

Permalink
Port TestVariableTemplate to serial test package
Browse files Browse the repository at this point in the history
  • Loading branch information
rhmdnd committed Apr 13, 2023
1 parent da8af77 commit 59e0de8
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 228 deletions.
150 changes: 0 additions & 150 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

compv1alpha1 "github.com/ComplianceAsCode/compliance-operator/pkg/apis/compliance/v1alpha1"
configv1 "github.com/openshift/api/config/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

Expand Down Expand Up @@ -70,155 +69,6 @@ func TestE2E(t *testing.T) {
// return removeNodeTaint(t, f, taintedNode.Name, taintKey)
// },
//},
testExecution{
Name: "TestVariableTemplate",
IsParallel: false,
TestFn: func(t *testing.T, f *framework.Framework, ctx *framework.Context, namespace string) error {

var baselineImage = fmt.Sprintf("%s:%s", brokenContentImagePath, "variabletemplate")
const requiredRule = "audit-profile-set"
pbName := getObjNameFromTest(t)
prefixName := func(profName, ruleBaseName string) string { return profName + "-" + ruleBaseName }

ocpPb := &compv1alpha1.ProfileBundle{
ObjectMeta: metav1.ObjectMeta{
Name: pbName,
Namespace: namespace,
},
Spec: compv1alpha1.ProfileBundleSpec{
ContentImage: baselineImage,
ContentFile: ocpContentFile,
},
}
if err := f.Client.Create(goctx.TODO(), ocpPb, getCleanupOpts(ctx)); err != nil {
return err
}
if err := waitForProfileBundleStatus(t, f, namespace, pbName, compv1alpha1.DataStreamValid); err != nil {
return err
}

// Check that if the rule we are going to test is there
err, found := doesRuleExist(f, ocpPb.Namespace, prefixName(pbName, requiredRule))
if err != nil {
return err
} else if found != true {
E2EErrorf(t, "Expected rule %s not found", prefixName(pbName, requiredRule))
return err
}

suiteName := "audit-profile-set-test"
scanName := "audit-profile-set-test"

tp := &compv1alpha1.TailoredProfile{
ObjectMeta: metav1.ObjectMeta{
Name: suiteName,
Namespace: namespace,
},
Spec: compv1alpha1.TailoredProfileSpec{
Title: "Audit-Profile-Set-Test",
Description: "A test tailored profile to auto remediate audit profile set",
EnableRules: []compv1alpha1.RuleReferenceSpec{
{
Name: prefixName(pbName, requiredRule),
Rationale: "To be tested",
},
},
SetValues: []compv1alpha1.VariableValueSpec{
{
Name: prefixName(pbName, "var-openshift-audit-profile"),
Rationale: "Value to be set",
Value: "WriteRequestBodies",
},
},
},
}

createTPErr := f.Client.Create(goctx.TODO(), tp, getCleanupOpts(ctx))
if createTPErr != nil {
return createTPErr
}

ssb := &compv1alpha1.ScanSettingBinding{
ObjectMeta: metav1.ObjectMeta{
Name: suiteName,
Namespace: namespace,
},
Profiles: []compv1alpha1.NamedObjectReference{
{
APIGroup: "compliance.openshift.io/v1alpha1",
Kind: "TailoredProfile",
Name: suiteName,
},
},
SettingsRef: &compv1alpha1.NamedObjectReference{
APIGroup: "compliance.openshift.io/v1alpha1",
Kind: "ScanSetting",
Name: "default-auto-apply",
},
}
err = f.Client.Create(goctx.TODO(), ssb, getCleanupOpts(ctx))
if err != nil {
return err
}

apiServerBeforeRemediation := &configv1.APIServer{}
err = f.Client.Get(goctx.TODO(), types.NamespacedName{Name: "cluster"}, apiServerBeforeRemediation)
if err != nil {
return err
}

// Ensure that all the scans in the suite have finished and are marked as Done
err = waitForSuiteScansStatus(t, f, namespace, suiteName, compv1alpha1.PhaseDone, compv1alpha1.ResultNonCompliant)
if err != nil {
return err
}

// We need to check that the remediation is auto-applied
remName := "audit-profile-set-test-audit-profile-set"
waitForGenericRemediationToBeAutoApplied(t, f, remName, namespace)

// We can re-run the scan at this moment and check that it's now compliant
// and it's reflected in a CheckResult
err = reRunScan(t, f, scanName, namespace)
if err != nil {
return err
}

// Scan has been re-started
E2ELogf(t, "Scan phase should be reset")
err = waitForSuiteScansStatus(t, f, namespace, suiteName, compv1alpha1.PhaseRunning, compv1alpha1.ResultNotAvailable)
if err != nil {
return err
}

// Ensure that all the scans in the suite have finished and are marked as Done
E2ELogf(t, "Let's wait for it to be done now")
err = waitForSuiteScansStatus(t, f, namespace, suiteName, compv1alpha1.PhaseDone, compv1alpha1.ResultCompliant)
if err != nil {
return err
}
E2ELogf(t, "scan re-run has finished")

// Now the check should be passing
auditProfileSet := compv1alpha1.ComplianceCheckResult{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-audit-profile-set", scanName),
Namespace: namespace,
},
ID: "xccdf_org.ssgproject.content_rule_audit_profile_set",
Status: compv1alpha1.CheckResultPass,
Severity: compv1alpha1.CheckResultSeverityMedium,
}
err = assertHasCheck(f, suiteName, scanName, auditProfileSet)
if err != nil {
return err
}

E2ELogf(t, "The test succeeded!")
return nil

},
},
testExecution{
Name: "TestKubeletConfigRemediation",
IsParallel: false,
Expand Down
35 changes: 35 additions & 0 deletions tests/e2e/framework/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2176,3 +2176,38 @@ func (f *Framework) RemoveObsoleteRemediationAndCheck(namespace, name, renderedM
fmt.Printf("machines updated with remediation that is no longer obsolete")
return nil
}

func (f *Framework) WaitForGenericRemediationToBeAutoApplied(remName, remNamespace string) error {
rem := &compv1alpha1.ComplianceRemediation{}
var lastErr error
timeouterr := wait.Poll(RetryInterval, Timeout, func() (bool, error) {
lastErr = f.Client.Get(context.TODO(), types.NamespacedName{Name: remName, Namespace: remNamespace}, rem)
if apierrors.IsNotFound(lastErr) {
log.Printf("waiting for availability of %s remediation\n", remName)
return false, nil
}
if lastErr != nil {
log.Printf("retrying. Got error: %v\n", lastErr)
return false, nil
}
log.Printf("found remediation: %s\n", remName)
if rem.Status.ApplicationState == compv1alpha1.RemediationNotApplied || rem.Status.ApplicationState == compv1alpha1.RemediationPending {
log.Printf("retrying. remediation not yet applied. Remediation Name: %s, ApplicationState: %s\n", remName, rem.Status.ApplicationState)
}
// wait for the remediation to get applied
time.Sleep(5 * time.Second)
return true, nil
})
if lastErr != nil {
return fmt.Errorf("failed getting remediation before it was applied: %s", lastErr)
}
if timeouterr != nil {
return fmt.Errorf("timed out waiting for remediation to be applied: %s", timeouterr)
}
log.Printf("machines updated with remediation")
err := f.WaitForNodesToBeReady()
if err != nil {
return err
}
return nil
}
78 changes: 0 additions & 78 deletions tests/e2e/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ import (
"io"
"os"
"path"
"regexp"
"strings"
"testing"
"time"

backoff "github.com/cenkalti/backoff/v4"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -87,27 +83,6 @@ func E2EFatalf(t *testing.T, format string, args ...interface{}) {
t.Fatalf(fmt.Sprintf("E2E-FAILURE: %s: %s", time.Now().Format(time.RFC3339), format), args...)
}

func getObjNameFromTest(t *testing.T) string {
fullTestName := t.Name()
regexForCapitals := regexp.MustCompile(`[A-Z]`)

testNameInitIndex := strings.LastIndex(fullTestName, "/") + 1

// Remove test prefix
testName := fullTestName[testNameInitIndex:]

// convert capitals to lower case letters with hyphens prepended
hyphenedTestName := regexForCapitals.ReplaceAllStringFunc(
testName,
func(currentMatch string) string {
return "-" + strings.ToLower(currentMatch)
})
// remove double hyphens
testNameNoDoubleHyphens := strings.ReplaceAll(hyphenedTestName, "--", "-")
// Remove leading and trailing hyphens
return strings.Trim(testNameNoDoubleHyphens, "-")
}

// executeTest sets up everything that a e2e test needs to run, and executes the test.
func executeTests(t *testing.T, tests ...testExecution) {
// get global framework variables
Expand Down Expand Up @@ -167,36 +142,6 @@ func getCleanupOpts(ctx *framework.Context) *framework.CleanupOptions {
}
}

// waitForProfileBundleStatus will poll until the compliancescan that we're lookingfor reaches a certain status, or until
// a timeout is reached.
func waitForProfileBundleStatus(t *testing.T, f *framework.Framework, namespace, name string, targetStatus compv1alpha1.DataStreamStatusType) error {
pb := &compv1alpha1.ProfileBundle{}
var lastErr error
// retry and ignore errors until timeout
timeouterr := wait.Poll(retryInterval, timeout, func() (bool, error) {
lastErr = f.Client.Get(goctx.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, pb)
if lastErr != nil {
if apierrors.IsNotFound(lastErr) {
E2ELogf(t, "Waiting for availability of %s ProfileBundle\n", name)
return false, nil
}
E2ELogf(t, "Retrying. Got error: %v\n", lastErr)
return false, nil
}

if pb.Status.DataStreamStatus == targetStatus {
return true, nil
}
E2ELogf(t, "Waiting for run of %s ProfileBundle (%s)\n", name, pb.Status.DataStreamStatus)
return false, nil
})
if err := processErrorOrTimeout(lastErr, timeouterr, "waiting for ProfileBundle status"); err != nil {
return err
}
E2ELogf(t, "ProfileBundle ready (%s)\n", pb.Status.DataStreamStatus)
return nil
}

// waitForScanStatus will poll until the compliancescan that we're lookingfor reaches a certain status, or until
// a timeout is reached.
func waitForScanStatus(t *testing.T, f *framework.Framework, namespace, name string, targetStatus compv1alpha1.ComplianceScanStatusPhase) {
Expand Down Expand Up @@ -418,29 +363,6 @@ func IsMachineConfigPoolConditionPresentAndEqual(conditions []mcfgv1.MachineConf
return false
}

func doesRuleExist(f *framework.Framework, namespace, ruleName string) (error, bool) {
return doesObjectExist(f, "Rule", namespace, ruleName)
}

func doesObjectExist(f *framework.Framework, kind, namespace, name string) (error, bool) {
obj := unstructured.Unstructured{}
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: compv1alpha1.SchemeGroupVersion.Group,
Version: compv1alpha1.SchemeGroupVersion.Version,
Kind: kind,
})

key := types.NamespacedName{Namespace: namespace, Name: name}
err := f.Client.Get(goctx.TODO(), key, &obj)
if apierrors.IsNotFound(err) {
return nil, false
} else if err == nil {
return nil, true
}

return err, false
}

func writeToArtifactsDir(dir, scan, pod, container, log string) error {
logPath := path.Join(dir, fmt.Sprintf("%s_%s_%s.log", scan, pod, container))
logFile, err := os.Create(logPath)
Expand Down
Loading

0 comments on commit 59e0de8

Please sign in to comment.