Skip to content

Commit

Permalink
WIP: Expose generic mechanism for configuring the controller builder
Browse files Browse the repository at this point in the history
  • Loading branch information
mtesseract committed Feb 28, 2022
1 parent 0d534ef commit 7c1a306
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
46 changes: 45 additions & 1 deletion pkg/reconciler/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/handler"
Expand Down Expand Up @@ -78,6 +79,7 @@ type Reconciler struct {
maxConcurrentReconciles int
reconcilePeriod time.Duration
maxHistory int
builderSetupFuncs []BuilderSetupFunc

annotSetupOnce sync.Once
annotations map[string]struct{}
Expand All @@ -86,6 +88,9 @@ type Reconciler struct {
uninstallAnnotations map[string]annotation.Uninstall
}

// BuilderSetupFunc allows configuring a controller's builder.
type BuilderSetupFunc func(b *builder.Builder)

// New creates a new Reconciler that reconciles custom resources that define a
// Helm release. New takes variadic Option arguments that are used to configure
// the Reconciler.
Expand Down Expand Up @@ -133,7 +138,38 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
r.addDefaults(mgr, controllerName)
r.setupScheme(mgr)

c, err := controller.New(controllerName, mgr, controller.Options{Reconciler: r, MaxConcurrentReconciles: r.maxConcurrentReconciles})
// Unfortunately the controller builder API requires us to use the For() method for registering
// an object to watch. This object is registered using the standard EnqueueRequestForObject event handler,
// without any way to configure this.
//
// For our object watches we would like to use the sdkhandler.InstrumentedEnqueueRequestForObject event
// handler -- the registration is being done in setupWatches.
//
// Currently I don't see an easy way out here: In order to implement a generic mechanism for configuring
// the controller builder we need to use the controller builder API for creating the controller.
//
// As long as using For() is mandatory we need to provide some object to this method.
//
// As I understand it, we cannot use the actual type we would like to register for watching, because
// it is hard-coded to use an undesired event handler.
//
// Therefore I am registering a dummy type here. :-(
//
// -MC
dummyObj := &unstructured.Unstructured{}
dummyObj.SetGroupVersionKind(schema.GroupVersionKind{
Group: "dummy",
Version: "0.0",
Kind: "_dummy",
})
opts := controller.Options{Reconciler: r, MaxConcurrentReconciles: r.maxConcurrentReconciles}
builder := builder.ControllerManagedBy(mgr).Named(controllerName).WithOptions(opts).For(dummyObj)

for _, f := range r.builderSetupFuncs {
f(builder)
}

c, err := builder.Build(r)
if err != nil {
return err
}
Expand Down Expand Up @@ -425,6 +461,14 @@ func WithSelector(s metav1.LabelSelector) Option {
}
}

// WithBuilderSetupFunc is an Option that allows configuring a controller's builder using a custom function.
func WithBuilderSetupFunc(f BuilderSetupFunc) Option {
return func(r *Reconciler) error {
r.builderSetupFuncs = append(r.builderSetupFuncs, f)
return nil
}
}

// Reconcile reconciles a CR that defines a Helm v3 release.
//
// - If a release does not exist for this CR, a new release is installed.
Expand Down
37 changes: 37 additions & 0 deletions pkg/reconciler/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
Expand Down Expand Up @@ -1222,6 +1223,42 @@ var _ = Describe("Reconciler", func() {
})
})

var _ = Describe("Test custom controller builder setup", func() {
const customName = "renamed-controller"

var (
mgr manager.Manager
r *Reconciler
err error
builderModified bool
)
setupBuilder := func(b *builder.Builder) {
b.Named(customName)
builderModified = true
}

It("Registering builder setup function for reconciler works", func() {
mgr = getManagerOrFail()
r, err = New(
WithGroupVersionKind(gvk),
WithChart(chrt),
WithInstallAnnotations(annotation.InstallDescription{}),
WithUpgradeAnnotations(annotation.UpgradeDescription{}),
WithUninstallAnnotations(annotation.UninstallDescription{}),
WithOverrideValues(map[string]string{
"image.repository": "custom-nginx",
}),
WithBuilderSetupFunc(setupBuilder),
)
Expect(err).To(BeNil())
})

It("Setting up reconciler with manager causes custom builder setup to be executed", func() {
Expect(r.SetupWithManager(mgr)).To(Succeed())
Expect(builderModified).To(BeTrue())
})
})

var _ = Describe("Test predicate selector", func() {
It("verifying when a valid selector is passed", func() {
selectorPass := metav1.LabelSelector{
Expand Down

0 comments on commit 7c1a306

Please sign in to comment.