Skip to content

Commit bd2dd07

Browse files
jan-lawopenshift-merge-bot[bot]
authored andcommitted
Store dry run validation result in Status
ref: https://issues.redhat.com/browse/ACM-14577 Adds boolean in the relatedObject properties, indicating when configuration policies detect desired vs actual object mismatches, but dry run updates produce no changes due to webhooks or mutating admission controllers modifying Update requests. Related object properties were previously only set for enforced policies and non-compliant objects, causing compliant objects in Inform policies to have nil properties and inconsistent status reporting. This commit displays related object properties on compliant objects regardless of remediation action. Signed-off-by: Janelle Law <[email protected]>
1 parent c177692 commit bd2dd07

7 files changed

+66
-27
lines changed

api/v1/configurationpolicy_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,11 @@ type ObjectProperties struct {
417417
// Diff stores the difference between the `objectDefinition` in the policy and the object on the
418418
// cluster.
419419
Diff string `json:"diff,omitempty"`
420+
421+
// MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
422+
// there was an initial mismatch between the policy and object, but the dry run update produced
423+
// a compliant result.
424+
MatchesAfterDryRun bool `json:"matchesAfterDryRun,omitempty"`
420425
}
421426

422427
// RelatedObject contains the details of an object matched by the policy.

controllers/configurationpolicy_controller.go

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,7 +2388,7 @@ func (r *ConfigurationPolicyReconciler) handleSingleObj(
23882388
if exists && obj.shouldExist {
23892389
log.V(2).Info("The object already exists. Verifying the object fields match what is desired.")
23902390

2391-
var throwSpecViolation, triedUpdate bool
2391+
var throwSpecViolation, triedUpdate, matchesAfterDryRun bool
23922392
var msg, diff string
23932393
var updatedObj *unstructured.Unstructured
23942394

@@ -2400,8 +2400,9 @@ func (r *ConfigurationPolicyReconciler) handleSingleObj(
24002400

24012401
for _, relatedObj := range obj.policy.Status.RelatedObjects {
24022402
if relatedObj.Properties != nil && relatedObj.Properties.UID == uid {
2403-
// Retain the diff from the previous evaluation
2403+
// Retain the properties from the previous evaluation
24042404
diff = relatedObj.Properties.Diff
2405+
matchesAfterDryRun = relatedObj.Properties.MatchesAfterDryRun
24052406

24062407
break
24072408
}
@@ -2410,7 +2411,7 @@ func (r *ConfigurationPolicyReconciler) handleSingleObj(
24102411
throwSpecViolation = !compliant
24112412
msg = cachedMsg
24122413
} else {
2413-
throwSpecViolation, msg, diff, triedUpdate, updatedObj = r.checkAndUpdateResource(
2414+
throwSpecViolation, msg, diff, triedUpdate, updatedObj, matchesAfterDryRun = r.checkAndUpdateResource(
24142415
obj, objectT, remediation,
24152416
)
24162417

@@ -2435,12 +2436,6 @@ func (r *ConfigurationPolicyReconciler) handleSingleObj(
24352436
resultReason = reasonWantFoundNoMatch
24362437
}
24372438

2438-
objectProperties = &policyv1.ObjectProperties{
2439-
CreatedByPolicy: &created,
2440-
UID: uid,
2441-
Diff: diff,
2442-
}
2443-
24442439
result.events = append(result.events, objectTmplEvalEvent{false, resultReason, resultMsg})
24452440
} else {
24462441
// it is a must have and it does exist, so it is compliant
@@ -2450,16 +2445,17 @@ func (r *ConfigurationPolicyReconciler) handleSingleObj(
24502445
} else {
24512446
result.events = append(result.events, objectTmplEvalEvent{true, reasonWantFoundExists, ""})
24522447
}
2453-
2454-
objectProperties = &policyv1.ObjectProperties{
2455-
CreatedByPolicy: &created,
2456-
UID: uid,
2457-
Diff: diff,
2458-
}
24592448
} else {
24602449
result.events = append(result.events, objectTmplEvalEvent{true, reasonWantFoundExists, ""})
24612450
}
24622451
}
2452+
2453+
objectProperties = &policyv1.ObjectProperties{
2454+
CreatedByPolicy: &created,
2455+
UID: uid,
2456+
Diff: diff,
2457+
MatchesAfterDryRun: matchesAfterDryRun,
2458+
}
24632459
}
24642460

24652461
return
@@ -3162,7 +3158,12 @@ type cachedEvaluationResult struct {
31623158
func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
31633159
obj singleObject, objectT *policyv1.ObjectTemplate, remediation policyv1.RemediationAction,
31643160
) (
3165-
throwSpecViolation bool, message string, diff string, updateNeeded bool, updatedObj *unstructured.Unstructured,
3161+
throwSpecViolation bool,
3162+
message string,
3163+
diff string,
3164+
updateNeeded bool,
3165+
updatedObj *unstructured.Unstructured,
3166+
matchesAfterDryRun bool,
31663167
) {
31673168
log := log.WithValues(
31683169
"policy", obj.policy.Name, "name", obj.name, "namespace", obj.namespace, "resource", obj.scopedGVR.Resource,
@@ -3188,7 +3189,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
31883189
if obj.existingObj == nil {
31893190
log.Info("Skipping update: Previous object retrieval from the API server failed")
31903191

3191-
return false, "", "", false, nil
3192+
return false, "", "", false, nil, true
31923193
}
31933194

31943195
var res dynamic.ResourceInterface
@@ -3210,7 +3211,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
32103211
objectT.MetadataComplianceType,
32113212
)
32123213
if errMsg != "" {
3213-
return true, errMsg, "", true, nil
3214+
return true, errMsg, "", true, nil, true
32143215
}
32153216

32163217
recordDiff := objectT.RecordDiffWithDefault()
@@ -3230,7 +3231,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
32303231

32313232
r.setEvaluatedObject(obj.policy, obj.existingObj, !throwSpecViolation, "")
32323233

3233-
return throwSpecViolation, "", diff, updateNeeded, updatedObj
3234+
return throwSpecViolation, "", diff, updateNeeded, updatedObj, true
32343235
}
32353236

32363237
if updateNeeded {
@@ -3274,7 +3275,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
32743275
r.setEvaluatedObject(obj.policy, obj.existingObj, false, message)
32753276
}
32763277

3277-
return true, message, "", updateNeeded, nil
3278+
return true, message, "", updateNeeded, nil, true
32783279
}
32793280

32803281
// If an update is invalid (i.e. modifying Pod spec fields), then return noncompliant since that
@@ -3300,7 +3301,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33003301

33013302
r.setEvaluatedObject(obj.policy, obj.existingObj, false, message)
33023303

3303-
return true, message, diff, false, nil
3304+
return true, message, diff, false, nil, true
33043305
}
33053306

33063307
mergedObjCopy := obj.existingObj.DeepCopy()
@@ -3323,9 +3324,12 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33233324
diff = handleDiff(log, recordDiff, existingObjectCopy, mergedObjCopy, r.FullDiffs)
33243325
}
33253326

