Skip to content

Commit a25a218

Browse files
Merge pull request #1725 from benluddy/fix-subscription-without-channel
Bug 1868497: Fix install plan creation for subscriptions that omit channel.
2 parents 6e748e0 + 3b086a7 commit a25a218

File tree

4 files changed

+64
-68
lines changed

4 files changed

+64
-68
lines changed

pkg/controller/registry/resolver/installabletypes.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,5 @@ func (r SubscriptionInstallable) Constraints() []solver.Constraint {
7777
func (r *SubscriptionInstallable) AddDependency(dependencies []solver.Identifier) {
7878
if len(dependencies) > 0 {
7979
r.constraints = append(r.constraints, solver.Dependency(dependencies...))
80-
// "dependencies" may contain bundles that are not mutually exclusive
81-
// currently, the constraint types:
82-
// - packagename+version range
83-
// - provided gvk
84-
// - ANDs of either of the above
85-
// all happen to be mutually exclusive, but this won't always be the case
86-
r.constraints = append(r.constraints, solver.AtMost(1, dependencies...))
8780
}
8881
}

pkg/controller/registry/resolver/resolver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type debugWriter struct {
3838

3939
func (w *debugWriter) Write(b []byte) (int, error) {
4040
n := len(b)
41-
w.Debug(b)
41+
w.Debug(string(b))
4242
return n, nil
4343
}
4444

pkg/controller/registry/resolver/step_resolver.go

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,6 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
8585
return nil, nil, nil, err
8686
}
8787

88-
// create a map of operatorsourceinfo (subscription+catalogsource data) to the original subscriptions
89-
subMap := r.sourceInfoToSubscriptions(subs)
90-
// get a list of new operators to add to the generation
91-
add := r.sourceInfoForNewSubscriptions(namespace, subMap)
92-
9388
var operators OperatorSet
9489
namespaces := []string{namespace, r.globalCatalogNamespace}
9590
operators, err = r.satResolver.SolveOperators(namespaces, csvs, subs)
@@ -103,21 +98,36 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
10398
updatedSubs := []*v1alpha1.Subscription{}
10499
bundleLookups := []v1alpha1.BundleLookup{}
105100
for name, op := range operators {
106-
// TODO: added "is default channel" to sourceinfo out
107-
// of convenience, which breaks map key equality here
108-
// because it requires information that can't be
109-
// gleaned from subscriptions alone. need to revisit
110-
// TODO: this check also doesn't properly account for
111-
// subscriptions made without a catalog specified,
112-
// which means the sourceinfo won't match for the
113-
// realized operator
101+
// Find an existing subscription that resolves to this operator.
102+
var (
103+
existingSubscription *v1alpha1.Subscription
104+
alreadyExists bool
105+
)
114106
sourceInfo := *op.SourceInfo()
115-
sourceInfo.DefaultChannel = false
116-
_, isAdded := add[sourceInfo]
117-
existingSubscription, subExists := subMap[sourceInfo]
107+
for _, sub := range subs {
108+
if sub.Spec.Package != sourceInfo.Package {
109+
continue
110+
}
111+
if sub.Spec.Channel != "" && sub.Spec.Channel != sourceInfo.Channel {
112+
continue
113+
}
114+
subCatalogKey := registry.CatalogKey{
115+
Name: sub.Spec.CatalogSource,
116+
Namespace: sub.Spec.CatalogSourceNamespace,
117+
}
118+
if !subCatalogKey.Empty() && !subCatalogKey.Equal(sourceInfo.Catalog) {
119+
continue
120+
}
121+
alreadyExists, err = r.hasExistingCurrentCSV(sub)
122+
if err != nil {
123+
return nil, nil, nil, fmt.Errorf("unable to determine whether subscription has a preexisting CSV")
124+
}
125+
existingSubscription = sub
126+
break
127+
}
118128

119129
// subscription exists and is up to date
120-
if subExists && existingSubscription.Status.CurrentCSV == op.Identifier() && !isAdded {
130+
if existingSubscription != nil && existingSubscription.Status.CurrentCSV == op.Identifier() && alreadyExists {
121131
continue
122132
}
123133

@@ -155,7 +165,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
155165
})
156166
}
157167

