builder
Overview
The main role of Builder is:
- Create a Controller from the given Reconciler
- Configure target resources for the controller
- Register the controller to the Manager
About how the registered controllers are triggered, you can study in Manager. The controller registered to the manager by Builder will be in runnables.Others in Manager object, which will be started by Manager.Start()
.
Types
Builder
// Builder builds a Controller.
type Builder struct {
forInput ForInput
ownsInput []OwnsInput
watchesInput []WatchesInput
mgr manager.Manager
globalPredicates []predicate.Predicate
ctrl controller.Controller
ctrlOptions controller.Options
name string
}
ControllerManagedBy
: Initialize Builder with a Manager
Initialize a Builder with the specified manager.
func ControllerManagedBy(m manager.Manager) *Builder {
return &Builder{mgr: m}
}
For, Owns, and Watches: Define what object to watch
For(object client.Object, opts ...ForOption) *Builder
: only one resource can be configured. Same asWatches(&source.Kind{Type: apiType}, &handler.EnqueueRequestForObject{})
Owns(object client.Object, opts ...OwnsOption) *Builder
: Owns defines types of Objects being generated by the ControllerManagedBy, and configures the ControllerManagedBy to respond to create / delete / update events by reconciling the owner object. Same as the following code:EnqueueRequestForOwner: Extract owner object from ownerReferences and enqueue it to the queue.Watches(object, handler.EnqueueRequestForOwner([...], ownerType, OnlyControllerOwner()))
Watches(src source.Source, eventhandler handler.EventHandler, opts ...WatchesOption) *Builder
: Watches exposes the lower-level ControllerManagedBy Watches functions through the builder. Consider using Owns or For instead of Watches directly.
Example:
err = builder.
ControllerManagedBy(mgr). // Create the ControllerManagedBy
For(&alpha1v1.Foo{}). // Foo is the Application API
Owns(&corev1.Pod{}). // Foo owns Pods created by it
Complete(&FooReconciler{})
Complete
: Receive reconciler and build a controller
Receive reconcile.Reconciler
and call Build
:
// Complete builds the Application Controller.
func (blder *Builder) Complete(r reconcile.Reconciler) error {
_, err := blder.Build(r)
return err
}
Build
: Create a controller and return the controller.
func (blder *Builder) Build(r reconcile.Reconciler) (controller.Controller, error) {
...
// Set the ControllerManagedBy
if err := blder.doController(r); err != nil {
return nil, err
}
// Set the Watch
if err := blder.doWatch(); err != nil {
return nil, err
}
return blder.ctrl, nil
}
- bldr.doController to register the controler to the buidler
- Create a new controller.
blder.ctrl, err = newController(controllerName, blder.mgr, ctrlOptions)
- the controller is added to
manager.runnables.Others
byManager.Add(Runnable)
innewController
. (controller)
- Create a new controller.
- bldr.doWatch to start watching the target resources configured by
For
,Owns
, andWatches
.- The actual implementation of
Watch
function is in the controller
- The actual implementation of
Convert client.Object
to Source
- Controller.Watch needs
Source
as the first argument.Watch(src source.Source, eventhandler handler.EventHandler, predicates ...predicate.Predicate) error
client.Object
is set inForInput
,OwnsInput
, andWatchesInput
forFor
,Owns
, andWatches
respectively.-
Before calling
Controller.Watch
, theclient.Object
needs to be projected into Source based onobjectProjection
:projectAsNormal
: Use the object as it is. (In most cases)projectAsMetadata
: Extract only metadata.
typeForSrc, err := blder.project(blder.forInput.object, blder.forInput.objectProjection) if err != nil { return err } src := &source.Kind{Type: typeForSrc}
Kind implements the Source interface.
type Kind struct { // Type is the type of object to watch. e.g. &v1.Pod{} Type client.Object // cache used to watch APIs cache cache.Cache // started may contain an error if one was encountered during startup. If its closed and does not // contain an error, startup and syncing finished. started chan error startCancel func() }