3327+
// Assume object is compliant by inverting the value of throwSpecViolation
33263328
r.setEvaluatedObject(obj.policy, obj.existingObj, !throwSpecViolation, "")
33273329

3328-
return throwSpecViolation, "", diff, updateNeeded, updatedObj
3330+
matchesAfterDryRun = false
3331+
3332+
return throwSpecViolation, "", diff, updateNeeded, updatedObj, matchesAfterDryRun
33293333
}
33303334

33313335
diff = handleDiff(log, recordDiff, existingObjectCopy, dryRunUpdatedObj, r.FullDiffs)
@@ -3335,7 +3339,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33353339
if isInform {
33363340
r.setEvaluatedObject(obj.policy, obj.existingObj, false, "")
33373341

3338-
return true, "", diff, false, nil
3342+
return true, "", diff, false, nil, true
33393343
}
33403344

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

3358-
return true, message, "", updateNeeded, nil
3362+
return true, message, "", updateNeeded, nil, true
33593363
}
33603364

33613365
attempts := 0
@@ -3373,7 +3377,7 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
33733377
message = getMsgPrefix(&obj) + " timed out waiting for the object to delete during recreate, " +
33743378
"will retry on the next policy evaluation"
33753379

3376-
return true, message, "", updateNeeded, nil
3380+
return true, message, "", updateNeeded, nil, true
33773381
}
33783382

