44 "context"
55 "fmt"
66 "slices"
7+ "sort"
78
89 mmsemver "github.com/Masterminds/semver/v3"
910 bsemver "github.com/blang/semver/v4"
@@ -50,9 +51,14 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1alpha1.ClusterEx
5051 }
5152 }
5253
54+ type foundBundle struct {
55+ bundle * declcfg.Bundle
56+ catalog string
57+ priority int32
58+ }
59+
60+ resolvedBundles := []foundBundle {}
5361 var (
54- resolvedBundles []* declcfg.Bundle
55- matchedCatalogs []string
5662 priorDeprecation * declcfg.Deprecation
5763 )
5864
@@ -114,33 +120,47 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1alpha1.ClusterEx
114120 if len (resolvedBundles ) != 0 {
115121 // We've already found one or more package candidates
116122 currentIsDeprecated := isDeprecated (thisBundle , thisDeprecation )
117- priorIsDeprecated := isDeprecated (* resolvedBundles [len (resolvedBundles )- 1 ], priorDeprecation )
123+ priorIsDeprecated := isDeprecated (* resolvedBundles [len (resolvedBundles )- 1 ]. bundle , priorDeprecation )
118124 if currentIsDeprecated && ! priorIsDeprecated {
119125 // Skip this deprecated package and retain the non-deprecated package(s)
120126 return nil
121127 } else if ! currentIsDeprecated && priorIsDeprecated {
122128 // Our package candidates so far were deprecated and this one is not; clear the lists
123- resolvedBundles = []* declcfg.Bundle {}
124- matchedCatalogs = []string {}
129+ resolvedBundles = []foundBundle {}
125130 }
126131 }
127132 // The current bundle shares deprecation status with prior bundles or
128133 // there are no prior bundles. Add it to the list.
129- resolvedBundles = append (resolvedBundles , & thisBundle )
130- matchedCatalogs = append (matchedCatalogs , cat .GetName ())
134+ resolvedBundles = append (resolvedBundles , foundBundle {& thisBundle , cat .GetName (), cat .Spec .Priority })
131135 priorDeprecation = thisDeprecation
132136 return nil
133137 }, listOptions ... ); err != nil {
134138 return nil , nil , nil , fmt .Errorf ("error walking catalogs: %w" , err )
135139 }
136140
141+ // Resolve for priority
142+ if len (resolvedBundles ) > 1 {
143+ // Want highest first (reverse sort)
144+ sort .Slice (resolvedBundles , func (i , j int ) bool { return resolvedBundles [i ].priority > resolvedBundles [j ].priority })
145+ // If the top two bundles do not have the same priority, then priority breaks the tie
146+ // Reduce resolvedBundles to just the first item (highest priority)
147+ if resolvedBundles [0 ].priority != resolvedBundles [1 ].priority {
148+ resolvedBundles = []foundBundle {resolvedBundles [0 ]}
149+ }
150+ }
151+
152+ // Check for ambiguity
137153 if len (resolvedBundles ) != 1 {
138154 errPrefix := ""
139155 if installedBundle != nil {
140156 errPrefix = fmt .Sprintf ("error upgrading from currently installed version %q: " , installedBundle .Version )
141157 }
142158 switch {
143159 case len (resolvedBundles ) > 1 :
160+ matchedCatalogs := []string {}
161+ for _ , r := range resolvedBundles {
162+ matchedCatalogs = append (matchedCatalogs , r .catalog )
163+ }
144164 slices .Sort (matchedCatalogs ) // sort for consistent error message
145165 return nil , nil , nil , fmt .Errorf ("%smatching packages found in multiple catalogs: %v" , errPrefix , matchedCatalogs )
146166 case versionRange != "" && channelName != "" :
@@ -153,7 +173,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1alpha1.ClusterEx
153173 return nil , nil , nil , fmt .Errorf ("%sno package %q found" , errPrefix , packageName )
154174 }
155175 }
156- resolvedBundle := resolvedBundles [0 ]
176+ resolvedBundle := resolvedBundles [0 ]. bundle
157177 resolvedBundleVersion , err := bundleutil .GetVersion (* resolvedBundle )
158178 if err != nil {
159179 return nil , nil , nil , fmt .Errorf ("error getting resolved bundle version for bundle %q: %w" , resolvedBundle .Name , err )
0 commit comments