refactor: configure the event recorder on the operator instead of the controller - #3581
refactor: configure the event recorder on the operator instead of the controller#3581csviri wants to merge 2 commits into
Conversation
… controller Removes EventRecorder from RegisteredController and makes the instance the controllers record their Kubernetes events through configurable for the whole operator, via ConfigurationService.eventRecorder() / ConfigurationServiceOverrider.withEventRecorder(). When none is configured, each controller keeps recording through a DefaultEventRecorder of its own, which attributes the events to that controller, as before. Recording events outside of a reconciliation is now done through the configured instance, which the caller owns, rather than through one handed out by the registered controller.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
FYI @TQJADE added this adjustment. Pls let me know if it makes sense for you. |
There was a problem hiding this comment.
Pull request overview
Refactors Kubernetes event recording so controllers use an EventRecorder configured at the operator level via ConfigurationService.eventRecorder() (and ConfigurationServiceOverrider.withEventRecorder()), while preserving per-controller default behavior when none is configured.
Changes:
- Add operator-level
EventRecorderconfiguration hook (ConfigurationService#eventRecorder) and an overrider (withEventRecorder). - Update
Controllerto use the configured recorder when present, otherwise instantiate a per-controllerDefaultEventRecorder. - Remove
EventRecorderaccess fromRegisteredControllerand update Javadocs/tests to reflect the new access pattern.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java | Adds coverage for controller using configured vs default event recorder. |
| operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java | Adds coverage for default-empty and overridden operator-level event recorder. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/RegisteredController.java | Removes EventRecorder accessor from the registered controller API. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java | Selects operator-configured EventRecorder or falls back to per-controller DefaultEventRecorder. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Context.java | Updates Javadoc to point to operator-configured EventRecorder rather than RegisteredController. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/event/EventRecorder.java | Updates Javadoc to describe the new configuration/access approach and marks API experimental. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java | Adds withEventRecorder support and forwards it via overridden ConfigurationService. |
| operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java | Introduces eventRecorder() as an (experimental) operator-level optional configuration point. |
Suppressed comments (1)
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java:370
- The Javadoc link uses
ConfigurationServicewhich currently requires an import; switching to a fully-qualified link keeps the Javadoc valid while allowing the unused import to be removed.
/**
* The {@link EventRecorder} this controller records its Kubernetes events through, either the one
* configured for the operator, see {@link ConfigurationService#eventRecorder()}, or a {@link
* DefaultEventRecorder} of its own.
*/
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| * <p>This is the unbound form of the API: it is scoped to a controller, not to a reconciliation, | ||
| * and can therefore be used outside of the reconciliation loop, for example from a status listener | ||
| * or a background task. Obtain it from {@link | ||
| * io.javaoperatorsdk.operator.RegisteredController#eventRecorder()}. Within a reconciliation, | ||
| * prefer {@link io.javaoperatorsdk.operator.api.reconciler.Context#eventRecorder()}, which is | ||
| * already bound to the primary resource. | ||
| * or a background task. To use it that way, configure the instance the operator records its events | ||
| * through, see {@link io.javaoperatorsdk.operator.api.config.ConfigurationService#eventRecorder()}, | ||
| * and keep a reference to it. Within a reconciliation, prefer {@link |
| @Override | ||
| public ResourceEventRecorder forResource(HasMetadata regarding) { | ||
| return null; | ||
| } | ||
| }; |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Suppressed comments (3)
Previously missed (2) — in code that hasn't changed since the last review.
operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverriderTest.java:122
- This test EventRecorder stub returns null from forResource(), which violates EventRecorder's contract and can mask/null-pointer failures if the test (or reused helper) ever exercises Context#eventRecorder(). Return a no-op ResourceEventRecorder instead.
@Override
public ResourceEventRecorder forResource(HasMetadata regarding) {
return null;
}
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java:308
- ConfigurationService#eventRecorder() documents that the configured recorder is shared across all controllers, but it doesn't mention the implied concurrency requirements. Since multiple reconciliations can run in parallel (and across controllers), a shared EventRecorder must be thread-safe; calling that out here would prevent subtle runtime issues in custom implementations.
* <p>When empty, which is the default, every controller gets a {@link DefaultEventRecorder} of
* its own, which attributes the events it records to that controller. A recorder configured here
* is shared by all controllers of the operator, so it decides on its own what the events it
* records are attributed to, and it is up to the caller to hold on to the instance if it also
* records events outside of a reconciliation.
operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/event/EventRecorder.java:27
- EventRecorder Javadoc still states the API is "scoped to a controller". With the new operator-level configuration (ConfigurationService#eventRecorder()), the same EventRecorder instance can be shared across controllers and attribution becomes implementation-defined, so this wording is misleading.
* Records Kubernetes events on behalf of a controller.
*
* <p>This is the unbound form of the API: it is scoped to a controller, not to a reconciliation,
* and can therefore be used outside of the reconciliation loop, for example from a status listener
Removes EventRecorder from RegisteredController and makes the instance the
controllers record their Kubernetes events through configurable for the whole
operator, via ConfigurationService.eventRecorder() /
ConfigurationServiceOverrider.withEventRecorder(). When none is configured, each
controller keeps recording through a DefaultEventRecorder of its own, which
attributes the events to that controller, as before. Recording events outside of
a reconciliation is now done through the configured instance, which the caller
owns, rather than through one handed out by the registered controller.