33793383
time.Sleep(time.Second)
@@ -3409,14 +3413,14 @@ func (r *ConfigurationPolicyReconciler) checkAndUpdateResource(
34093413
message = fmt.Sprintf("%s failed to %s with the error `%v`", getMsgPrefix(&obj), action, err)
34103414
}
34113415

3412-
return true, message, diff, updateNeeded, nil
3416+
return true, message, diff, updateNeeded, nil, true
34133417
}
34143418

34153419
if !statusMismatch {
34163420
r.setEvaluatedObject(obj.policy, updatedObj, true, message)
34173421
}
34183422

3419-
return throwSpecViolation, "", diff, updateNeeded, updatedObj
3423+
return throwSpecViolation, "", diff, updateNeeded, updatedObj, true
34203424
}
34213425

34223426
func getMsgPrefix(obj *singleObject) string {

deploy/crds/kustomize_configurationpolicy/policy.open-cluster-management.io_configurationpolicies.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,12 @@ spec:
477477
Diff stores the difference between the `objectDefinition` in the policy and the object on the
478478
cluster.
479479
type: string
480+
matchesAfterDryRun:
481+
description: |-
482+
MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
483+
there was an initial mismatch between the policy and object, but the dry run update produced
484+
a compliant result.
485+
type: boolean
480486
uid:
481487
description: |-
482488
UID stores the object UID to help track object ownership for deletion when pruning is

deploy/crds/kustomize_operatorpolicy/policy.open-cluster-management.io_operatorpolicies.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ spec:
384384
Diff stores the difference between the `objectDefinition` in the policy and the object on the
385385
cluster.
386386
type: string
387+
matchesAfterDryRun:
388+
description: |-
389+
MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
390+
there was an initial mismatch between the policy and object, but the dry run update produced
391+
a compliant result.
392+
type: boolean
387393
uid:
388394
description: |-
389395
UID stores the object UID to help track object ownership for deletion when pruning is

deploy/crds/policy.open-cluster-management.io_configurationpolicies.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,12 @@ spec:
484484
Diff stores the difference between the `objectDefinition` in the policy and the object on the
485485
cluster.
486486
type: string
487+
matchesAfterDryRun:
488+
description: |-
489+
MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
490+
there was an initial mismatch between the policy and object, but the dry run update produced
491+
a compliant result.
492+
type: boolean
487493
uid:
488494
description: |-
489495
UID stores the object UID to help track object ownership for deletion when pruning is

deploy/crds/policy.open-cluster-management.io_operatorpolicies.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,12 @@ spec:
381381
CreatedByPolicy reports whether the object was created by the configuration policy, which is
382382
important when pruning is configured.
383383
type: boolean
384+
matchesAfterDryRun:
385+
description: |-
386+
MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
387+
there was an initial mismatch between the policy and object, but the dry run update produced
388+
a compliant result.
389+
type: boolean
384390
uid:
385391
description: |-
386392
UID stores the object UID to help track object ownership for deletion when pruning is

pkg/dryrun/policy.open-cluster-management.io_configurationpolicies.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,12 @@ spec:
484484
Diff stores the difference between the `objectDefinition` in the policy and the object on the
485485
cluster.
486486
type: string
487+
matchesAfterDryRun:
488+
description: |-
489+
MatchesAfterDryRun indicates whether the dry run update matches the policy assessment. If false,
490+
there was an initial mismatch between the policy and object, but the dry run update produced
491+
a compliant result.
492+
type: boolean
487493
uid:
488494
description: |-
489495
UID stores the object UID to help track object ownership for deletion when pruning is

0 commit comments

Comments
 (0)