Summary
Revisit #1410 ("Access secondary resources by ResourceID") now that ResourceDiscriminators are gone with JOSDK 5. Add typed by-name accessors on Context<P> so reconcilers can look up secondary resources scoped to a specific event source by ResourceID (or by name, with the primary's namespace) 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, ResourceID resourceID);
default <R> Optional<R> getSecondaryResource(Class<R> expectedType, String eventSourceName, String name) {
return getSecondaryResource(expectedType, eventSourceName,
new ResourceID(name, getPrimaryResource().getMetadata().getNamespace()));
}
<R> Stream<R> getSecondaryResourcesAsStream(Class<R> expectedType, String eventSourceName);
Semantics:
- Single-resource by
ResourceID: 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) with a ResourceID filter.
- Single-resource by
name (default method): convenience that builds a ResourceID from name plus the primary's namespace. Documented caveat: for cluster-scoped primaries (no namespace) the lookup is cluster-scoped; use the ResourceID overload to target a specific namespace.
- Stream by event source: dispatch to
ResourceCache<R>.list(namespace, Cache.TRUE) when the event source implements ResourceCache<R> (read-cache-after-write consistent). For cluster-scoped primaries (null namespace) falls back to Cache.list(Cache.TRUE) 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.
PR open: #3373
Summary
Revisit #1410 ("Access secondary resources by ResourceID") now that
ResourceDiscriminatorsare gone with JOSDK 5. Add typed by-name accessors onContext<P>so reconcilers can look up secondary resources scoped to a specific event source byResourceID(or by name, with the primary's namespace) 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:
ResourceID: dispatch toCache<R>.get(ResourceID)when the event source implementsCache<R>(direct cache lookup, read-cache-after-write consistent). Otherwise fall back toEventSource.getSecondaryResources(primary)with aResourceIDfilter.name(default method): convenience that builds aResourceIDfromnameplus the primary's namespace. Documented caveat: for cluster-scoped primaries (no namespace) the lookup is cluster-scoped; use theResourceIDoverload to target a specific namespace.ResourceCache<R>.list(namespace, Cache.TRUE)when the event source implementsResourceCache<R>(read-cache-after-write consistent). For cluster-scoped primaries (null namespace) falls back toCache.list(Cache.TRUE)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.PR open: #3373