-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor object template status generation #143
Refactor object template status generation #143
Conversation
/hold |
e4b0360
to
ff294aa
Compare
/unhold this is ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes haven't really "clicked" for me yet... I only have some initial comments, I need to look at it again.
var namesStr string | ||
|
||
if len(namespaceToEvent[ns].result.objectNames) > 0 { | ||
namesStr = " [" | ||
|
||
for i, name := range namespaceToEvent[ns].result.objectNames { | ||
namesStr += name | ||
if i != len(namespaceToEvent[ns].result.objectNames)-1 { | ||
namesStr += ", " | ||
} | ||
} | ||
|
||
namesStr += "]" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var namesStr string | |
if len(namespaceToEvent[ns].result.objectNames) > 0 { | |
namesStr = " [" | |
for i, name := range namespaceToEvent[ns].result.objectNames { | |
namesStr += name | |
if i != len(namespaceToEvent[ns].result.objectNames)-1 { | |
namesStr += ", " | |
} | |
} | |
namesStr += "]" | |
} | |
namesStr := "" | |
if len(namespaceToEvent[ns].result.objectNames) > 0 { | |
namesStr = " [" + strings.Join(namespaceToEvent[ns].result.objectNames, ", ") + "]" | |
} |
I know we have this same kind of loop somewhere else, but I think we should use the stdlib for this.
r.Recorder.Event(policy, eventType, fmt.Sprintf(eventFmtStr, policy.GetName(), objDetails.name), | ||
convertPolicyStatusToString(policy)) | ||
result = objectResult{ | ||
[]string{objName}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when this objName
is empty? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It ends up not being used because it's an error case, so it falls in the default
switch case. Here is an example of the status:
conditions:
- lastTransitionTime: "2023-06-21T12:24:28Z"
message: namespaced object of kind Role has no namespace specified from the policy namespaceSelector nor the object metadata
reason: K8s missing namespace
status: "True"
type: violation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a unit test for this situation to illustrate this. I hope this helps clarify it.
type objectResult struct { | ||
objectNames []string | ||
namespace string | ||
events []objectResultEvent | ||
} | ||
|
||
type objectResultEvent struct { | ||
compliant bool | ||
reason string | ||
message string | ||
} | ||
|
||
type objectResultEventWithCtx struct { | ||
result objectResult | ||
event objectResultEvent | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these names are pretty confusing. I don't have anything better though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I tried renaming them. Let me know if the new names are better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree
result = objectResult{ | ||
objectNames: []string{obj.name}, | ||
namespace: obj.namespace, | ||
events: append(result.events, objectResultEvent{completed, reason, msg}), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just append to the events here (like 2 lines down) ?
result = objectResult{ | |
objectNames: []string{obj.name}, | |
namespace: obj.namespace, | |
events: append(result.events, objectResultEvent{completed, reason, msg}), | |
} | |
result.events = append(result.events, objectResultEvent{completed, reason, msg}) |
// Determine the applicable batch. For example, if there are 3 batches but 2 events, we need | ||
// to skip the first batch and append to the second and third batches. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely need more explanation for this comment. Why skip any batches? Why specifically the first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the comment with a real example. Does this help?
f8ca607
to
7989040
Compare
Signed-off-by: mprahl <mprahl@users.noreply.github.com>
@@ -205,7 +205,7 @@ install-resources: | |||
|
|||
.PHONY: e2e-test | |||
e2e-test: e2e-dependencies | |||
$(GINKGO) -v --fail-fast $(E2E_TEST_ARGS) test/e2e | |||
$(GINKGO) -v --timeout=2h --fail-fast $(E2E_TEST_ARGS) test/e2e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove this. I fixed flaky e2e test issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once #145 is merged, I'll rebase this PR and remove the increased timeout.
Would you refactor the lines from 88 to 91 in configurationpolicy_utils. |
|
||
for namespace, eventWithCtx := range namespaceToEvent { | ||
// If a noncompliant event is encountered, then reset the maps to only include noncompliant events. | ||
if compliant && !eventWithCtx.event.compliant { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this part. Amazing logic flow!
// createMergedStatus updates the status field for a configurationpolicy with remediationAction=inform | ||
// based on how many compliant/noncompliant objects are found when processing the templates in the configurationpolicy | ||
// Or multiple namespaces and enforce use this | ||
func createMergedStatus( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lovely remove this part
@yiraeChristineKim I think since that change is unrelated to this PR, I'd prefer it in a separate PR. |
This refactoring takes away the responsibility of individual methods of updating the status and instead they return one or more status events. The handleObjectTemplates method then generates status events using the entire context of results from the object-template to be able to consolidate messages and include different messages per namespace. Relates: https://issues.redhat.com/browse/ACM-5175 Signed-off-by: mprahl <mprahl@users.noreply.github.com>
/hold for reviews |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple questions about whether passing a pointer is necessary, but overall a great update. The batching pulls together similar actions nicely (though I'll be honest some of the more elaborate batching logic I kind of took your word it worked 😆 )
policy *policyv1.ConfigurationPolicy, | ||
index int, | ||
) (mapping *meta.RESTMapping, updateNeeded bool) { | ||
) (mapping *meta.RESTMapping, result *objectTmplEvalResult) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The policy argument no longer needs to be a pointer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pointer is nice in that it prevents the policy data from being copied in memory, however, it does mean the function could unintentionally modify the policy.
What do you think @yiraeChristineKim and @JustinKuli?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If our controller is out of memory, I agree to use a pointer. Otherwise, mappingErrResult is only used
line 1159, so I vote for removing Pointer
mappingErrResult != nil {
nsToResults[ns] = *mappingErrResult
continue
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh no, getmapping(helper) is used only here... let's go with pointer to save memory
@@ -2931,7 +2867,7 @@ func (r *ConfigurationPolicyReconciler) sendComplianceEvent(instance *policyv1.C | |||
} | |||
|
|||
// convertPolicyStatusToString to be able to pass the status as event | |||
func convertPolicyStatusToString(plc *policyv1.ConfigurationPolicy) (results string) { | |||
func convertPolicyStatusToString(plc *policyv1.ConfigurationPolicy) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'm not sure the plc argument needs to be a pointer?
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dhaiducek, mprahl, yiraeChristineKim The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/unhold |
3237da5
into
open-cluster-management-io:main
The code is ready for review but I will need to update some E2E tests.
This refactoring takes away the responsibility of individual methods of updating the status and instead they return one or more status events. The handleObjectTemplates method then generates status events using the entire context of results from the object-template to be able to consolidate messages and include different messages per namespace.
Relates:
https://issues.redhat.com/browse/ACM-5175