Skip to content

next (v5.6; do not merge) - #3474

Merged
csviri merged 23 commits into
mainfrom
next
Sep 3, 2026
Merged

next (v5.6; do not merge)#3474
csviri merged 23 commits into
mainfrom
next

Conversation

@csviri

@csviri csviri commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI review requested due to automatic review settings July 3, 2026 06:53
@openshift-ci
openshift-ci Bot requested review from metacosm and xstefank July 3, 2026 06:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Maven project/module versions across Java Operator SDK and its submodules, presumably in preparation for the next development cycle.

Changes:

  • Bumped the root project version in pom.xml.
  • Updated all module parent version references to match the new root version.
  • Updated the standalone operator-framework-bom artifact version.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
pom.xml Updates root project version used across the multi-module build.
operator-framework-core/pom.xml Aligns module parent version with the root project version.
operator-framework/pom.xml Aligns module parent version with the root project version.
operator-framework-junit/pom.xml Aligns module parent version with the root project version.
operator-framework-bom/pom.xml Updates BOM artifact version to match the intended release line.
micrometer-support/pom.xml Aligns module parent version with the root project version.
caffeine-bounded-cache-support/pom.xml Aligns module parent version with the root project version.
bootstrapper-maven-plugin/pom.xml Aligns module parent version with the root project version.
test-index-processor/pom.xml Aligns module parent version with the root project version.
migration/pom.xml Aligns module parent version with the root project version.
sample-operators/pom.xml Aligns sample parent version with the root project version.
sample-operators/webpage/pom.xml Aligns sample module parent version with the sample reactor version.
sample-operators/tomcat-operator/pom.xml Aligns sample module parent version with the sample reactor version.
sample-operators/operations/pom.xml Aligns sample module parent version with the sample reactor version.
sample-operators/mysql-schema/pom.xml Aligns sample module parent version with the sample reactor version.
sample-operators/leader-election/pom.xml Aligns sample module parent version with the sample reactor version.
sample-operators/controller-namespace-deletion/pom.xml Aligns sample module parent version with the sample reactor version.

Comment thread pom.xml
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
Comment thread operator-framework-bom/pom.xml
<groupId>io.javaoperatorsdk</groupId>
<artifactId>sample-operators</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>sample-operators</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>sample-operators</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>sample-operators</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>sample-operators</artifactId>
<version>5.4.1-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 18, 2026
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 19, 2026
Copilot AI review requested due to automatic review settings July 22, 2026 13:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (17)

pom.xml:24

  • The project version was changed to 999-SNAPSHOT, which will publish/build artifacts under an unexpected version and doesn't align with the stated v5.5 line. Revert to the previous snapshot version (or the intended next v5.5.x version).
  <version>999-SNAPSHOT</version>

operator-framework-core/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

operator-framework/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

operator-framework-junit/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

operator-framework-bom/pom.xml:24

  • The BOM version was changed to 999-SNAPSHOT, which will publish an unexpected BOM coordinate/version. Revert to the previous snapshot version (or the intended next v5.5.x version).
  <version>999-SNAPSHOT</version>

migration/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

micrometer-support/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

caffeine-bounded-cache-support/pom.xml:24

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

bootstrapper-maven-plugin/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this plugin resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

test-index-processor/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this module resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make the samples aggregator resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/webpage/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/tomcat-operator/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/operations/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/mysql-schema/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/leader-election/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

sample-operators/controller-namespace-deletion/pom.xml:25

  • The parent version was changed to 999-SNAPSHOT, which will make this sample resolve against an unexpected parent version. Revert to the previous snapshot version (or the intended next v5.5.x version).
    <version>999-SNAPSHOT</version>

@csviri csviri changed the title next (v5.5; do not mege) next (v5.6; do not mege) Jul 28, 2026
Copilot AI review requested due to automatic review settings July 29, 2026 07:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

pom.xml:24

  • Project version is set to 999-SNAPSHOT, which doesn’t align with the PR title targeting v5.6 and looks like a placeholder version. This will publish artifacts under an unexpected coordinate; set the intended next snapshot version (e.g., 5.6.0-SNAPSHOT) and keep all module parent versions consistent with it.
  <version>999-SNAPSHOT</version>