158-
if !subExists {
168+
if existingSubscription == nil {
159169
// explicitly track the resolved CSV as the starting CSV on the resolved subscriptions
160170
op.SourceInfo().StartingCSV = op.Identifier()
161171
subStep, err := NewSubscriptionStepResource(namespace, *op.SourceInfo())
@@ -171,7 +181,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
171181
}
172182

173183
// add steps for subscriptions for bundles that were added through resolution
174-
if subExists && existingSubscription.Status.CurrentCSV != op.Identifier() {
184+
if existingSubscription != nil && existingSubscription.Status.CurrentCSV != op.Identifier() {
175185
// update existing subscription status
176186
existingSubscription.Status.CurrentCSV = op.Identifier()
177187
updatedSubs = append(updatedSubs, existingSubscription)
@@ -183,56 +193,30 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
183193
return steps, bundleLookups, updatedSubs, nil
184194
}
185195

186-
func (r *OperatorStepResolver) sourceInfoForNewSubscriptions(namespace string, subs map[OperatorSourceInfo]*v1alpha1.Subscription) (add map[OperatorSourceInfo]struct{}) {
187-
add = make(map[OperatorSourceInfo]struct{})
188-
for key, sub := range subs {
189-
if sub.Status.CurrentCSV == "" {
190-
add[key] = struct{}{}
191-
continue
192-
}
193-
csv, err := r.csvLister.ClusterServiceVersions(namespace).Get(sub.Status.CurrentCSV)
194-
if csv == nil || errors.IsNotFound(err) {
195-
add[key] = struct{}{}
196-
}
196+
func (r *OperatorStepResolver) hasExistingCurrentCSV(sub *v1alpha1.Subscription) (bool, error) {
197+
if sub.Status.CurrentCSV == "" {
198+
return false, nil
197199
}
198-
return
199-
}
200-
201-
func (r *OperatorStepResolver) sourceInfoToSubscriptions(subs []*v1alpha1.Subscription) (add map[OperatorSourceInfo]*v1alpha1.Subscription) {
202-
add = make(map[OperatorSourceInfo]*v1alpha1.Subscription)
203-
var sourceNamespace string
204-
for _, s := range subs {
205-
startingCSV := s.Spec.StartingCSV
206-
if s.Status.CurrentCSV != "" {
207-
// If a csv has previously been resolved for the operator, don't enable
208-
// a starting csv search.
209-
startingCSV = ""
210-
}
211-
if s.Spec.CatalogSourceNamespace == "" {
212-
sourceNamespace = s.GetNamespace()
213-
} else {
214-
sourceNamespace = s.Spec.CatalogSourceNamespace
215-
}
216-
add[OperatorSourceInfo{
217-
Package: s.Spec.Package,
218-
Channel: s.Spec.Channel,
219-
StartingCSV: startingCSV,
220-
Catalog: registry.CatalogKey{Name: s.Spec.CatalogSource, Namespace: sourceNamespace},
221-
}] = s.DeepCopy()
200+
_, err := r.csvLister.ClusterServiceVersions(sub.GetNamespace()).Get(sub.Status.CurrentCSV)
201+
if err == nil {
202+
return true, nil
203+
}
204+
if errors.IsNotFound(err) {
205+
return false, nil
222206
}
223-
return
207+
return false, err // Can't answer this question right now.
224208
}
225209

226-
func (r *OperatorStepResolver) listSubscriptions(namespace string) (subs []*v1alpha1.Subscription, err error) {
210+
func (r *OperatorStepResolver) listSubscriptions(namespace string) ([]*v1alpha1.Subscription, error) {
227211
list, err := r.client.OperatorsV1alpha1().Subscriptions(namespace).List(context.TODO(), metav1.ListOptions{})
228212
if err != nil {
229-
return
213+
return nil, err
230214
}
231215

232-
subs = make([]*v1alpha1.Subscription, 0)
216+
var subs []*v1alpha1.Subscription
233217
for i := range list.Items {
234218
subs = append(subs, &list.Items[i])
235219
}
236220

237-
return
221+
return subs, nil
238222
}

pkg/controller/registry/resolver/step_resolver_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,33 @@ type resolverTestOut struct {
6262
}
6363

6464
func SharedResolverSpecs() []resolverTest {
65-
namespace := "catsrc-namespace"
65+
const namespace = "catsrc-namespace"
6666
catalog := registry.CatalogKey{Name: "catsrc", Namespace: namespace}
6767
nothing := resolverTestOut{
6868
steps: [][]*v1alpha1.Step{},
6969
lookups: []v1alpha1.BundleLookup{},
7070
subs: []*v1alpha1.Subscription{},
7171
}
7272
return []resolverTest{
73+
{
74+
name: "SubscriptionOmitsChannel",
75+
clusterState: []runtime.Object{
76+
newSub(namespace, "package", "", catalog),
77+
},
78+
bundlesByCatalog: map[registry.CatalogKey][]*api.Bundle{
79+
catalog: {
80+
bundle("bundle", "package", "channel", "", nil, nil, nil, nil),
81+
},
82+
},
83+
out: resolverTestOut{
84+
steps: [][]*v1alpha1.Step{
85+
bundleSteps(bundle("bundle", "package", "channel", "", nil, nil, nil, nil), namespace, "", catalog),
86+
},
87+
subs: []*v1alpha1.Subscription{
88+
updatedSub(namespace, "bundle", "", "package", "", catalog),
89+
},
90+
},
91+
},
7392
{
7493
name: "SingleNewSubscription/NoDeps",
7594
clusterState: []runtime.Object{

0 commit comments

Comments
 (0)