Skip to content

Commit 4bae06a

Browse files
authored
UpdateStrategy RegistryPoll with nil Interval (#2920)
Adds protection against a nil-pointer panic when an UpdateStrategy with nil value for RegistryPoll Interval is supplied. Also adds a unit test to ensure that the code does not panic but instead returns an error when this situation is encountered. Signed-off-by: Daniel Franz <[email protected]>
1 parent 401bfff commit 4bae06a

File tree

2 files changed

+59
-8
lines changed

2 files changed

+59
-8
lines changed

pkg/controller/operators/catalog/operator.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -749,16 +749,19 @@ func (o *Operator) syncRegistryServer(logger *logrus.Entry, in *v1alpha1.Catalog
749749
logger.Debug("ensured registry server")
750750

751751
// requeue the catalog sync based on the polling interval, for accurate syncs of catalogs with polling enabled
752-
if out.Spec.UpdateStrategy != nil {
753-
if out.Spec.UpdateStrategy.RegistryPoll != nil {
754-
if out.Spec.UpdateStrategy.RegistryPoll.ParsingError != "" && out.Status.Reason != v1alpha1.CatalogSourceIntervalInvalidError {
755-
out.SetError(v1alpha1.CatalogSourceIntervalInvalidError, fmt.Errorf(out.Spec.UpdateStrategy.RegistryPoll.ParsingError))
756-
}
757-
logger.Debugf("requeuing registry server sync based on polling interval %s", out.Spec.UpdateStrategy.Interval.Duration.String())
758-
resyncPeriod := reconciler.SyncRegistryUpdateInterval(out, time.Now())
759-
o.catsrcQueueSet.RequeueAfter(out.GetNamespace(), out.GetName(), queueinformer.ResyncWithJitter(resyncPeriod, 0.1)())
752+
if out.Spec.UpdateStrategy != nil && out.Spec.UpdateStrategy.RegistryPoll != nil {
753+
if out.Spec.UpdateStrategy.Interval == nil {
754+
syncError = fmt.Errorf("empty polling interval; cannot requeue registry server sync without a provided polling interval")
755+
out.SetError(v1alpha1.CatalogSourceIntervalInvalidError, syncError)
760756
return
761757
}
758+
if out.Spec.UpdateStrategy.RegistryPoll.ParsingError != "" && out.Status.Reason != v1alpha1.CatalogSourceIntervalInvalidError {
759+
out.SetError(v1alpha1.CatalogSourceIntervalInvalidError, fmt.Errorf(out.Spec.UpdateStrategy.RegistryPoll.ParsingError))
760+
}
761+
logger.Debugf("requeuing registry server sync based on polling interval %s", out.Spec.UpdateStrategy.Interval.Duration.String())
762+
resyncPeriod := reconciler.SyncRegistryUpdateInterval(out, time.Now())
763+
o.catsrcQueueSet.RequeueAfter(out.GetNamespace(), out.GetName(), queueinformer.ResyncWithJitter(resyncPeriod, 0.1)())
764+
return
762765
}
763766

764767
if err := o.sources.Remove(sourceKey); err != nil {

pkg/controller/operators/catalog/operator_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,54 @@ func TestValidateExistingCRs(t *testing.T) {
14151415
}
14161416
}
14171417

1418+
func TestSyncRegistryServer(t *testing.T) {
1419+
namespace := "ns"
1420+
1421+
tests := []struct {
1422+
testName string
1423+
err error
1424+
catSrc *v1alpha1.CatalogSource
1425+
clientObjs []runtime.Object
1426+
}{
1427+
{
1428+
testName: "EmptyRegistryPoll",
1429+
err: fmt.Errorf("empty polling interval; cannot requeue registry server sync without a provided polling interval"),
1430+
catSrc: &v1alpha1.CatalogSource{
1431+
Spec: v1alpha1.CatalogSourceSpec{
1432+
UpdateStrategy: &v1alpha1.UpdateStrategy{
1433+
RegistryPoll: &v1alpha1.RegistryPoll{},
1434+
},
1435+
},
1436+
},
1437+
},
1438+
}
1439+
1440+
for _, tt := range tests {
1441+
t.Run(tt.testName, func(t *testing.T) {
1442+
ctx, cancel := context.WithCancel(context.TODO())
1443+
defer cancel()
1444+
1445+
tt.clientObjs = append(tt.clientObjs, tt.catSrc)
1446+
op, err := NewFakeOperator(ctx, namespace, []string{namespace}, withClientObjs(tt.clientObjs...))
1447+
require.NoError(t, err)
1448+
1449+
op.reconciler = &fakes.FakeRegistryReconcilerFactory{
1450+
ReconcilerForSourceStub: func(source *v1alpha1.CatalogSource) reconciler.RegistryReconciler {
1451+
return &fakes.FakeRegistryReconciler{
1452+
EnsureRegistryServerStub: func(source *v1alpha1.CatalogSource) error {
1453+
return nil
1454+
},
1455+
}
1456+
},
1457+
}
1458+
require.NotPanics(t, func() {
1459+
_, _, err = op.syncRegistryServer(logrus.NewEntry(op.logger), tt.catSrc)
1460+
})
1461+
require.Equal(t, tt.err, err)
1462+
})
1463+
}
1464+
}
1465+
14181466
func fakeConfigMapData() map[string]string {
14191467
data := make(map[string]string)
14201468
yaml, err := yaml.Marshal([]apiextensionsv1beta1.CustomResourceDefinition{crd("fake-crd")})

0 commit comments

Comments
 (0)