Summary
Revisit #1410 ("Access secondary resources by ResourceID") now that ResourceDiscriminators are gone. Add typed by-name accessors on Context<P> so reconcilers can look up secondary resources scoped to a specific event source without dropping to eventSourceRetriever().getEventSourceFor(...) and casting.
Motivation
When a reconciler watches external secondary resources via a named event source (e.g. ConfigMaps referenced from a custom resource's spec), today's options on Context<P> are:
getSecondaryResource(Class, String eventSourceName) returns the single linked resource. No by-name lookup.
getSecondaryResourcesAsStream(Class, boolean deduplicate) returns all secondary resources of the type across all event sources. No event-source scoping.
- Drop to
context.eventSourceRetriever().getEventSourceFor(...), cast to InformerEventSource, then call .get(ResourceID). Works, but ad-hoc.
#1410 acknowledged this back in 2022 and the chosen mechanism (ResourceDiscriminators) was later removed in #2253, leaving the gap unfilled.
With PR #3345 having landed (Cache<T> / ResourceCache<T> interfaces, read-cache-after-write consistent), the natural fix is to expose typed accessors on Context<P> that dispatch to those interfaces.
Proposed API additions on Context<P>
<R> Optional<R> getSecondaryResource(
Class<R> expectedType, String eventSourceName, String name, String namespace);
default <R> Optional<R> getSecondaryResource(
Class<R> expectedType, String eventSourceName, String name) {
return getSecondaryResource(
expectedType, eventSourceName, name,
getPrimaryResource().getMetadata().getNamespace());
}
<R> Stream<R> getSecondaryResourcesAsStream(Class<R> expectedType, String eventSourceName);
Semantics:
- Single-resource by name and namespace: dispatch to
Cache<R>.get(ResourceID) when the event source implements Cache<R> (direct cache lookup, read-cache-after-write consistent). Otherwise fall back to EventSource.getSecondaryResources(primary) filtered by ResourceID. ResourceID stays an implementation detail.
- Single-resource by name (default method): convenience that uses the primary resource's namespace. Documented caveat: for cluster-scoped primaries (no namespace) the lookup is cluster-scoped; use the four-arg overload to target a specific namespace.
- Stream by event source: dispatch to
ResourceCache<R>.list(namespace) when the event source implements ResourceCache<R> (read-cache-after-write consistent). For cluster-scoped primaries (null namespace) falls back to Cache.list() to avoid an NPE in InformerWrapper.list. Otherwise falls back to eventSource.getSecondaryResources(primary).stream().
NoEventSourceForClassException handling mirrors the existing getSecondaryResource(Class, String): rethrow unless eventSourceName == null and the type is part of a managed workflow, in which case return an empty result.
Validated end-to-end against a real consumer; PR includes the API + tests, downstream migration verified separately (119 ITs passing).
Status
PR #3373 is open, targeting the next branch for the next minor release. After the first review round (csviri, 2026-05-22) the original (Class, String eventSourceName, ResourceID) signature was replaced with (Class, String eventSourceName, String name, String namespace) to keep ResourceID out of the public Context API surface.
Summary
Revisit #1410 ("Access secondary resources by ResourceID") now that
ResourceDiscriminatorsare gone. Add typed by-name accessors onContext<P>so reconcilers can look up secondary resources scoped to a specific event source without dropping toeventSourceRetriever().getEventSourceFor(...)and casting.Motivation
When a reconciler watches external secondary resources via a named event source (e.g.
ConfigMaps referenced from a custom resource's spec), today's options onContext<P>are:getSecondaryResource(Class, String eventSourceName)returns the single linked resource. No by-name lookup.getSecondaryResourcesAsStream(Class, boolean deduplicate)returns all secondary resources of the type across all event sources. No event-source scoping.context.eventSourceRetriever().getEventSourceFor(...), cast toInformerEventSource, then call.get(ResourceID). Works, but ad-hoc.#1410 acknowledged this back in 2022 and the chosen mechanism (
ResourceDiscriminators) was later removed in #2253, leaving the gap unfilled.With PR #3345 having landed (
Cache<T>/ResourceCache<T>interfaces, read-cache-after-write consistent), the natural fix is to expose typed accessors onContext<P>that dispatch to those interfaces.Proposed API additions on
Context<P>Semantics:
Cache<R>.get(ResourceID)when the event source implementsCache<R>(direct cache lookup, read-cache-after-write consistent). Otherwise fall back toEventSource.getSecondaryResources(primary)filtered byResourceID.ResourceIDstays an implementation detail.ResourceCache<R>.list(namespace)when the event source implementsResourceCache<R>(read-cache-after-write consistent). For cluster-scoped primaries (null namespace) falls back toCache.list()to avoid an NPE inInformerWrapper.list. Otherwise falls back toeventSource.getSecondaryResources(primary).stream().NoEventSourceForClassExceptionhandling mirrors the existinggetSecondaryResource(Class, String): rethrow unlesseventSourceName == nulland the type is part of a managed workflow, in which case return an empty result.Validated end-to-end against a real consumer; PR includes the API + tests, downstream migration verified separately (119 ITs passing).
Status
PR #3373 is open, targeting the
nextbranch for the next minor release. After the first review round (csviri, 2026-05-22) the original(Class, String eventSourceName, ResourceID)signature was replaced with(Class, String eventSourceName, String name, String namespace)to keepResourceIDout of the publicContextAPI surface.