Skip to content

Commit 2bd2a0a

Browse files
authored
Expose generic mechanism for configuring the controller, allowing to add additional watch sources. (#153)
Expose generic mechanism for configuring the controller, allowing to add additional watch sources. Signed-off-by: Moritz Clasmeier <[email protected]>
1 parent 31544ee commit 2bd2a0a

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

pkg/reconciler/reconciler.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ type Reconciler struct {
8080
reconcilePeriod time.Duration
8181
maxHistory int
8282
skipPrimaryGVKSchemeRegistration bool
83+
controllerSetupFuncs []ControllerSetupFunc
8384

8485
annotSetupOnce sync.Once
8586
annotations map[string]struct{}
@@ -149,6 +150,13 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
149150
return err
150151
}
151152

153+
for _, f := range r.controllerSetupFuncs {
154+
err = f(c)
155+
if err != nil {
156+
return fmt.Errorf("failed to execute custom controller setup function: %v", err)
157+
}
158+
}
159+
152160
r.log.Info("Watching resource",
153161
"group", r.gvk.Group,
154162
"version", r.gvk.Version,
@@ -482,6 +490,30 @@ func WithSelector(s metav1.LabelSelector) Option {
482490
}
483491
}
484492

493+
// WithControllerSetupFunc is an Option that allows customizing a controller before it is started.
494+
// The only supported customization here is adding additional Watch sources to the controller.
495+
func WithControllerSetupFunc(f ControllerSetupFunc) Option {
496+
return func(r *Reconciler) error {
497+
r.controllerSetupFuncs = append(r.controllerSetupFuncs, f)
498+
return nil
499+
}
500+
}
501+
502+
// ControllerSetup allows restricted access to the Controller using the WithControllerSetupFunc option.
503+
// Currently the only supposed configuration is adding additional watchers do the controller.
504+
type ControllerSetup interface {
505+
// Watch takes events provided by a Source and uses the EventHandler to
506+
// enqueue reconcile.Requests in response to the events.
507+
//
508+
// Watch may be provided one or more Predicates to filter events before
509+
// they are given to the EventHandler. Events will be passed to the
510+
// EventHandler if all provided Predicates evaluate to true.
511+
Watch(src source.Source, eventhandler handler.EventHandler, predicates ...predicate.Predicate) error
512+
}
513+
514+
// ControllerSetupFunc allows configuring a controller's builder.
515+
type ControllerSetupFunc func(c ControllerSetup) error
516+
485517
// Reconcile reconciles a CR that defines a Helm v3 release.
486518
//
487519
// - If a release does not exist for this CR, a new release is installed.

pkg/reconciler/reconciler_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import (
4848
"sigs.k8s.io/controller-runtime/pkg/log/zap"
4949
"sigs.k8s.io/controller-runtime/pkg/manager"
5050
"sigs.k8s.io/controller-runtime/pkg/reconcile"
51+
"sigs.k8s.io/controller-runtime/pkg/source"
5152
"sigs.k8s.io/yaml"
5253

5354
"github.com/operator-framework/helm-operator-plugins/internal/sdk/controllerutil"
@@ -59,6 +60,7 @@ import (
5960
"github.com/operator-framework/helm-operator-plugins/pkg/reconciler/internal/conditions"
6061
helmfake "github.com/operator-framework/helm-operator-plugins/pkg/reconciler/internal/fake"
6162
"github.com/operator-framework/helm-operator-plugins/pkg/values"
63+
sdkhandler "github.com/operator-framework/operator-lib/handler"
6264
)
6365

6466
// custom is used within the reconciler test suite as underlying type for the GVK scheme.
@@ -1328,6 +1330,43 @@ var _ = Describe("Reconciler", func() {
13281330
})
13291331

13301332
})
1333+
1334+
var _ = Describe("Test custom controller setup", func() {
1335+
var (
1336+
mgr manager.Manager
1337+
r *Reconciler
1338+
err error
1339+
controllerSetupCalled bool
1340+
)
1341+
additionalGVK := schema.GroupVersionKind{Group: "example.com", Version: "v1", Kind: "SomeOtherKind"}
1342+
setupController := func(c ControllerSetup) error {
1343+
controllerSetupCalled = true
1344+
u := &unstructured.Unstructured{}
1345+
u.SetGroupVersionKind(additionalGVK)
1346+
return c.Watch(&source.Kind{Type: u}, &sdkhandler.InstrumentedEnqueueRequestForObject{})
1347+
}
1348+
1349+
It("Registering builder setup function for reconciler works", func() {
1350+
mgr = getManagerOrFail()
1351+
r, err = New(
1352+
WithGroupVersionKind(gvk),
1353+
WithChart(chrt),
1354+
WithInstallAnnotations(annotation.InstallDescription{}),
1355+
WithUpgradeAnnotations(annotation.UpgradeDescription{}),
1356+
WithUninstallAnnotations(annotation.UninstallDescription{}),
1357+
WithOverrideValues(map[string]string{
1358+
"image.repository": "custom-nginx",
1359+
}),
1360+
WithControllerSetupFunc(setupController),
1361+
)
1362+
Expect(err).To(BeNil())
1363+
})
1364+
1365+
It("Setting up reconciler with manager causes custom builder setup to be executed", func() {
1366+
Expect(r.SetupWithManager(mgr)).To(Succeed())
1367+
Expect(controllerSetupCalled).To(BeTrue())
1368+
})
1369+
})
13311370
})
13321371

13331372
func getManagerOrFail() manager.Manager {

0 commit comments

Comments
 (0)