diff --git a/internal/operator-controller/resolve/catalog.go b/internal/operator-controller/resolve/catalog.go index f0d4da6fab..b213c480d5 100644 --- a/internal/operator-controller/resolve/catalog.go +++ b/internal/operator-controller/resolve/catalog.go @@ -181,12 +181,14 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio // Check for ambiguity if len(resolvedBundles) != 1 { l.Info("resolution failed", "stats", catStats) + upgradePolicyEnforced := ext.Spec.Source.Catalog.UpgradeConstraintPolicy != ocv1.UpgradeConstraintPolicySelfCertified && installedBundle != nil return nil, nil, nil, resolutionError{ - PackageName: packageName, - Version: versionRange, - Channels: channels, - InstalledBundle: installedBundle, - ResolvedBundles: resolvedBundles, + PackageName: packageName, + Version: versionRange, + Channels: channels, + InstalledBundle: installedBundle, + ResolvedBundles: resolvedBundles, + UpgradePolicyEnforced: upgradePolicyEnforced, } } resolvedBundle := resolvedBundles[0].bundle @@ -210,11 +212,12 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio } type resolutionError struct { - PackageName string - Version string - Channels []string - InstalledBundle *ocv1.BundleMetadata - ResolvedBundles []foundBundle + PackageName string + Version string + Channels []string + InstalledBundle *ocv1.BundleMetadata + ResolvedBundles []foundBundle + UpgradePolicyEnforced bool } func (rei resolutionError) Error() string { @@ -223,6 +226,21 @@ func (rei resolutionError) Error() string { sb.WriteString(fmt.Sprintf("error upgrading from currently installed version %q: ", rei.InstalledBundle.Version)) } + // When upgrade policy is enforced and no bundles were found, provide a clearer message + // indicating that the version doesn't match any successor + if rei.UpgradePolicyEnforced && len(rei.ResolvedBundles) == 0 { + sb.WriteString(fmt.Sprintf("desired package %q ", rei.PackageName)) + if rei.Version != "" { + sb.WriteString(fmt.Sprintf("with version range %q ", rei.Version)) + } + sb.WriteString(fmt.Sprintf("does not match any successor of %q", rei.InstalledBundle.Version)) + if len(rei.Channels) > 0 { + sb.WriteString(fmt.Sprintf(" in channels %v", rei.Channels)) + } + return sb.String() + } + + // Default error message for other scenarios if len(rei.ResolvedBundles) > 1 { sb.WriteString(fmt.Sprintf("found bundles for package %q ", rei.PackageName)) } else { diff --git a/internal/operator-controller/resolve/catalog_test.go b/internal/operator-controller/resolve/catalog_test.go index 2ec3192b69..832a2be611 100644 --- a/internal/operator-controller/resolve/catalog_test.go +++ b/internal/operator-controller/resolve/catalog_test.go @@ -471,7 +471,7 @@ func TestUpgradeNotFoundLegacy(t *testing.T) { } // 0.1.0 only upgrades to 1.0.x with its legacy upgrade edges, so this fails. _, _, _, err := r.Resolve(context.Background(), ce, installedBundle) - assert.EqualError(t, err, fmt.Sprintf(`error upgrading from currently installed version "0.1.0": no bundles found for package %q matching version "<1.0.0 >=2.0.0"`, pkgName)) + assert.EqualError(t, err, fmt.Sprintf(`error upgrading from currently installed version "0.1.0": desired package %q with version range "<1.0.0 >=2.0.0" does not match any successor of "0.1.0"`, pkgName)) } func TestDowngradeFound(t *testing.T) {