@@ -101,7 +101,7 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust
101
101
}
102
102
103
103
// find operators, in channel order, that can skip from the current version or list the current in "replaces"
104
- subInstallables , err := r .getSubscriptionInstallables (pkg , current , catalog , predicates , channelFilter , namespacedCache , visited )
104
+ subInstallables , err := r .getSubscriptionInstallables (pkg , sub . Namespace , current , catalog , predicates , channelFilter , namespacedCache , visited )
105
105
if err != nil {
106
106
errs = append (errs , err )
107
107
continue
@@ -122,7 +122,7 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust
122
122
if len (errs ) > 0 {
123
123
return nil , utilerrors .NewAggregate (errs )
124
124
}
125
- s , err := solver .New (solver .WithInput (input ), solver .WithTracer (solver.LoggingTracer {& debugWriter {r .log }}))
125
+ s , err := solver .New (solver .WithInput (input ), solver .WithTracer (solver.LoggingTracer {Writer : & debugWriter {r .log }}))
126
126
if err != nil {
127
127
return nil , err
128
128
}
@@ -135,6 +135,14 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust
135
135
operatorInstallables := make ([]BundleInstallable , 0 )
136
136
for _ , installable := range solvedInstallables {
137
137
if bundleInstallable , ok := installable .(* BundleInstallable ); ok {
138
+ _ , _ , catalog , err := bundleInstallable .BundleSourceInfo ()
139
+ if err != nil {
140
+ return nil , fmt .Errorf ("error determining origin of operator: %w" , err )
141
+ }
142
+ if catalog .Virtual () {
143
+ // Result is expected to contain only new things.
144
+ continue
145
+ }
138
146
operatorInstallables = append (operatorInstallables , * bundleInstallable )
139
147
}
140
148
}
@@ -171,7 +179,7 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust
171
179
return operators , nil
172
180
}
173
181
174
- func (r * SatResolver ) getSubscriptionInstallables (pkg string , current * Operator , catalog registry.CatalogKey , cachePredicates []OperatorPredicate , channelPredicates []OperatorPredicate , namespacedCache MultiCatalogOperatorFinder , visited map [OperatorSurface ]* BundleInstallable ) (map [solver.Identifier ]solver.Installable , error ) {
182
+ func (r * SatResolver ) getSubscriptionInstallables (pkg , namespace string , current * Operator , catalog registry.CatalogKey , cachePredicates []OperatorPredicate , channelPredicates []OperatorPredicate , namespacedCache MultiCatalogOperatorFinder , visited map [OperatorSurface ]* BundleInstallable ) (map [solver.Identifier ]solver.Installable , error ) {
175
183
installables := make (map [solver.Identifier ]solver.Installable , 0 )
176
184
candidates := make ([]* BundleInstallable , 0 )
177
185
@@ -180,12 +188,6 @@ func (r *SatResolver) getSubscriptionInstallables(pkg string, current *Operator,
180
188
181
189
bundles := namespacedCache .Catalog (catalog ).Find (cachePredicates ... )
182
190
183
- // there are no options for this package, return early
184
- if len (bundles ) == 0 {
185
- // should this condition fail resolution altogether?
186
- return installables , nil
187
- }
188
-
189
191
// bundles in the default channel appear first, then lexicographically order by channel name
190
192
sort .SliceStable (bundles , func (i , j int ) bool {
191
193
var idef bool
@@ -243,9 +245,19 @@ func (r *SatResolver) getSubscriptionInstallables(pkg string, current *Operator,
243
245
// track which operator this is replacing, so that it can be realized when creating the resources on cluster
244
246
if current != nil {
245
247
c .Replaces = current .Identifier ()
248
+ // Until properties are projected onto CSVs,
249
+ // an installed operator can't be confidently
250
+ // folded into the existing package uniqueness
251
+ // constraints, so for the replacement case, a
252
+ // one-to-one conflict is created between the
253
+ // replacer and the replacee.
254
+ c .AddConflict (bundleId (current .Identifier (), current .Channel (), registry .NewVirtualCatalogKey (namespace )))
246
255
}
247
256
depIds = append (depIds , c .Identifier ())
248
257
}
258
+ if current != nil {
259
+ depIds = append (depIds , bundleId (current .Identifier (), current .Channel (), registry .NewVirtualCatalogKey (namespace )))
260
+ }
249
261
250
262
// all candidates added as options for this constraint
251
263
subInstallable .AddDependency (depIds )
@@ -363,8 +375,12 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1
363
375
}
364
376
standaloneOperators := make ([]* Operator , 0 )
365
377
for _ , csv := range csvs {
366
- if _ , ok := csvsWithSubscriptions [csv ]; ok {
367
- continue
378
+ var constraints []solver.Constraint
379
+ if _ , ok := csvsWithSubscriptions [csv ]; ! ok {
380
+ // CSVs already associated with a Subscription
381
+ // may be replaced, but freestanding CSVs must
382
+ // appear in any solution.
383
+ constraints = append (constraints , solver .Mandatory ())
368
384
}
369
385
370
386
op , err := NewOperatorFromV1Alpha1CSV (csv )
@@ -377,7 +393,7 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1
377
393
standaloneOperators = append (standaloneOperators , op )
378
394
379
395
// all standalone operators are mandatory
380
- i := NewBundleInstallable (op .Identifier (), "" , existingOperatorCatalog , solver . Mandatory () )
396
+ i := NewBundleInstallable (op .Identifier (), "" , existingOperatorCatalog , constraints ... )
381
397
installables = append (installables , & i )
382
398
}
383
399
0 commit comments