Skip to content

Commit 3fd6da7

Browse files
Correct compliance on no-op dryrun updates
Previously, the policy status would incorrectly have a noncompliant event followed immediately by a compliant event when a dryrun update would not make any changes on that object. This would cause the policy status to repeatedly update if the policy was reconciling often - for example if any of its watched objects were updating. Now only the correct "compliant" event should be emitted in that case. Refs: - https://issues.redhat.com/browse/ACM-25694 Signed-off-by: Justin Kulikauskas <[email protected]>
1 parent 186763b commit 3fd6da7

File tree

2 files changed

+38
-24
lines changed

2 files changed

+38
-24
lines changed

controllers/configurationpolicy_controller.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3325,12 +3325,10 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33253325
diff = handleDiff(log, recordDiff, existingObjectCopy, mergedObjCopy, r.FullDiffs)
33263326
}
33273327

3328-
// Assume object is compliant by inverting the value of throwSpecViolation
3329-
r.setEvaluatedObject(obj.policy, obj.existingObj, !throwSpecViolation, "")
3328+
// treat the object as compliant, with no updates needed
3329+
r.setEvaluatedObject(obj.policy, obj.existingObj, true, "")
33303330

3331-
matchesAfterDryRun = true
3332-
3333-
return throwSpecViolation, "", diff, updateNeeded, updatedObj, matchesAfterDryRun
3331+
return false, "", diff, false, updatedObj, true
33343332
}
33353333

33363334
diff = handleDiff(log, recordDiff, existingObjectCopy, dryRunUpdatedObj, r.FullDiffs)
@@ -3340,7 +3338,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33403338
if isInform {
33413339
r.setEvaluatedObject(obj.policy, obj.existingObj, false, "")
33423340

3343-
return true, "", diff, false, nil, matchesAfterDryRun
3341+
return true, "", diff, false, nil, false
33443342
}
33453343

33463344
// If it's not inform (i.e. enforce), update the object
@@ -3360,7 +3358,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33603358
if err != nil && !k8serrors.IsNotFound(err) {
33613359
message = fmt.Sprintf(`%s failed to delete when recreating with the error %v`, getMsgPrefix(&obj), err)
33623360

3363-
return true, message, "", updateNeeded, nil, matchesAfterDryRun
3361+
return true, message, "", updateNeeded, nil, false
33643362
}
33653363

33663364
attempts := 0
@@ -3378,7 +3376,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33783376
message = getMsgPrefix(&obj) + " timed out waiting for the object to delete during recreate, " +
33793377
"will retry on the next policy evaluation"
33803378

3381-
return true, message, "", updateNeeded, nil, matchesAfterDryRun
3379+
return true, message, "", updateNeeded, nil, false
33823380
}
33833381

33843382
time.Sleep(time.Second)
@@ -3414,14 +3412,14 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
34143412
message = fmt.Sprintf("%s failed to %s with the error `%v`", getMsgPrefix(&obj), action, err)
34153413
}
34163414

3417-
return true, message, diff, updateNeeded, nil, matchesAfterDryRun
3415+
return true, message, diff, updateNeeded, nil, false
34183416
}
34193417

34203418
if !statusMismatch {
34213419
r.setEvaluatedObject(obj.policy, updatedObj, true, message)
34223420
}
34233421

3424-
return throwSpecViolation, "", diff, updateNeeded, updatedObj, matchesAfterDryRun
3422+
return throwSpecViolation, "", diff, updateNeeded, updatedObj, false
34253423
}
34263424

