fix(compliance): Make tailored profiles extends attribute optional#19158
fix(compliance): Make tailored profiles extends attribute optional#19158
Conversation
|
Skipping CI for Draft Pull Request. |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In the
Fetched profile not of type 'unstructured'log line, consider loggingprofileObjrather thanobjso the reported type corresponds to the value actually being type-asserted. - The mock listers’
ListandGetmethods currently return(nil, nil); having them return an error or panic instead would make tests fail fast if those methods are accidentally used, preventing silent misbehavior in future changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the `Fetched profile not of type 'unstructured'` log line, consider logging `profileObj` rather than `obj` so the reported type corresponds to the value actually being type-asserted.
- The mock listers’ `List` and `Get` methods currently return `(nil, nil)`; having them return an error or panic instead would make tests fail fast if those methods are accidentally used, preventing silent misbehavior in future changes.
## Individual Comments
### Comment 1
<location path="sensor/kubernetes/complianceoperator/dispatchers/complianceoperatortailoredprofiles_test.go" line_range="79-88" />
<code_context>
+ baseProfile := &v1alpha1.Profile{
</code_context>
<issue_to_address>
**suggestion (testing):** Add assertions that the tailored profile inherits labels/annotations/description from the base profile when Extends is set
In `TestProcessEvent_ExtendsProfile`, the test only checks rule computation, but this change also preserves labels, annotations, and description from the base profile when `Extends` is set. Please set `Labels`, `Annotations`, and `Description` on `baseProfile`, leave the tailored profile’s `Spec.Description` empty, and assert that the resulting `ComplianceOperatorProfile` inherits those values. That will lock in the new `baseProfile` behavior and guard against regressions.
Suggested implementation:
```golang
ObjectMeta: metav1.ObjectMeta{
Name: "ocp4-cis",
Namespace: "openshift-compliance",
Labels: map[string]string{
"base-profile-label": "label-value",
},
Annotations: map[string]string{
"base-profile-annotation": "annotation-value",
},
},
```
```golang
ProfilePayload: v1alpha1.ProfilePayload{
ID: "xccdf_org.ssgproject.content_profile_cis",
Description: "Base profile description",
```
To fully implement your review comment, the following additional changes are needed elsewhere in `TestProcessEvent_ExtendsProfile` (not visible in the provided snippet):
1. **TailoredProfile spec description**
- Locate the construction of the `*v1alpha1.TailoredProfile` used in this test.
- In `tp.Spec`, ensure `Description` is explicitly empty, e.g.:
```go
Spec: v1alpha1.TailoredProfileSpec{
// other fields...
Description: "",
}
```
2. **Assertions on the resulting ComplianceOperatorProfile**
- After the code under test processes the event and produces the resulting `ComplianceOperatorProfile` (let’s call it `cop`), add assertions verifying inherited metadata and description:
```go
require.Equal(t, baseProfile.Labels, cop.Labels)
require.Equal(t, baseProfile.Annotations, cop.Annotations)
require.Equal(t, baseProfile.Description, cop.Spec.Description)
```
- If the description is stored differently (e.g., `cop.Annotations["description"]` or a differently named field), adjust the assertion to target the actual field used for the profile description in your `ComplianceOperatorProfile` type.
These changes will ensure the test not only validates rule computation, but also that labels, annotations, and description from the base profile are preserved when `Extends` is set, guarding against regressions in the new `baseProfile` behavior.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
sensor/kubernetes/complianceoperator/dispatchers/complianceoperatortailoredprofiles_test.go
Show resolved
Hide resolved
|
This change is part of the following stack: Change managed by git-spice. |
|
/test ocp-4-20-compliance-e2e-tests |
|
Images are ready for the commit at 74b4543. To use with deploy scripts, first |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #19158 +/- ##
==========================================
+ Coverage 49.50% 49.59% +0.08%
==========================================
Files 2668 2675 +7
Lines 201442 201830 +388
==========================================
+ Hits 99715 100088 +373
- Misses 94280 94282 +2
- Partials 7447 7460 +13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In the tests, you index
event.ForwardMessages[0]without asserting thatevent.ForwardMessagesis non-nil and non-empty; consider adding arequire.NotEmpty(t, event.ForwardMessages)(or similar) before indexing to avoid panics if the dispatcher behavior changes. - For tailored profiles without
Spec.Extends,baseProfileis left at its zero value and you rely solely on enabled rules; consider explicitly documenting or guarding this path (e.g., early-return whenExtends == ""and there are disabled rules) so the behavior is clearer and misconfigurations are easier to diagnose.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the tests, you index `event.ForwardMessages[0]` without asserting that `event.ForwardMessages` is non-nil and non-empty; consider adding a `require.NotEmpty(t, event.ForwardMessages)` (or similar) before indexing to avoid panics if the dispatcher behavior changes.
- For tailored profiles without `Spec.Extends`, `baseProfile` is left at its zero value and you rely solely on enabled rules; consider explicitly documenting or guarding this path (e.g., early-return when `Extends == ""` and there are disabled rules) so the behavior is clearer and misconfigurations are easier to diagnose.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
mtodor
left a comment
There was a problem hiding this comment.
Nice work! Changes look good, I have added a few nitpicks, but nothing that changes functionality.
| Labels: complianceProfile.Labels, | ||
| Annotations: complianceProfile.Annotations, | ||
| Description: stringutils.FirstNonEmpty(tailoredProfile.Spec.Description, complianceProfile.Description), | ||
| Labels: baseProfile.Labels, |
There was a problem hiding this comment.
nitpick: It's good practice to use getters instead directly accessing fields.
There was a problem hiding this comment.
Yep, I didn't change this here because the existing code does not use getters, so it would be a rather unrelated refactor, so I'd prefer to open a separate PR to use getters everywhere
| Description: stringutils.FirstNonEmpty(tailoredProfile.Spec.Description, complianceProfile.Description), | ||
| Labels: baseProfile.Labels, | ||
| Annotations: baseProfile.Annotations, | ||
| Description: stringutils.FirstNonEmpty(tailoredProfile.Spec.Description, baseProfile.Description), |
There was a problem hiding this comment.
Is there are a reason why we are not using the same logic for Labels and Annotations?
Under "the same logic" - I'm referring to: Use information from tailoredProfile if it exists, and if not -> use info from baseProfile.
There was a problem hiding this comment.
I suppose the previous reason was that, since tailored profiles were always extending a base profile, the annotations of that base were the meaningful ones, the TP itself was likely to not have any annotations.
Good catch though, because now we support TPs which don't extend a profile so it's good to take these metadata from them.
I did this: 74b4543
However I'm not fully convinced, because that changes previous intended behavior: for tailored profiles that extend a base profile, and where the user added metadata to the TP itself, previously we were ignoring the TP's metadata altogether, while now we only take the TP's metadata and ignore the base profile.
We could reverse the precedence to keep behavior unchanged, but that would make the code look weird because for labels/annotations the base takes precedence while for description the TP takes precedence.
We could also merge everything.
Or we can keep the current behavior (revert that commit I added) and consider this in a separate PR. I think the correct approach is what you suggested and I implemented here, ignoring user-provided metadata feels wrong.
Thoughts?
sensor/kubernetes/complianceoperator/dispatchers/complianceoperatortailoredprofiles.go
Show resolved
Hide resolved
| "k8s.io/client-go/tools/cache" | ||
| ) | ||
|
|
||
| // mockNamespaceLister implements cache.GenericNamespaceLister |
There was a problem hiding this comment.
Can we use already existing mock: sensor/kubernetes/listener/resources/mocks/dispatcher.go? As I see, it's one level higher and there are some functions related to tailored profiles. Tbh, I'm not sure where is it used and how.
Beside that, we usually keep mocks in separate package and in most cases they are generated with mockgen. I'm not sure if we can use that here.
There was a problem hiding this comment.
The existing mock is for Dispatcher interface, but we need to mock cache.GenericLister (to fetch the base profile).
Regarding mockgen, since this is a simple external interface with custom behavior (store/retrieve by namespace) - this seemed simpler than setting up expectations per test.
So I think we can use it but it would be less compact than this. Happy to change it if you prefer though!
| for i, r := range profile.GetRules() { | ||
| ruleNames[i] = r.GetName() | ||
| } | ||
| assert.Len(t, ruleNames, 3) |
There was a problem hiding this comment.
nit-nitpick: maybe sort and use Equal to []string{"ocp4-api-server-anonymous-auth", "ocp4-api-server-encryption-provider-cipher", "ocp4-audit-log-forwarding-enabled"} - easier to read/understand.
There was a problem hiding this comment.
That results in nicer code indeed, thanks! Here: 89fe9bc
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ofile This is relevant now that TPs without a base profile are supported. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
/test ocp-4-20-compliance-e2e-tests |
|
@guzalv: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
Description
While our current code requires tailored profiles to contain an "extends" attribute, it was made optional in CO v0.1.4 , to enable creating tailored profiles from scratch.
This PR makes the attribute optional and adds tests to ensure effective rules are computed correctly in all cases.
User-facing documentation
Testing and quality
Automated testing
How I validated my change
CI