Config follow-up: Implement component override functionality for Config resource#475
Conversation
21f23b4 to
1fb3071
Compare
1fb3071 to
b183d8b
Compare
b183d8b to
ddcb996
Compare
|
@andreaskaris, this pull request is now in conflict and requires a rebase. |
ddcb996 to
8f6b916
Compare
frobware
left a comment
There was a problem hiding this comment.
ConfigMap should not be overrideable given that it's now an internal implementation detail of the Config CRD (post #461). Should isOverrideable narrow the list down to the DaemonSet, CSIDriver, SCC -- everthing else is excluded.
|
I played around with the functionality and have some suggestions for UX in #489. |
|
Replying to my own question here after experimenting with this. For a debug/escape hatch, I think blocking creation is the right behaviour. The semantics become simple and predictable: unmanaged = the operator pretends this resource doesn't exist. If you mark something as unmanaged and then delete it, you presumably meant to delete it. Recreating something marked "unmanaged" would be semantically incoherent - you're telling the operator not to manage it, but then expecting it to manage recreation. If deletion was accidental, the recovery is straightforward: remove the override, and the operator recreates the resource on the next reconcile. I tested this flow and it works as expected. The alternative (only blocking updates, allowing recreation) adds complexity and creates confusing edge cases. For a feature explicitly framed as a debug escape hatch for advanced users, I'd keep it simple and trust the user knows what they're doing. |
The reason for the format that I chose is that OpenShift does it like that: It doesn't have to follow OCP's example, though, your version feels cleaner to me |
This commit adds the ability to mark components as unmanaged in the bpfman-operator, preventing the operator from creating or updating specific objects. The implementation includes: - Added ComponentOverride struct to Config API with fields for kind, group, namespace, name, and unmanaged flag - Modified assureResource function to check for overrides and skip management of unmanaged components - Implemented isOverridden helper function to match objects against override specifications - Added tests to verify override functionality works correctly across all component types Signed-off-by: Andreas Karis <ak.karis@gmail.com>
Change the override selector from requiring a separate group field to using apiVersion, which matches the format users see in kubectl output. This makes overrides easier to configure by allowing direct copy/paste from manifests. The implementation now uses scheme-based GVK resolution instead of relying on the object's TypeMeta, which may not be populated for objects constructed in code. This ensures reliable matching regardless of how the object was created. Also fix typos and improve documentation to clarify that overrides are a debug/escape hatch feature for advanced users. Signed-off-by: Andrew McDermott <amcdermo@redhat.com> (cherry picked from commit 39dfd65)
- make generate - make manifests Signed-off-by: Andreas Karis <ak.karis@gmail.com>
- make bundle Signed-off-by: Andreas Karis <ak.karis@gmail.com>
8f6b916 to
235fffe
Compare
Signed-off-by: Andreas Karis <ak.karis@gmail.com>
|
@frobware Ready for another review, I added your changes |
Testing Component OverridesHelper script: https://github.com/frobware/nix-bpfman/blob/main/scripts/bpfman-operator-component-override Initial state - no overridesAdd daemon overrideOperator logs confirm skippingAdd all componentsReset all overrides |
Follow-up: Verify unmanaged resource is not recreated$ bpfman-operator-component-override add daemon
config.bpfman.io/bpfman-config patched
Added override: daemon
$ kubectl get daemonset -n bpfman bpfman-daemon
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
bpfman-daemon 1 1 1 1 1 <none> 76m
$ kubectl delete daemonset -n bpfman bpfman-daemon
daemonset.apps "bpfman-daemon" deleted
$ sleep 15; kubectl get daemonset -n bpfman bpfman-daemon
Error from server (NotFound): daemonsets.apps "bpfman-daemon" not found
$ bpfman-operator-component-override delete daemon
config.bpfman.io/bpfman-config patched
Removed override: daemon
$ sleep 5; kubectl get daemonset -n bpfman bpfman-daemon
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
bpfman-daemon 1 1 1 1 1 <none> 8sThe operator correctly:
|
All components testedEach component was marked as unmanaged, deleted, verified not recreated, then the override was removed and verified the operator recreated it. metrics-proxy (DaemonSet)$ bpfman-operator-component-override add metrics-proxy && kubectl delete daemonset -n bpfman bpfman-metrics-proxy
Added override: metrics-proxy
daemonset.apps "bpfman-metrics-proxy" deleted
$ sleep 10; kubectl get daemonset -n bpfman bpfman-metrics-proxy
Error from server (NotFound): daemonsets.apps "bpfman-metrics-proxy" not found
$ bpfman-operator-component-override delete metrics-proxy && sleep 5; kubectl get daemonset -n bpfman bpfman-metrics-proxy
Removed override: metrics-proxy
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
bpfman-metrics-proxy 1 1 1 1 1 <none> 5scsi (CSIDriver)$ bpfman-operator-component-override add csi && kubectl delete csidriver csi.bpfman.io
Added override: csi
csidriver.storage.k8s.io "csi.bpfman.io" deleted
$ sleep 10; kubectl get csidriver csi.bpfman.io
Error from server (NotFound): csidrivers.storage.k8s.io "csi.bpfman.io" not found
$ bpfman-operator-component-override delete csi && sleep 5; kubectl get csidriver csi.bpfman.io
Removed override: csi
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE
csi.bpfman.io false true false <unset> false Ephemeral 5sconfig (ConfigMap)$ bpfman-operator-component-override add config && kubectl delete configmap -n bpfman bpfman-config
Added override: config
configmap "bpfman-config" deleted
$ sleep 10; kubectl get configmap -n bpfman bpfman-config
Error from server (NotFound): configmaps "bpfman-config" not found
$ bpfman-operator-component-override delete config && sleep 5; kubectl get configmap -n bpfman bpfman-config
Removed override: config
NAME DATA AGE
bpfman-config 3 5sALL (bulk operations)$ bpfman-operator-component-override add ALL && bpfman-operator-component-override list
Added override: daemon
Added override: csi
Added override: metrics-proxy
Added override: config
Current overrides:
DaemonSet/bpfman-daemon (unmanaged=true)
CSIDriver/csi.bpfman.io (unmanaged=true)
DaemonSet/bpfman-metrics-proxy (unmanaged=true)
ConfigMap/bpfman-config (unmanaged=true)
$ bpfman-operator-component-override reset && bpfman-operator-component-override list
All overrides removed
No overrides configuredAll component types (DaemonSet, CSIDriver, ConfigMap) work correctly with the override functionality. |
|
LGTM |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #475 +/- ##
===========================
===========================
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This commit adds the ability to mark components as unmanaged in the
bpfman-operator, preventing the operator from creating or updating
specific objects. The implementation includes:
kind, group, namespace, name, and unmanaged flag
management of unmanaged components
override specifications
across all component types
Documentation
Component Overrides
The
overridesfield allows you to mark specific components as unmanaged, preventing the operator from creating or updating them. This is intended as a debug/escape hatch for advanced users who need to customize specific resources without operator interference.YAML Configuration
Add overrides directly to the Config resource:
JSON Patch for Precise Control
Using
kubectl patchto add overrides:Adding Multiple Overrides
To append to existing overrides without replacing them:
The
/-notation appends to the existing overrides array rather than replacing it.Examples
Override the metrics proxy DaemonSet:
Override a ConfigMap:
Override multiple resources:
Note: The
apiVersionfield matches what you see in kubectl output (e.g.,apps/v1for DaemonSets,v1for core resources like ConfigMaps), making it easy to copy/paste from existing manifests.