34273425
func getMsgPrefix(obj *singleObject) string {

test/e2e/case8_status_check_test.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ import (
1111
"open-cluster-management.io/config-policy-controller/test/utils"
1212
)
1313

14-
const (
15-
case8ConfigPolicyNamePod string = "policy-pod-to-check"
16-
case8ConfigPolicyNameCheck string = "policy-status-checker"
17-
case8ConfigPolicyNameCheckFail string = "policy-status-checker-fail"
18-
case8ConfigPolicyNameEnforceFail string = "policy-status-enforce-fail"
19-
case8PolicyYamlPod string = "../resources/case8_status_check/case8_pod.yaml"
20-
case8PolicyYamlCheck string = "../resources/case8_status_check/case8_status_check.yaml"
21-
case8PolicyYamlCheckFail string = "../resources/case8_status_check/case8_status_check_fail.yaml"
22-
case8PolicyYamlEnforceFail string = "../resources/case8_status_check/case8_status_enforce_fail.yaml"
23-
case8ConfigPolicyStatusPod string = "policy-pod-invalid"
24-
case8PolicyYamlBadPod string = "../resources/case8_status_check/case8_pod_fail.yaml"
25-
case8PolicyYamlSpecChange string = "../resources/case8_status_check/case8_pod_change.yaml"
26-
)
27-
2814
var _ = Describe("Test pod obj template handling", func() {
15+
const (
16+
case8ConfigPolicyNamePod string = "policy-pod-to-check"
17+
case8ConfigPolicyNameCheck string = "policy-status-checker"
18+
case8ConfigPolicyNameCheckFail string = "policy-status-checker-fail"
19+
case8ConfigPolicyNameEnforceFail string = "policy-status-enforce-fail"
20+
case8PolicyYamlPod string = "../resources/case8_status_check/case8_pod.yaml"
21+
case8PolicyYamlCheck string = "../resources/case8_status_check/case8_status_check.yaml"
22+
case8PolicyYamlCheckFail string = "../resources/case8_status_check/case8_status_check_fail.yaml"
23+
case8PolicyYamlEnforceFail string = "../resources/case8_status_check/case8_status_enforce_fail.yaml"
24+
case8ConfigPolicyStatusPod string = "policy-pod-invalid"
25+
case8PolicyYamlBadPod string = "../resources/case8_status_check/case8_pod_fail.yaml"
26+
case8PolicyYamlSpecChange string = "../resources/case8_status_check/case8_pod_change.yaml"
27+
)
28+
2929
Describe("Create a policy on managed cluster in ns:"+testNamespace, Ordered, func() {
3030
It("should create a policy properly on the managed cluster", func() {
3131
By("Creating " + case8ConfigPolicyNamePod + " on managed")
@@ -204,6 +204,10 @@ var _ = Describe("Test related object property status", Ordered, func() {
204204
matchesAfterDryRun, _, _ := unstructured.NestedBool(relatedObj, "properties", "matchesAfterDryRun")
205205

206206
g.Expect(matchesAfterDryRun).To(BeTrue())
207+
208+
history, _, err := unstructured.NestedSlice(managedPlc.Object, "status", "history")
209+
g.Expect(err).NotTo(HaveOccurred())
210+
g.Expect(history).To(HaveLen(1))
207211
}, defaultTimeoutSeconds, 1).Should(Succeed())
208212
})
209213

@@ -227,6 +231,10 @@ var _ = Describe("Test related object property status", Ordered, func() {
227231
matchesAfterDryRun, _, _ := unstructured.NestedBool(relatedObj, "properties", "matchesAfterDryRun")
228232

229233
g.Expect(matchesAfterDryRun).To(BeTrue())
234+
235+
history, _, err := unstructured.NestedSlice(managedPlc.Object, "status", "history")
236+
g.Expect(err).NotTo(HaveOccurred())
237+
g.Expect(history).To(HaveLen(2))
230238
}, defaultTimeoutSeconds, 1).Should(Succeed())
231239
})
232240

@@ -251,6 +259,10 @@ var _ = Describe("Test related object property status", Ordered, func() {
251259
matchesAfterDryRun, _, _ := unstructured.NestedBool(relatedObj, "properties", "matchesAfterDryRun")
252260

253261
g.Expect(matchesAfterDryRun).To(BeFalse())
262+
263+
history, _, err := unstructured.NestedSlice(managedPlc.Object, "status", "history")
264+
g.Expect(err).NotTo(HaveOccurred())
265+
g.Expect(history).To(HaveLen(3))
254266
}, defaultTimeoutSeconds, 1).Should(Succeed())
255267
})
256268

@@ -275,6 +287,10 @@ var _ = Describe("Test related object property status", Ordered, func() {
275287
matchesAfterDryRun, _, _ := unstructured.NestedBool(relatedObj, "properties", "matchesAfterDryRun")
276288

277289
g.Expect(matchesAfterDryRun).To(BeFalse())
290+
291+
history, _, err := unstructured.NestedSlice(managedPlc.Object, "status", "history")
292+
g.Expect(err).NotTo(HaveOccurred())
293+
g.Expect(history).To(HaveLen(4))
278294
}, defaultTimeoutSeconds, 1).Should(Succeed())
279295
})
280296

0 commit comments

Comments
 (0)