-
Notifications
You must be signed in to change notification settings - Fork 73
✨ Support explicit pkg.Release field with build metadata fallback for bundle comparison #2543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
199f9cc
85c337b
477accb
a199aaf
7931651
0788808
19ccfa7
d568b20
8d6dda3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import ( | |
| "github.com/operator-framework/operator-registry/alpha/declcfg" | ||
|
|
||
| "github.com/operator-framework/operator-controller/internal/operator-controller/bundleutil" | ||
| "github.com/operator-framework/operator-controller/internal/operator-controller/features" | ||
| slicesutil "github.com/operator-framework/operator-controller/internal/shared/util/slices" | ||
| ) | ||
|
|
||
|
|
@@ -39,9 +40,27 @@ func newMastermindsRange(versionRange string) (bsemver.Range, error) { | |
| } | ||
|
|
||
| // ByVersionAndRelease is a comparison function that compares bundles by | ||
| // version and release. Bundles with lower versions/releases are | ||
| // considered less than bundles with higher versions/releases. | ||
| // version and release. When the BundleReleaseSupport feature gate is | ||
| // enabled, it uses Bundle.Compare() (which reads pkg.Release from olm.package) | ||
| // and falls back to build metadata comparison if equal. When disabled, it uses | ||
| // version+release from build metadata (backward compatible). | ||
rashmigottipati marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| func ByVersionAndRelease(b1, b2 declcfg.Bundle) int { | ||
| if features.OperatorControllerFeatureGate.Enabled(features.BundleReleaseSupport) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change feels off to me. It seems like this function shouldn't change at all. The change, as I understand it, boils down to how we build a version/release. Without the feature gate: Only do it the legacy way by inspecting/parsing build metadata With the feature gate: If release field is set, parse it directly. Only if unset do we fall back to legacy registry+v1 build metadata parsing. But then once we have a VersionRelease, the comparison is the same. Am I missing something else?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe the thing I'm missing is:
These represent the same exact concept, and we're trying to move in the direction of using the operator-registry variant? IMO, we shouldn't mix them. We should pick one and delete the other.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I completely agree that we need to consolidate to a single representative type.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So WDYT about this PR focusing on "if release explicitly set, load it into
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems reasonable to me. |
||
| // Use CompositeVersion comparison (reads pkg.Release from olm.package). | ||
| // Note: Bundle.Compare() returns 0 in three cases: | ||
| // 1. Bundle names are identical | ||
| // 2. Versions and releases are equal | ||
| // 3. Parsing errors occur (silently swallowed) | ||
| // Catalog validation should catch malformed versions before they reach this code. | ||
| result := b2.Compare(&b1) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comparing at the bundle level seems incorrect to me based on the name of this function. What if the bundle comparison method considers more than the version and release? Seems like we'd want |
||
| if result != 0 { | ||
| return result | ||
| } | ||
rashmigottipati marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // If CompositeVersion comparison is equal, fall back to version+release comparison | ||
| return compareByVersionRelease(b1, b2) | ||
| } | ||
rashmigottipati marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Default: use version+release from build metadata (backward compatible) | ||
| vr1, err1 := bundleutil.GetVersionAndRelease(b1) | ||
| vr2, err2 := bundleutil.GetVersionAndRelease(b2) | ||
|
|
||
|
|
@@ -54,6 +73,20 @@ func ByVersionAndRelease(b1, b2 declcfg.Bundle) int { | |
| return vr2.Compare(*vr1) | ||
| } | ||
|
|
||
| // compareByVersionRelease compares bundles using GetVersionAndRelease, which | ||
| // returns version+release from either explicit pkg.Release field (when feature gate | ||
| // enabled and field present) or build metadata (legacy registry+v1 fallback). | ||
| // This is used as a fallback when CompositeVersion comparison returns equal. | ||
| func compareByVersionRelease(b1, b2 declcfg.Bundle) int { | ||
| vr1, err1 := bundleutil.GetVersionAndRelease(b1) | ||
| vr2, err2 := bundleutil.GetVersionAndRelease(b2) | ||
|
|
||
rashmigottipati marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if err1 != nil || err2 != nil { | ||
| return compareErrors(err2, err1) | ||
| } | ||
| return vr2.Compare(*vr1) | ||
| } | ||
|
|
||
| func ByDeprecationFunc(deprecation declcfg.Deprecation) func(a, b declcfg.Bundle) int { | ||
| deprecatedBundles := sets.New[string]() | ||
| for _, entry := range deprecation.Entries { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,19 +20,22 @@ func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Chann | |
| // registry+v1 and embed release in build metadata. | ||
| installedVersionRelease, err := bundle.NewLegacyRegistryV1VersionRelease(installedBundle.Version) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to get version and release of installed bundle: %v", err) | ||
| return nil, fmt.Errorf("failed to get version and release of installed bundle: %w", err) | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this section of code also need to change similar to If we resolve a bundle in the catalog that has an explicit release field, we'll install it, but we don't persist it's release value anywhere. Later (here) it'll show up as TL;DR: I think this PR needs to also add a new field to the |
||
|
|
||
| successorsPredicate, err := legacySuccessor(installedBundle, channels...) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("getting successorsPredicate: %w", err) | ||
| } | ||
|
|
||
| // We need either successors or current version (no upgrade) | ||
| return filter.Or( | ||
| // Bundle matches if it's a channel successor or current version (no upgrade). | ||
| // Re-releases must have explicit channel entries to be valid successors. | ||
| predicates := []filter.Predicate[declcfg.Bundle]{ | ||
| successorsPredicate, | ||
| ExactVersionRelease(*installedVersionRelease), | ||
| ), nil | ||
| } | ||
|
|
||
| return filter.Or(predicates...), nil | ||
grokspawn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| func legacySuccessor(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (filter.Predicate[declcfg.Bundle], error) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.