diff --git a/example_test.go b/example_test.go index 2890699d56..e86719480f 100644 --- a/example_test.go +++ b/example_test.go @@ -87,8 +87,8 @@ func GenericExample() { b := ctrl.NewControllerManagedBy(manager) // Create the Controller // ReplicaSet is the Application API - b.Add(builder.For(b, &appsv1.ReplicaSet{})). - Add(builder.Owns(b, &appsv1.ReplicaSet{}, &corev1.Pod{})). // ReplicaSet owns Pods created by it + b.Add(builder.For(manager, &appsv1.ReplicaSet{})). + Add(builder.Owns(manager, &appsv1.ReplicaSet{}, &corev1.Pod{})). // ReplicaSet owns Pods created by it Complete(&ReplicaSetReconciler{Client: manager.GetClient()}) if err != nil { log.Error(err, "could not create controller") @@ -189,6 +189,58 @@ func Example_customHandler() { } } +// This example creates a simple application Controller that is configured for ExampleCRDWithConfigMapRef CRD. +// Any change in the configMap referenced in this Custom Resource will cause the re-reconcile of the parent ExampleCRDWithConfigMapRef +// due to the implementation of the .Watches method of "sigs.k8s.io/controller-runtime/pkg/builder".Builder. +func Example_generic_customHandler() { + log := ctrl.Log.WithName("builder-examples") + + manager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{}) + if err != nil { + log.Error(err, "could not create manager") + os.Exit(1) + } + + err = ctrl. + NewControllerManagedBy(manager). + For(&ExampleCRDWithConfigMapRef{}). + Add(builder.Watches(manager, &corev1.ConfigMap{}, handler.EnqueueRequestsFromObjectMap(func(ctx context.Context, cm *corev1.ConfigMap) []ctrl.Request { + // map a change from referenced configMap to ExampleCRDWithConfigMapRef, which causes its re-reconcile + crList := &ExampleCRDWithConfigMapRefList{} + if err := manager.GetClient().List(ctx, crList); err != nil { + manager.GetLogger().Error(err, "while listing ExampleCRDWithConfigMapRefs") + return nil + } + + reqs := make([]ctrl.Request, 0, len(crList.Items)) + for _, item := range crList.Items { + if item.ConfigMapRef.Name == cm.Name && cm.Data["Namespace"] == item.GetNamespace() { + reqs = append(reqs, ctrl.Request{ + NamespacedName: types.NamespacedName{ + Namespace: item.GetNamespace(), + Name: item.GetName(), + }, + }) + } + } + + return reqs + }))). + Complete(reconcile.Func(func(ctx context.Context, r reconcile.Request) (reconcile.Result, error) { + // Your business logic to implement the API by creating, updating, deleting objects goes here. + return reconcile.Result{}, nil + })) + if err != nil { + log.Error(err, "could not create controller") + os.Exit(1) + } + + if err := manager.Start(ctrl.SetupSignalHandler()); err != nil { + log.Error(err, "could not start manager") + os.Exit(1) + } +} + // This example creates a simple application Controller that is configured for ReplicaSets and Pods. // This application controller will be running leader election with the provided configuration in the manager options. // If leader election configuration is not provided, controller runs leader election with default values. diff --git a/pkg/builder/controller.go b/pkg/builder/controller.go index b23468ee15..f75bfaaaec 100644 --- a/pkg/builder/controller.go +++ b/pkg/builder/controller.go @@ -187,25 +187,23 @@ func (blder *Builder) WatchesRawSource(src source.PrepareSyncing, eventHandler h return blder } -func For[T client.Object](blder *Builder, object T, prct ...predicate.ObjectPredicate[T]) source.Source { - blder.forInput = ForInput{object: object} - - return source.ObjectKind(blder.mgr.GetCache(), object).PrepareObject(&handler.EnqueueRequest[T]{}, prct...) +func For[T client.Object](mgr manager.Manager, object T, prct ...predicate.ObjectPredicate[T]) source.Source { + return source.ObjectKind(mgr.GetCache(), object).PrepareObject(&handler.EnqueueRequest[T]{}, prct...) } -func Owns[F, T client.Object](blder *Builder, owner F, owned T, prct ...predicate.ObjectPredicate[T]) source.Source { - src := source.ObjectKind(blder.mgr.GetCache(), owned) +func Owns[F, T client.Object](mgr manager.Manager, owner F, owned T, prct ...predicate.ObjectPredicate[T]) source.Source { + src := source.ObjectKind(mgr.GetCache(), owned) hdler := handler.EnqueueRequestForOwner( - blder.mgr.GetScheme(), blder.mgr.GetRESTMapper(), + mgr.GetScheme(), mgr.GetRESTMapper(), owner, ) return src.PrepareObject(handler.ObjectFuncAdapter[T](hdler), prct...) } -func Watches[T client.Object](blder *Builder, object T, eventHandler handler.ObjectHandler[T], prct ...predicate.ObjectPredicate[T]) source.Source { - return source.ObjectKind(blder.mgr.GetCache(), object).PrepareObject(eventHandler, prct...) +func Watches[T client.Object](mgr manager.Manager, object T, eventHandler handler.ObjectHandler[T], prct ...predicate.ObjectPredicate[T]) source.Source { + return source.ObjectKind(mgr.GetCache(), object).PrepareObject(eventHandler, prct...) } func (blder *Builder) Add(src source.Source) *Builder {