Skip to content

Commit c705e25

Browse files
committed
CMP-3613: Gracefully handle profile deprecation checks
Previously, when the operator checked if a profile was deprecated, it would fail if it couldn't reliably detect the profile bundle used for the profile. This is because the profile bundle contained the profiles, which carries the deprecation flag. If the operator doesn't know which profile bundle a profile came from, it can't guarantee it knows if the profile is supported or not. This is mostly fine when users are scanning their environments using ScanSettingBindings, which rely on existing Profile and ProfileBundle resources. But, if a user is creating a ComplianceSuite or ComplianceScan directly, they get to set the content and content image for the scan, which usually comes from the profile and profile bundle. If a user specifies a content image pointing to their own content (or even in our testing cases, where we point to content images built for each pull request), that is going to mismatch with the default profile bundles, meaning they can't create a ComplianceScan directly to hook in their own content anymore because the deprecation logic will always error out looking for a profile bundle that it assumes must exist. This commit relaxes that requirement, but maintains the default behavior so that users relying on ScanSettingBindings still get deprecation notices when they should, and allows power users the ability to set their own content images directly without breaking the workflow on the deprecation check.
1 parent cfcd702 commit c705e25

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

pkg/controller/compliancescan/compliancescan_controller.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,12 @@ func (r *ReconcileComplianceScan) notifyUseOfDeprecatedProfile(instance *compv1a
329329
}
330330
}
331331
if pbName == "" {
332-
err := goerrors.New("Could not find ProfileBundle used by scan")
333-
logger.Error(err, "ComplianceScan uses non-existent ProfileBundle", "ComplianceScan", instance.Name, "Profile", instance.Spec.Profile)
334-
return err
332+
logger.Info("Could not find ProfileBundle used by scan to check if the Profile is deprecated",
333+
"ComplianceScan", instance.Name,
334+
"Profile", instance.Spec.Profile,
335+
"ContentImage", instance.Spec.ContentImage,
336+
"Content", instance.Spec.Content)
337+
return nil
335338
}
336339

337340
xccdfProfileName := xccdf.GetProfileNameFromID(instance.Spec.Profile)

tests/e2e/parallel/main_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,3 +3404,59 @@ func TestScanCleansUpComplianceCheckResults(t *testing.T) {
34043404
t.Fatal(err)
34053405
}
34063406
}
3407+
3408+
func TestComplianceScanWithMissingProfileBundleGracefullyHandlesDeprecationCheck(t *testing.T) {
3409+
t.Parallel()
3410+
f := framework.Global
3411+
3412+
scanName := framework.GetObjNameFromTest(t)
3413+
testScan := &compv1alpha1.ComplianceScan{
3414+
ObjectMeta: metav1.ObjectMeta{
3415+
Name: scanName,
3416+
Namespace: f.OperatorNamespace,
3417+
},
3418+
Spec: compv1alpha1.ComplianceScanSpec{
3419+
Profile: "xccdf_org.ssgproject.content_profile_moderate",
3420+
// Make the ProfileBundle lookup fail because the
3421+
// Content and ContentImage mismatch. This means the
3422+
// operator can't check if the profile is deprecated
3423+
// because it can't reliably know which bundle it came
3424+
// from and hasn't parsed that specific datastream. In
3425+
// cases like this, the profile deprecation logic
3426+
// shouldn't prevent the scan. Advanced users might use
3427+
// this technique to point to their own custom content,
3428+
// which is rare but possible.
3429+
Content: framework.OcpContentFile,
3430+
ContentImage: contentImagePath,
3431+
ComplianceScanSettings: compv1alpha1.ComplianceScanSettings{
3432+
Debug: true,
3433+
},
3434+
},
3435+
}
3436+
3437+
// Create the scan directly since we want to set these attributes
3438+
// directly, and not assume the existing ProfileBundles.
3439+
err := f.Client.Create(context.TODO(), testScan, nil)
3440+
if err != nil {
3441+
t.Fatalf("failed to create scan %s: %s", scanName, err)
3442+
}
3443+
defer f.Client.Delete(context.TODO(), testScan)
3444+
3445+
// Wait for the scan to reach Done phase
3446+
err = f.WaitForScanStatus(f.OperatorNamespace, scanName, compv1alpha1.PhaseDone)
3447+
if err != nil {
3448+
t.Fatal(err)
3449+
}
3450+
3451+
// Get the final scan state
3452+
if err = f.Client.Get(context.TODO(), types.NamespacedName{Name: scanName, Namespace: f.OperatorNamespace}, testScan); err != nil {
3453+
t.Fatal(err)
3454+
}
3455+
3456+
// The scan should NOT fail on profile deprecation check when ProfileBundle matching fails
3457+
if testScan.Status.ErrorMessage == "Could not check whether the Profile used by ComplianceScan is deprecated" {
3458+
t.Fatal(errors.New("scan should not fail on profile deprecation check when ProfileBundle matching fails"))
3459+
}
3460+
3461+
t.Logf("Scan completed with result: %s", testScan.Status.Result)
3462+
}

0 commit comments

Comments
 (0)