operator-framework/pom.xml:24

  • Module parent version is set to 999-SNAPSHOT. If the intent is v5.6, this should match the root project version (e.g., 5.6.0-SNAPSHOT) to avoid producing/publishing modules under an unexpected version.
    <version>999-SNAPSHOT</version>

operator-framework-bom/pom.xml:24

  • BOM version is set to 999-SNAPSHOT, which appears to be a placeholder and doesn’t match the PR’s v5.6 intent. Use the intended snapshot version (e.g., 5.6.0-SNAPSHOT) so consumers don’t import an unexpected BOM version.
  <version>999-SNAPSHOT</version>

Copilot AI review requested due to automatic review settings August 1, 2026 18:59
private final AtomicBoolean blockNextRelease = new AtomicBoolean(true);

@Override
public <R extends HasMetadata> Optional<SharedIndexInformer<R>> releaseInformer(
}

@Override
public <R extends HasMetadata> Optional<SharedIndexInformer<R>> releaseInformer(
Comment on lines +65 to +67
final var configurationService =
ConfigurationService.newOverriddenConfigurationService(
this.configurationService, o -> o.withKubernetesClient(client));

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 88 out of 88 changed files in this pull request and generated no new comments.

Suppressed comments (3)

pom.xml:25

  • The project version is set to 999-SNAPSHOT, which doesn’t match the PR title indicating a v5.6 branch and will produce artifacts with an unexpected coordinate. If this is intended to be the next development snapshot, use a 5.6.x-SNAPSHOT version (and keep all module parent versions aligned).
    operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/pool/NonSharingInformerPool.java:34
  • Use the generic diamond operator here to avoid a raw ConcurrentHashMap (this currently forces @SuppressWarnings({"unchecked", "rawtypes"}) to cover more than necessary).
  private final Map<ClassifierWithName, SharedIndexInformer> informers = new ConcurrentHashMap();

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java:502

  • ConfigurationService#informerPool() currently returns a new DefaultInformerPool instance on every call and doesn’t call setConfigurationService(this), which violates the method’s own contract (“same instance on every call”) and can disable cross-controller informer sharing (or break reference counting) for implementations that don’t override it. Consider caching and initializing the pool in the default implementation (or make it non-default and require implementations to provide a cached pool).
  @Experimental(
      "Only the configuration API around informer pooling could still change in a"
          + " non-backwards-compatible way, the pooling itself is prod ready.")
  default InformerPool informerPool() {
    return new DefaultInformerPool();

Copilot AI review requested due to automatic review settings August 1, 2026 19:27
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 106 out of 106 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

pom.xml:25

  • The root project version is set to 999-SNAPSHOT, which doesn’t match the PR title intent ("next (v5.6; …)") and will cause all produced artifacts to use an obviously placeholder version. Please set this to the intended next snapshot version and keep it consistent across all module parent references updated in this PR.
    operator-framework-core/pom.xml:26
  • This module now points at parent version 999-SNAPSHOT, which looks like a placeholder and will prevent aligning the module with the actual reactor parent version intended for the v5.6 line. Please update to the real parent snapshot version (and keep consistent with the root pom.xml).
  <parent>
    <groupId>io.javaoperatorsdk</groupId>
    <artifactId>java-operator-sdk</artifactId>
    <version>999-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

sample-operators/pom.xml:26

  • The sample-operators parent version is set to 999-SNAPSHOT, which appears to be a placeholder and should match the actual parent version used by the root project for the intended release line.

Copilot AI review requested due to automatic review settings August 3, 2026 08:03
@csviri
csviri requested a lite review from Copilot September 3, 2026 11:30
csviri and others added 23 commits September 3, 2026 13:36
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
…us (#3480)

Add integration tests that showcases handling explicit state in status. Both for simple managed/secondary resources and using a dependent resource.


Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: pool informers so controllers and event sources can share them

Every InformerEventSource used to create its own SharedIndexInformer, so an
operator whose controllers all watch the same secondary type - ConfigMap and
Secret being the usual suspects - opened one watch connection and kept one cache
per controller for the very same resources.

Informers are now handed out by an InformerPool obtained from the
ConfigurationService, keyed by an InformerClassifier. Event sources whose
classifiers are equal are backed by one informer; the pool reference counts its
users and stops the informer once the last one releases it. The classifier is
made up of everything that decides what an informer watches and how: the
KubernetesClient instance (compared by identity, since two clients for the same
API server may still differ in credentials, impersonation or TLS material), the
resource class or the group/version/kind for generic resources, the namespace,
the label, field and shard selectors, and the item store.

Two components are deliberately not part of that identity. The informerListLimit
is excluded, so event sources that disagree only on it still share an informer,
keeping the limit of whichever one created it and logging a warning. Indexers are
excluded because they can be added to a running informer: they are registered
under a name qualified with the controller and event source that added them, so
index names stay private to an event source while callers keep using their own
names, and they are removed again when that event source releases the informer.

Two strategies ship: DefaultInformerPool shares as described and is the default,
NonSharingInformerPool creates a dedicated informer per event source for anyone
wanting to opt out. Either is selected with
ConfigurationServiceOverrider#withInformerPool, and a custom strategy extends
AbstractInformerPool, which already creates the informers from a classifier,
starts them and waits for their caches to sync, leaving the subclass only the
question of whether and when an informer is shared.

Consequently informer creation and startup moved out of InformerWrapper and
InformerManager into the pool, InformerManager acquires and releases informers
instead of owning them, and it removes its own event handler and indexers from an
informer that keeps running for others. An event source registered dynamically
against an already running shared informer needs no special handling: the client
replays the cache contents to a newly added handler.

Also in support of the above: ConfigurationService#informerPool, an
InformerEventSource constructor that no longer needs an EventSourceContext (the
one taking it is deprecated), the resource group/version/kind on
InformerConfiguration, equality and toString on FieldSelector, and equality of
GroupVersionKindPlural made consistent with its hashCode so that an unspecified
plural no longer splits informers.

The pooling itself is production ready; the configuration API around it is marked
experimental and may still change. Covered by unit tests for the pools, the
classifier, the wrapper and the manager, and by integration tests for sharing,
dynamic registration and de-registration that each run against both strategies.


Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
This needed to be fixed after rebase.

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
This is expected for a pool to set. Event if the underlying implementation would set it, this is the correct way to handle it.

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
AbstractWorkflowExecutor called Workflow#getDependentResourcesByName purely to
read its size. That allocates a HashMap and walks every node to collect the
dependent resources, then discards the map. The executor is constructed on
every reconcile and cleanup of a workflow-based reconciler, so use the existing
Workflow#size instead.
No behavior change; each site is replaced by a helper that already exists.

- PrimaryUpdateAndCacheUtils#compareResourceVersions (and its private
  validateResourceVersion) duplicated the entire algorithm of
  ReconcilerUtilsInternal#validateAndCompareResourceVersions: the length-first
  compare, the empty check, the leading-zero check and the same exception
  messages. It had no production caller, so the copy could silently drift from
  the version all production paths use. Delegate instead.
- addFinalizerWithSSA builds its bare SSA skeleton with
  HasMetadata#initNameAndNamespaceFrom, which ResourceOperations already uses
  for the same purpose and which is Namespaced-aware.
- AbstractInformerPool formats the informer identifier with
  ReconcilerUtilsInternal#getResourceTypeNameWithVersion instead of
  concatenating the resource name and version by hand.
- EventFilterWindow uses ExtendedResourceEvent#getResourceVersion, which had
  no callers even though it is exactly the expression used here.
- LocallyRunOperatorExtension instantiates reconcilers with Utils#instantiate,
  so it also supports non-public no-arg constructors and reports the failing
  class instead of wrapping in a bare RuntimeException.
…3543)

The event count is increased at the beginning of the reconciliation, thus
waiting for it released the test into the middle of a reconciliation that
was still about to remove the finalizer. The subsequent update then raced
with that removal and failed with a conflict.

Wait for the finalizer removal to actually land, and retry the (optimistically
locked) update with a fresh read on conflict.
Add an opt-in, experimental detectApiVersionChange option on
@KubernetesDependent that records the API version the operator applies
in the javaoperatorsdk.io/last-applied-api-version annotation. The
regular matcher then detects a mismatch when that marker differs from
(or is missing relative to) the currently applied API version, causing
a one-time update without triggering repeated reconciliations once the
resource is up-to-date. Disabled by default, so existing behavior and
matching are unaffected unless explicitly enabled.

Guard against a null or immutable annotations map (e.g. Map.of(...))
on the desired resource when detectApiVersionChange is enabled, since
writing the last-applied-api-version marker (and the pre-existing
previous-annotation bookkeeping that runs alongside it) requires a
mutable map. Also rename a misleadingly-named test helper and replace
a no-op assertion on a primitive boolean with a concrete expectation.

Addresses Copilot review feedback on PR #3536.

Add DetectApiVersionChangeIT covering the end-to-end scenario: a
ConfigMap dependent resource configured with detectApiVersionChange
is marked with the current API version on creation (without
triggering an update), and a stale marker annotation left on the
actual resource (simulating an older operator/CRD version) is
detected and corrected with exactly one update, after which no
further reconciliation loop occurs.

Signed-off-by: hej090224 <fc49854985@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
InformerManager is generic over C extends Informable, but getTargetClient
type-tested for InformerEventSourceConfiguration to find out whether a specific
(e.g. remote cluster) client was configured. Informable has two implementors
and only one could answer the question, so a third configuration type wanting
its own client would be ignored silently rather than failing to compile.

Move the default getKubernetesClient() up from InformerEventSourceConfiguration
to Informable and let InformerManager ask the configuration directly. The
default still returns Optional.empty(), so existing implementations are
unaffected. As a side effect the ConfigurationService client is now only
created when no specific client is configured, instead of being created and
then discarded.
- GenericKubernetesResourceMatcher allocated the path-prefix lists
  (List.of(SPEC), List.of(METADATA), the labels/annotations pair, List.of(STATUS))
  once per JSON-diff node while matching, and nodeIsChildOf built a stream per
  call. Both run for every node of every match, so hoist the lists to constants
  and use an indexed loop.
- SSABasedGenericKubernetesResourceMatcher#sanitizeState nested the StatefulSet
  volume-claim-template handling four levels deep inside the type ladder;
  extract it into sanitizeVolumeClaimTemplates so the ladder reads as one
  dispatch per resource kind.
- addresses deprecations
- addresses late PR comments for Informer Pools: #3325

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
markEventReceived and unMarkEventReceived took a boolean that only ever selects
which IllegalStateException guards apply, and every EventProcessor call site
supplied it by re-reading the same controller configuration value. It can never
differ between calls for a given processor, but nothing enforced that: a call
site passing the wrong value would silently change which state transitions are
legal, and the state machine could not be read without also reading its callers.

Decide it once at the edge: ResourceStateManager takes the flag at construction
(EventProcessor already knows it there) and passes it to each ResourceState,
which keeps it as a final field. Both types are package-private, so this is
self-contained.
- Mappers#fromMetadata resolved the primary GroupVersionKind on every
  secondary event, although it only depends on the primary type. Hoist it out
  of the lambda and compare the encoded string before falling back to parsing
  the annotation value.
- Mappers.SecondaryToPrimaryFromDefaultAnnotation built a whole new mapper on
  every invocation; hold a single delegate instead. The primaryResourceType
  field becomes unused and is dropped.
- InformerEventSource#start walked the entire informer cache to seed the
  primary-to-secondary index even when that index is the no-op implementation
  (i.e. whenever a primaryToSecondaryMapper is configured), which is pure
  startup latency proportional to the number of cached secondaries.
- ExternalResourceCachingEventSource#getSecondaryResources looked the primary
  up in the cache a second time although the value was already in a local.
- PerResourcePollingEventSource#getAndCacheResource derived the same
  ResourceID twice in adjacent statements.
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Adds an IT for the situation where the resource that cannot be
deserialized is already present when the informer lists on startup, the
counterpart of MultiVersionCRDIT, which covers the watch case. With
stopOnInformerErrorDuringStartup set to false the operator starts, but the
informer is not retried: the exception handler installed by the informer pool
declines a retry for deserialization errors and the Reflector of the fabric8
client then completes its stop future, so fixing the problem in the cluster
while the operator runs does not bring the informer back.

The test asserts that current behavior, so it fails once the informer does get
retried; the log of the informer pool no longer promises a periodic retry in
this case.

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…update (#3565)

An update of the whole resource set of a primary (a poll result or a received
event) might have been created before the reconciler wrote a resource, thus not
containing it yet. Since such updates are handled as the full actual state, the
write was lost from the cache, and the next reconciliation created a duplicate
of an already created resource or repeated an already executed update.

Writes are now marked as unconfirmed and retained for the next update if it
either does not contain the resource at all - the expected case for a create -
or still contains a state that a write replaced. Every state replaced since the
last update is kept, since the reconciler might write the same resource multiple
times in between, and an update created before any of those writes is stale. Any
other state is treated as a change made outside of the reconciler and accepted
as actual. Marks are dropped on the first update, so a resource really deleted
or changed meanwhile is not retained indefinitely.

Also guards handleRecentResourceUpdate against a missing cache entry, and
resolves the actual resources from the state resources in the external state
bulk dependent integration test, which is the recommended approach for
resources that take longer to become visible.
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
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.

Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

It introduces at least one confirmed correctness issue (the ConfigurationService#informerPool() default implementation violates its own caching contract) and also contains publishing/versioning changes that would likely break release/build expectations.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

pom.xml:25

  • Project version is set to 999-SNAPSHOT, and the same placeholder is referenced as the parent version in multiple module POMs. This will change the published artifact coordinates and typically breaks downstream consumption and release/publishing automation unless it’s the intended next development version.
    operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java:541
  • ConfigurationService#informerPool() is documented as requiring a stable, cached instance per ConfigurationService, but the method is currently default and creates a new DefaultInformerPool on every call. Custom ConfigurationService implementations that don’t override this method will compile but will get incorrect pooling/reference-counting behavior at runtime.
  default InformerPool informerPool() {
    var pool = new DefaultInformerPool();
    pool.setConfigurationService(this);
    return pool;
  }
  • Files reviewed: 172/172 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread pom.xml
Comment on lines 641 to 645
<publishingServerId>central</publishingServerId>
<tokenAuth>true</tokenAuth>
<autoPublish>true</autoPublish>
<waitUntil>published</waitUntil>
<!-- The samples are demos and end-to-end tests, not artifacts to depend on, so they
are not published. The Kotlin one could not be published anyway: it has no Java
sources, so no javadoc jar is attached to it and Central rejects the whole
deployment with "Javadocs must be provided but not found in entries". -->
<excludeArtifacts>
<excludeArtifact>sample-operators</excludeArtifact>
<excludeArtifact>sample-controller-namespace-deletion</excludeArtifact>
<excludeArtifact>sample-kotlin-operator</excludeArtifact>
<excludeArtifact>sample-leader-election</excludeArtifact>
<excludeArtifact>sample-mysql-schema-operator</excludeArtifact>
<excludeArtifact>sample-operations</excludeArtifact>
<excludeArtifact>sample-tomcat-operator</excludeArtifact>
<excludeArtifact>sample-webpage-operator</excludeArtifact>
</excludeArtifacts>
</configuration>
Comment thread pom.xml
Comment on lines 70 to 74
<sonar.organization>java-operator-sdk</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<fabric8-httpclient-impl.name>jdk</fabric8-httpclient-impl.name>
<junit.version>6.1.3</junit.version>
<junit.version>6.1.2</junit.version>
<fabric8-client.version>7.8.0</fabric8-client.version>
Comment thread docs/content/en/docs/documentation/working-with-es-caches.md
@csviri
csviri merged commit 478199e into main Sep 3, 2026
41 checks passed
@csviri
csviri deleted the next branch September 3, 2026 13:15
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.

4 participants