Skip to content

Typed by-name secondary resource accessors on Context #3372

@afalhambra-hivemq

Description

@afalhambra-hivemq

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:

  1. getSecondaryResource(Class, String eventSourceName) returns the single linked resource. No by-name lookup.
  2. getSecondaryResourcesAsStream(Class, boolean deduplicate) returns all secondary resources of the type across all event sources. No event-source scoping.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions