Skip to content

Commit a49cd8b

Browse files
committed
Expose errors generated while retrieving catalog content.
Failing to fetch catalog content should not silently return an empty cache. Instead, it should fail outright with an error that indicates which catalog(s) could not be fetched. Signed-off-by: Ben Luddy <[email protected]>
1 parent 167e031 commit a49cd8b

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

pkg/controller/registry/resolver/cache.go

+19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"sync"
99
"time"
1010

11+
"k8s.io/apimachinery/pkg/util/errors"
12+
1113
"github.com/sirupsen/logrus"
1214

1315
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1"
@@ -79,6 +81,19 @@ type NamespacedOperatorCache struct {
7981
snapshots map[registry.CatalogKey]*CatalogSnapshot
8082
}
8183

84+
func (c *NamespacedOperatorCache) Error() error {
85+
var errs []error
86+
for key, snapshot := range c.snapshots {
87+
snapshot.m.Lock()
88+
err := snapshot.err
89+
snapshot.m.Unlock()
90+
if err != nil {
91+
errs = append(errs, fmt.Errorf("error using catalog %s (in namespace %s): %w", key.Name, key.Namespace, err))
92+
}
93+
}
94+
return errors.NewAggregate(errs)
95+
}
96+
8297
func (c *OperatorCache) Expire(catalog registry.CatalogKey) {
8398
c.m.Lock()
8499
defer c.m.Unlock()
@@ -195,6 +210,7 @@ func (c *OperatorCache) populate(ctx context.Context, snapshot *CatalogSnapshot,
195210
it, err := registry.ListBundles(ctx)
196211
if err != nil {
197212
snapshot.logger.Errorf("failed to list bundles: %s", err.Error())
213+
snapshot.err = err
198214
return
199215
}
200216
c.logger.WithField("catalog", snapshot.key.String()).Debug("updating cache")
@@ -223,6 +239,7 @@ func (c *OperatorCache) populate(ctx context.Context, snapshot *CatalogSnapshot,
223239
}
224240
if err := it.Error(); err != nil {
225241
snapshot.logger.Warnf("error encountered while listing bundles: %s", err.Error())
242+
snapshot.err = err
226243
}
227244
snapshot.operators = operators
228245
}
@@ -293,6 +310,7 @@ type CatalogSnapshot struct {
293310
m sync.RWMutex
294311
pop context.CancelFunc
295312
priority catalogSourcePriority
313+
err error
296314
}
297315

298316
func (s *CatalogSnapshot) Cancel() {
@@ -400,6 +418,7 @@ type MultiCatalogOperatorFinder interface {
400418
Catalog(registry.CatalogKey) OperatorFinder
401419
FindPreferred(*registry.CatalogKey, ...OperatorPredicate) []*Operator
402420
WithExistingOperators(*CatalogSnapshot) MultiCatalogOperatorFinder
421+
Error() error
403422
OperatorFinder
404423
}
405424

pkg/controller/registry/resolver/cache_test.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package resolver
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"io"
78
"math/rand"
@@ -10,6 +11,7 @@ import (
1011
"time"
1112

1213
"github.com/sirupsen/logrus"
14+
"github.com/sirupsen/logrus/hooks/test"
1315
"github.com/stretchr/testify/assert"
1416
"github.com/stretchr/testify/require"
1517

@@ -35,6 +37,8 @@ func (s *BundleStreamStub) Recv() (*api.Bundle, error) {
3537

3638
type RegistryClientStub struct {
3739
BundleIterator *client.BundleIterator
40+
41+
ListBundlesError error
3842
}
3943

4044
func (s *RegistryClientStub) Get() (client.Interface, error) {
@@ -58,7 +62,7 @@ func (s *RegistryClientStub) GetBundleThatProvides(ctx context.Context, group, v
5862
}
5963

6064
func (s *RegistryClientStub) ListBundles(ctx context.Context) (*client.BundleIterator, error) {
61-
return s.BundleIterator, nil
65+
return s.BundleIterator, s.ListBundlesError
6266
}
6367

6468
func (s *RegistryClientStub) GetPackage(ctx context.Context, packageName string) (*api.Package, error) {
@@ -339,3 +343,16 @@ func TestStripPluralRequiredAndProvidedAPIKeys(t *testing.T) {
339343
assert.Equal(t, "K.v1.g", result[0].providedAPIs.String())
340344
assert.Equal(t, "K2.v2.g2", result[0].requiredAPIs.String())
341345
}
346+
347+
func TestNamespaceOperatorCacheError(t *testing.T) {
348+
rcp := RegistryClientProviderStub{}
349+
catsrcLister := operatorlister.NewLister().OperatorsV1alpha1().CatalogSourceLister()
350+
key := registry.CatalogKey{Namespace: "dummynamespace", Name: "dummyname"}
351+
rcp[key] = &RegistryClientStub{
352+
ListBundlesError: errors.New("testing"),
353+
}
354+
355+
logger, _ := test.NewNullLogger()
356+
c := NewOperatorCache(rcp, logger, catsrcLister)
357+
require.EqualError(t, c.Namespaced("dummynamespace").Error(), "error using catalog dummyname (in namespace dummynamespace): testing")
358+
}

pkg/controller/registry/resolver/resolver.go

+4
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust
103103

104104
r.addInvariants(namespacedCache, installables)
105105

106+
if err := namespacedCache.Error(); err != nil {
107+
return nil, err
108+
}
109+
106110
input := make([]solver.Installable, 0)
107111
for _, i := range installables {
108112
input = append(input, i)

pkg/controller/registry/types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (k *CatalogKey) Virtual() bool {
3333

3434
func NewVirtualCatalogKey(namespace string) CatalogKey {
3535
return CatalogKey{
36-
Name: ExistingOperatorKey,
36+
Name: ExistingOperatorKey,
3737
Namespace: namespace,
3838
}
3939
}

0 commit comments

Comments
 (0)