Skip to content

Conversation

@ephico2real2
Copy link

PR-194: Remove fields present in actual but missing in expected (handles zero-value cases like "0")

Summary

This change fixes a bug where fields with "zero-like" values (e.g., "0") were not removed when conditionals stop rendering them in templates. The comparison/patch logic previously didn’t emit deletions for keys missing in expected but present in actual.

Implementation

How reviewers can reproduce and verify (using my operator fork)

Wire the fixed dependency

Option A (track branch):

# In namespace-configuration-operator
go get github.com/ephico2real2/operator-utils@fix-issue-194-field-removal-zero-value
go mod tidy

Option B (pin exact commit via pseudo-version):

check examples/test-and-logic/ISSUE-194-FIX-IMPLEMENTATION.md for directions.

// go.mod
replace github.com/redhat-cop/operator-utils => github.com/ephico2real2/operator-utils v0.0.0-20251208075852-9569465257c1

Build & run locally (in namespace-configuration-operator)

./build.sh -o bin/manager main.go
./run-go.sh --skip-build

Test config

examples/test-and-logic/test-issue-194-field-removal-namespaceconfig.yaml
- Matches namespaces labeled test-issue-194=true
- Conditional: if allow-pvc != "true", include spec.hard.persistentvolumeclaims: "0"

Verification steps

  1. Initial (no annotation) → field present:
oс create namespace test-issue-194-ns || true
oc label namespace test-issue-194-ns test-issue-194=true --overwrite
oc apply -f examples/test-and-logic/test-issue-194-field-removal-namespaceconfig.yaml
oc get resourcequota test-issue-194-quota -n test-issue-194-ns -o jsonpath='{.spec.hard.persistentvolumeclaims}' && echo
# Expect: 0
  1. Set annotation allow-pvc=true → field removed:
oc annotate namespace test-issue-194-ns allow-pvc=true --overwrite
sleep 8
oc get resourcequota test-issue-194-quota -n test-issue-194-ns -o jsonpath='{.spec.hard.persistentvolumeclaims}' && echo
# Expect: (empty)
  1. Remove annotation → field added back:
oc annotate namespace test-issue-194-ns allow-pvc-
sleep 8
oc get resourcequota test-issue-194-quota -n test-issue-194-ns -o jsonpath='{.spec.hard.persistentvolumeclaims}' && echo
# Expect: 0

Real-time proof (timestamps + full YAML)

Server-side apply captures managedFields.time:

oc apply -f examples/test-and-logic/test-issue-194-field-removal-namespaceconfig.yaml --server-side --field-manager=issue-194-test
oc get namespaceconfig test-issue-194-field-removal -o json | jq -r '.metadata.managedFields | sort_by(.time) | last | .time'

Capture and diff YAML:

oc get resourcequota test-issue-194-quota -n test-issue-194-ns -o yaml > /tmp/rq-before.yaml
oc annotate namespace test-issue-194-ns allow-pvc=true --overwrite && sleep 8
oc get resourcequota test-issue-194-quota -n test-issue-194-ns -o yaml > /tmp/rq-after.yaml
diff -u /tmp/rq-before.yaml /tmp/rq-after.yaml | sed -n '1,200p'

Live YAML excerpt (after fix — allow-pvc=true) and the original template snippet are embedded in:

  • examples/test-and-logic/ISSUE-194-VERIFICATION-GUIDE.md

Commands used to identify the correct module

grep -r "func.*UpdateLockedResources" controllers/

go doc github.com/redhat-cop/operator-utils/pkg/util/lockedresourcecontroller.EnforcingReconciler.UpdateLockedResources

grep -A 5 "type NamespaceConfigReconciler struct" controllers/namespaceconfig_controller.go

grep -B 2 -A 2 "UpdateLockedResources" controllers/namespaceconfig_controller.go

go list -m -versions github.com/redhat-cop/operator-utils

go list -m github.com/redhat-cop/operator-utils

Impact & compatibility

  • Generic fix for any resource/field removed by conditional rendering.
  • Uses standard JSON Merge Patch semantics (null deletes); respects excluded paths; supports nested structures.

Checklist

  • Fix implemented with recursive null-injection for missing keys

  • Verified locally and on a cluster with before/after YAML diffs

  • No changes to public API of operator-utils

  • Backwards compatible

  • Add createPatchWithNullFields to set missing fields to null in merge patches

  • Add addNullFieldsForMissing helper to recursively handle nested structures

  • Ensures fields are properly removed when they should be absent

  • Fixes bug where fields with value "0" are not removed when conditionals change from true to false

- Add createPatchWithNullFields to set missing fields to null in merge patches
- Add addNullFieldsForMissing helper to recursively handle nested structures
- Ensures fields are properly removed when they should be absent
- Fixes bug where fields with value "0" are not removed when conditionals change from true to false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant