Skip to content

Commit 81e7a60

Browse files
authored
Remove oudated subscription update logic to improve resolution delay (#2369)
Currently, olm logic checks for upgrade in subscription via another obsolete API that is no longer in use for dependency solution. As a result, sometimes, subscriptions display `UpgradeAvailable` status but there will be no upgrades as the upgrade is not valid in the resolver. Also, the `UpgradeAvailable` status is used to trigger the new resolution even though that status is no longer a valid indicator of having a pending upgrade. This leads to unwanted upgrade delay when the obsolete API works properly. This commit will remove the code that is using this obsolete API and allow the resolution to happen when there is a subscription change. Signed-off-by: Vu Dinh <[email protected]>
1 parent afc0848 commit 81e7a60

File tree

4 files changed

+5
-197
lines changed

4 files changed

+5
-197
lines changed

pkg/controller/operators/catalog/operator.go

+2-14
Original file line numberDiff line numberDiff line change
@@ -1044,11 +1044,6 @@ func (o *Operator) syncSubscriptions(obj interface{}) error {
10441044
}
10451045

10461046
func (o *Operator) nothingToUpdate(logger *logrus.Entry, sub *v1alpha1.Subscription) bool {
1047-
// Only sync if catalog has been updated since last sync time
1048-
if o.sourcesLastUpdate.Before(sub.Status.LastUpdated.Time) && sub.Status.State != v1alpha1.SubscriptionStateNone && sub.Status.State != v1alpha1.SubscriptionStateUpgradeAvailable {
1049-
logger.Debugf("skipping update: no new updates to catalog since last sync at %s", sub.Status.LastUpdated.String())
1050-
return true
1051-
}
10521047
if sub.Status.InstallPlanRef != nil && sub.Status.State == v1alpha1.SubscriptionStateUpgradePending {
10531048
logger.Debugf("skipping update: installplan already created")
10541049
return true
@@ -1102,7 +1097,7 @@ func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha
11021097
return sub, false, nil
11031098
}
11041099

1105-
csv, err := o.client.OperatorsV1alpha1().ClusterServiceVersions(sub.GetNamespace()).Get(context.TODO(), sub.Status.CurrentCSV, metav1.GetOptions{})
1100+
_, err := o.client.OperatorsV1alpha1().ClusterServiceVersions(sub.GetNamespace()).Get(context.TODO(), sub.Status.CurrentCSV, metav1.GetOptions{})
11061101
out := sub.DeepCopy()
11071102
if err != nil {
11081103
logger.WithError(err).WithField("currentCSV", sub.Status.CurrentCSV).Debug("error fetching csv listed in subscription status")
@@ -1112,14 +1107,7 @@ func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha
11121107
if err := querier.Queryable(); err != nil {
11131108
return nil, false, err
11141109
}
1115-
b, _, _ := querier.FindReplacement(&csv.Spec.Version.Version, sub.Status.CurrentCSV, sub.Spec.Package, sub.Spec.Channel, registry.CatalogKey{Name: sub.Spec.CatalogSource, Namespace: sub.Spec.CatalogSourceNamespace})
1116-
if b != nil {
1117-
o.logger.Tracef("replacement %s bundle found for current bundle %s", b.CsvName, sub.Status.CurrentCSV)
1118-
out.Status.State = v1alpha1.SubscriptionStateUpgradeAvailable
1119-
} else {
1120-
out.Status.State = v1alpha1.SubscriptionStateAtLatest
1121-
}
1122-
1110+
out.Status.State = v1alpha1.SubscriptionStateAtLatest
11231111
out.Status.InstalledCSV = sub.Status.CurrentCSV
11241112
}
11251113

pkg/controller/operators/catalog/querier.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type SourceRef struct {
2626
}
2727

2828
type SourceQuerier interface {
29+
// Deprecated: This FindReplacement function will be deprecated soon
2930
FindReplacement(currentVersion *semver.Version, bundleName, pkgName, channelName string, initialSource registry.CatalogKey) (*api.Bundle, *registry.CatalogKey, error)
3031
Queryable() error
3132
}
@@ -49,6 +50,7 @@ func (q *NamespaceSourceQuerier) Queryable() error {
4950
return nil
5051
}
5152

53+
// Deprecated: This FindReplacement function will be deprecated soon
5254
func (q *NamespaceSourceQuerier) FindReplacement(currentVersion *semver.Version, bundleName, pkgName, channelName string, initialSource registry.CatalogKey) (*api.Bundle, *registry.CatalogKey, error) {
5355
errs := []error{}
5456

Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
package catalog
22

33
import (
4-
"context"
5-
"encoding/json"
64
"fmt"
75
"testing"
86

9-
"github.com/blang/semver/v4"
10-
"github.com/operator-framework/operator-registry/pkg/api"
117
"github.com/operator-framework/operator-registry/pkg/client"
128
"github.com/stretchr/testify/require"
13-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
149

15-
"github.com/operator-framework/api/pkg/lib/version"
16-
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1710
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/fakes"
1811
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
1912
)
@@ -112,178 +105,3 @@ func TestNamespaceSourceQuerier_Queryable(t *testing.T) {
112105
})
113106
}
114107
}
115-
116-
func TestNamespaceSourceQuerier_FindReplacement(t *testing.T) {
117-
// TODO: clean up this test setup
118-
initialSource := fakes.FakeClientInterface{}
119-
otherSource := fakes.FakeClientInterface{}
120-
replacementSource := fakes.FakeClientInterface{}
121-
replacementAndLatestSource := fakes.FakeClientInterface{}
122-
replacementAndNoAnnotationLatestSource := fakes.FakeClientInterface{}
123-
124-
latestVersion := semver.MustParse("1.0.0-1556661308")
125-
csv := v1alpha1.ClusterServiceVersion{
126-
TypeMeta: metav1.TypeMeta{
127-
Kind: v1alpha1.ClusterServiceVersionKind,
128-
APIVersion: v1alpha1.GroupVersion,
129-
},
130-
ObjectMeta: metav1.ObjectMeta{
131-
Name: "latest",
132-
Namespace: "placeholder",
133-
Annotations: map[string]string{
134-
"olm.skipRange": ">= 1.0.0-0 < 1.0.0-1556661308",
135-
},
136-
},
137-
Spec: v1alpha1.ClusterServiceVersionSpec{
138-
CustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{
139-
Owned: []v1alpha1.CRDDescription{},
140-
Required: []v1alpha1.CRDDescription{},
141-
},
142-
APIServiceDefinitions: v1alpha1.APIServiceDefinitions{
143-
Owned: []v1alpha1.APIServiceDescription{},
144-
Required: []v1alpha1.APIServiceDescription{},
145-
},
146-
Version: version.OperatorVersion{latestVersion},
147-
},
148-
}
149-
csvJson, err := json.Marshal(csv)
150-
require.NoError(t, err)
151-
152-
nextBundle := &api.Bundle{CsvName: "test.v1", PackageName: "testPkg", ChannelName: "testChannel"}
153-
latestBundle := &api.Bundle{CsvName: "latest", PackageName: "testPkg", ChannelName: "testChannel", CsvJson: string(csvJson), Object: []string{string(csvJson)}, SkipRange: ">= 1.0.0-0 < 1.0.0-1556661308", Version: latestVersion.String()}
154-
155-
csv.SetAnnotations(map[string]string{})
156-
csvUnstNoAnnotationJson, err := json.Marshal(csv)
157-
require.NoError(t, err)
158-
latestBundleNoAnnotation := &api.Bundle{CsvName: "latest", PackageName: "testPkg", ChannelName: "testChannel", CsvJson: string(csvUnstNoAnnotationJson), Object: []string{string(csvUnstNoAnnotationJson)}}
159-
160-
initialSource.GetReplacementBundleInPackageChannelStub = func(ctx context.Context, bundleName, pkgName, channelName string) (*api.Bundle, error) {
161-
return nil, fmt.Errorf("not found")
162-
}
163-
replacementSource.GetReplacementBundleInPackageChannelStub = func(ctx context.Context, bundleName, pkgName, channelName string) (*api.Bundle, error) {
164-
return nextBundle, nil
165-
}
166-
initialSource.GetBundleInPackageChannelStub = func(ctx context.Context, pkgName, channelName string) (*api.Bundle, error) {
167-
if pkgName != latestBundle.PackageName {
168-
return nil, fmt.Errorf("not found")
169-
}
170-
return latestBundle, nil
171-
}
172-
otherSource.GetBundleInPackageChannelStub = func(ctx context.Context, pkgName, channelName string) (*api.Bundle, error) {
173-
if pkgName != latestBundle.PackageName {
174-
return nil, fmt.Errorf("not found")
175-
}
176-
return latestBundle, nil
177-
}
178-
replacementAndLatestSource.GetReplacementBundleInPackageChannelStub = func(ctx context.Context, bundleName, pkgName, channelName string) (*api.Bundle, error) {
179-
return nextBundle, nil
180-
}
181-
replacementAndLatestSource.GetBundleInPackageChannelStub = func(ctx context.Context, pkgName, channelName string) (*api.Bundle, error) {
182-
return latestBundle, nil
183-
}
184-
replacementAndNoAnnotationLatestSource.GetReplacementBundleInPackageChannelStub = func(ctx context.Context, bundleName, pkgName, channelName string) (*api.Bundle, error) {
185-
return nextBundle, nil
186-
}
187-
replacementAndNoAnnotationLatestSource.GetBundleInPackageChannelStub = func(ctx context.Context, pkgName, channelName string) (*api.Bundle, error) {
188-
return latestBundleNoAnnotation, nil
189-
}
190-
191-
initialKey := registry.CatalogKey{"initial", "ns"}
192-
otherKey := registry.CatalogKey{"other", "other"}
193-
replacementKey := registry.CatalogKey{"replacement", "ns"}
194-
replacementAndLatestKey := registry.CatalogKey{"replat", "ns"}
195-
replacementAndNoAnnotationLatestKey := registry.CatalogKey{"replatbad", "ns"}
196-
197-
sources := map[registry.CatalogKey]registry.ClientInterface{
198-
initialKey: &initialSource,
199-
otherKey: &otherSource,
200-
replacementKey: &replacementSource,
201-
replacementAndLatestKey: &replacementAndLatestSource,
202-
replacementAndNoAnnotationLatestKey: &replacementAndNoAnnotationLatestSource,
203-
}
204-
205-
startVersion := semver.MustParse("1.0.0-0")
206-
notInRange := semver.MustParse("1.0.0-1556661347")
207-
208-
type fields struct {
209-
sources map[registry.CatalogKey]registry.ClientInterface
210-
}
211-
type args struct {
212-
currentVersion *semver.Version
213-
pkgName string
214-
channelName string
215-
bundleName string
216-
initialSource registry.CatalogKey
217-
}
218-
type out struct {
219-
bundle *api.Bundle
220-
key *registry.CatalogKey
221-
err error
222-
}
223-
tests := []struct {
224-
name string
225-
fields fields
226-
args args
227-
out out
228-
}{
229-
{
230-
name: "FindsLatestInPrimaryCatalog",
231-
fields: fields{sources: sources},
232-
args: args{&startVersion, "testPkg", "testChannel", "test.v1", initialKey},
233-
out: out{bundle: latestBundle, key: &initialKey, err: nil},
234-
},
235-
{
236-
name: "FindsLatestInSecondaryCatalog",
237-
fields: fields{sources: sources},
238-
args: args{&startVersion, "testPkg", "testChannel", "test.v1", otherKey},
239-
out: out{bundle: latestBundle, key: &otherKey, err: nil},
240-
},
241-
{
242-
name: "PrefersLatestToReplaced/SameCatalog",
243-
fields: fields{sources: sources},
244-
args: args{&startVersion, "testPkg", "testChannel", "test.v1", replacementAndLatestKey},
245-
out: out{bundle: latestBundle, key: &replacementAndLatestKey, err: nil},
246-
},
247-
{
248-
name: "PrefersLatestToReplaced/OtherCatalog",
249-
fields: fields{sources: sources},
250-
args: args{&startVersion, "testPkg", "testChannel", "test.v1", initialKey},
251-
out: out{bundle: latestBundle, key: &initialKey, err: nil},
252-
},
253-
{
254-
name: "IgnoresLatestWithoutAnnotation",
255-
fields: fields{sources: sources},
256-
args: args{&startVersion, "testPkg", "testChannel", "test.v1", replacementAndNoAnnotationLatestKey},
257-
out: out{bundle: nextBundle, key: &replacementAndNoAnnotationLatestKey, err: nil},
258-
},
259-
{
260-
name: "IgnoresLatestNotInRange",
261-
fields: fields{sources: sources},
262-
args: args{&notInRange, "testPkg", "testChannel", "test.v1", replacementAndLatestKey},
263-
out: out{bundle: nextBundle, key: &replacementAndLatestKey, err: nil},
264-
},
265-
{
266-
name: "IgnoresLatestAtLatest",
267-
fields: fields{sources: sources},
268-
args: args{&latestVersion, "testPkg", "testChannel", "test.v1", otherKey},
269-
out: out{bundle: nil, key: nil, err: nil},
270-
},
271-
}
272-
for _, tt := range tests {
273-
t.Run(tt.name, func(t *testing.T) {
274-
q := &NamespaceSourceQuerier{
275-
sources: tt.fields.sources,
276-
}
277-
var got *api.Bundle
278-
var key *registry.CatalogKey
279-
var err error
280-
got, key, err = q.FindReplacement(tt.args.currentVersion, tt.args.bundleName, tt.args.pkgName, tt.args.channelName, tt.args.initialSource)
281-
if err != nil {
282-
t.Log(err.Error())
283-
}
284-
require.Equal(t, tt.out.err, err, "%v", err)
285-
require.Equal(t, tt.out.bundle, got)
286-
require.Equal(t, tt.out.key, key)
287-
})
288-
}
289-
}

test/e2e/subscription_e2e_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2066,7 +2066,7 @@ var _ = Describe("Subscription", func() {
20662066
}
20672067
updateInternalCatalog(GinkgoT(), kubeClient, crClient, catalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{crd, crd2}, []operatorsv1alpha1.ClusterServiceVersion{csvNewA, csvA, csvB}, manifests)
20682068
csvAsub := strings.Join([]string{packageName1, stableChannel, catalogSourceName, testNamespace}, "-")
2069-
_, err = fetchSubscription(crClient, testNamespace, csvAsub, subscriptionStateUpgradeAvailableChecker)
2069+
_, err = fetchSubscription(crClient, testNamespace, csvAsub, subscriptionStateAtLatestChecker)
20702070
require.NoError(GinkgoT(), err)
20712071
// Ensure csvNewA is not installed
20722072
_, err = crClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.Background(), csvNewA.Name, metav1.GetOptions{})

0 commit comments

Comments
 (0)