Skip to content

Bind package resolution to the highest-priority catalog containing the package #3043

Closed

Description

@joelanford

Problem

Today the catalog resolver filters each catalog's bundles by channel, version, and upgrade constraints before comparing catalog priorities. If a high-priority catalog contains the requested package but has no eligible bundle, a lower-priority catalog can supply an install or update. This can install content from a catalog the user did not intend to use.

Same-priority ambiguity is currently detected only among surviving bundle candidates, not among catalogs containing the package. Deprecation preference is also applied across catalogs before priority, and the returned deprecation pointer may come from a different catalog than the winning bundle. See internal/operator-controller/resolve/catalog.go (particularly the filtering at lines 92-125, deprecation comparison at 148-163, priority at 169-178, and return at 207-208).

This request implements package-level catalog precedence. Related historical discussion: #1023, which raised the option of resolving from the highest-priority catalog containing a package.

Proposed resolution order

  1. Apply the ClusterExtension catalog selector and exclude unavailable ClusterCatalogs, as today. Group the remaining catalogs by spec.priority, highest first.
  2. For each priority group, determine whether the requested package is present in each catalog. Presence must be based on package metadata, not on whether a bundle survives selection filters. Evaluate the entire group before deciding.
  3. If more than one catalog in that group contains the package, fail with a same-priority package ambiguity error. Do not use version, channel, upgrade edges, deprecation, or bundle validity to break this tie. List conflicting catalog names deterministically.
  4. If exactly one catalog in that group contains the package, select it and run all follow-on bundle resolution only against that catalog. If its bundles cannot satisfy the request or fail validation, return an error. Do not consult a lower-priority catalog for an alternative bundle.
  5. If no catalog in that group contains the package, continue to the next group. If none contains it, report that the package was not found.

A package lookup or metadata-loading error is not evidence of absence. Fail closed rather than falling through to a lower-priority group when presence in the current group cannot be determined. Once an owner is selected, lower-priority groups do not need to be queried.

Examples

Highest-priority group Lower-priority group Expected result
Package absent One catalog has package Select lower-priority catalog
One catalog has package, but requested version or channel is absent Matching bundle exists Fail within selected catalog
Two catalogs have package, but only one has an eligible bundle Any contents Fail due to same-priority package ambiguity
One catalog has package, but its eligible bundles are deprecated Non-deprecated bundle exists Resolve within selected higher-priority catalog
Package lookup fails Matching bundle exists Fail without falling through

Deprecation and errors

  • Deprecation information must come only from the selected catalog, including when bundle resolution fails after catalog selection. A lower-priority catalog's metadata must not affect selection or status.
  • Distinguish "selected catalog data is available, but contains no deprecations" from "catalog data is unavailable." The controller currently uses err == nil || resolvedDeprecation != nil as its availability check (internal/operator-controller/controllers/clusterextension_reconcile_steps.go), which cannot distinguish those cases on a bundle resolution error. Adjust the resolver/controller contract as needed so conditions can accurately reflect known metadata even without an eligible bundle.
  • When package ownership is ambiguous or cannot be established, do not attribute deprecation metadata to an arbitrary catalog.
  • Make errors distinguish package not found, same-priority package ambiguity, and no eligible bundle in the selected catalog. Include the selected catalog name for the latter.

Acceptance criteria

  • Tests cover: higher-priority package presence blocking fallback for version, channel, upgrade-edge, and validation failures; absence allowing the next group; same-priority ambiguity even when only one catalog has an eligible or non-deprecated bundle; lookup errors failing closed; and deprecation data coming exclusively from the selected catalog, including on bundle resolution failure.
  • Same-priority ambiguity errors list only the conflicting catalogs at the selected priority, in stable order. Update cross-catalog test expectations such as TestPackageVariationsBetweenCatalogs and TestMultiplePriority in internal/operator-controller/resolve/catalog_test.go.
  • Update the ClusterCatalog priority API description and docs/concepts/controlling-catalog-selection.md to describe package-first precedence rather than priority among catalogs with matching bundles.

Scope note

This rule is evaluated on each resolution. If a higher-priority catalog stops providing the package, a lower-priority catalog can then be selected. Preventing a switch in that situation would require explicit catalog selection or a separate sticky-binding policy. This is distinct from the controller's existing fallback to the installed bundle when catalogs are deleted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kind/featureCategorizes issue or PR as related to a new feature.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions