@@ -26,6 +26,7 @@ import (
2626 "k8s.io/klog/v2"
2727 "k8s.io/utils/ptr"
2828
29+ "sigs.k8s.io/controller-runtime/pkg/config"
2930 "sigs.k8s.io/controller-runtime/pkg/controller/priorityqueue"
3031 "sigs.k8s.io/controller-runtime/pkg/internal/controller"
3132 "sigs.k8s.io/controller-runtime/pkg/manager"
@@ -80,13 +81,53 @@ type TypedOptions[request comparable] struct {
8081 // Only use a custom NewQueue if you know what you are doing.
8182 NewQueue func (controllerName string , rateLimiter workqueue.TypedRateLimiter [request ]) workqueue.TypedRateLimitingInterface [request ]
8283
84+ // Logger will be used to build a default LogConstructor if unset.
85+ Logger logr.Logger
86+
8387 // LogConstructor is used to construct a logger used for this controller and passed
8488 // to each reconciliation via the context field.
8589 LogConstructor func (request * request ) logr.Logger
90+
91+ // UsePriorityQueue configures the controllers queue to use the controller-runtime provided
92+ // priority queue.
93+ //
94+ // Note: This flag is disabled by default until a future version. It's currently in beta.
95+ UsePriorityQueue * bool
96+ }
97+
98+ // DefaultFromConfig defaults the config from a config.Controller
99+ func (options * TypedOptions [request ]) DefaultFromConfig (config config.Controller ) {
100+ if options .Logger .GetSink () == nil {
101+ options .Logger = config .Logger
102+ }
103+
104+ if options .SkipNameValidation == nil {
105+ options .SkipNameValidation = config .SkipNameValidation
106+ }
107+
108+ if options .MaxConcurrentReconciles <= 0 && config .MaxConcurrentReconciles > 0 {
109+ options .MaxConcurrentReconciles = config .MaxConcurrentReconciles
110+ }
111+
112+ if options .CacheSyncTimeout == 0 && config .CacheSyncTimeout > 0 {
113+ options .CacheSyncTimeout = config .CacheSyncTimeout
114+ }
115+
116+ if options .UsePriorityQueue == nil {
117+ options .UsePriorityQueue = config .UsePriorityQueue
118+ }
119+
120+ if options .RecoverPanic == nil {
121+ options .RecoverPanic = config .RecoverPanic
122+ }
123+
124+ if options .NeedLeaderElection == nil {
125+ options .NeedLeaderElection = config .NeedLeaderElection
126+ }
86127}
87128
88- // Controller implements a Kubernetes API. A Controller manages a work queue fed reconcile.Requests
89- // from source.Sources. Work is performed through the reconcile.Reconciler for each enqueued item.
129+ // Controller implements an API. A Controller manages a work queue fed reconcile.Requests
130+ // from source.Sources. Work is performed through the reconcile.Reconciler for each enqueued item.
90131// Work typically is reads and writes Kubernetes objects to make the system state match the state specified
91132// in the object Spec.
92133type Controller = TypedController [reconcile.Request ]
@@ -119,7 +160,8 @@ func New(name string, mgr manager.Manager, options Options) (Controller, error)
119160//
120161// The name must be unique as it is used to identify the controller in metrics and logs.
121162func NewTyped [request comparable ](name string , mgr manager.Manager , options TypedOptions [request ]) (TypedController [request ], error ) {
122- c , err := NewTypedUnmanaged (name , mgr , options )
163+ options .DefaultFromConfig (mgr .GetControllerOptions ())
164+ c , err := NewTypedUnmanaged (name , options )
123165 if err != nil {
124166 return nil , err
125167 }
@@ -132,14 +174,14 @@ func NewTyped[request comparable](name string, mgr manager.Manager, options Type
132174// caller is responsible for starting the returned controller.
133175//
134176// The name must be unique as it is used to identify the controller in metrics and logs.
135- func NewUnmanaged (name string , mgr manager. Manager , options Options ) (Controller , error ) {
136- return NewTypedUnmanaged (name , mgr , options )
177+ func NewUnmanaged (name string , options Options ) (Controller , error ) {
178+ return NewTypedUnmanaged (name , options )
137179}
138180
139181// NewTypedUnmanaged returns a new typed controller without adding it to the manager.
140182//
141183// The name must be unique as it is used to identify the controller in metrics and logs.
142- func NewTypedUnmanaged [request comparable ](name string , mgr manager. Manager , options TypedOptions [request ]) (TypedController [request ], error ) {
184+ func NewTypedUnmanaged [request comparable ](name string , options TypedOptions [request ]) (TypedController [request ], error ) {
143185 if options .Reconciler == nil {
144186 return nil , fmt .Errorf ("must specify Reconciler" )
145187 }
@@ -148,18 +190,14 @@ func NewTypedUnmanaged[request comparable](name string, mgr manager.Manager, opt
148190 return nil , fmt .Errorf ("must specify Name for Controller" )
149191 }
150192
151- if options .SkipNameValidation == nil {
152- options .SkipNameValidation = mgr .GetControllerOptions ().SkipNameValidation
153- }
154-
155193 if options .SkipNameValidation == nil || ! * options .SkipNameValidation {
156194 if err := checkName (name ); err != nil {
157195 return nil , err
158196 }
159197 }
160198
161199 if options .LogConstructor == nil {
162- log := mgr . GetLogger () .WithValues (
200+ log := options . Logger .WithValues (
163201 "controller" , name ,
164202 )
165203 options .LogConstructor = func (in * request ) logr.Logger {
@@ -175,23 +213,15 @@ func NewTypedUnmanaged[request comparable](name string, mgr manager.Manager, opt
175213 }
176214
177215 if options .MaxConcurrentReconciles <= 0 {
178- if mgr .GetControllerOptions ().MaxConcurrentReconciles > 0 {
179- options .MaxConcurrentReconciles = mgr .GetControllerOptions ().MaxConcurrentReconciles
180- } else {
181- options .MaxConcurrentReconciles = 1
182- }
216+ options .MaxConcurrentReconciles = 1
183217 }
184218
185219 if options .CacheSyncTimeout == 0 {
186- if mgr .GetControllerOptions ().CacheSyncTimeout != 0 {
187- options .CacheSyncTimeout = mgr .GetControllerOptions ().CacheSyncTimeout
188- } else {
189- options .CacheSyncTimeout = 2 * time .Minute
190- }
220+ options .CacheSyncTimeout = 2 * time .Minute
191221 }
192222
193223 if options .RateLimiter == nil {
194- if ptr .Deref (mgr . GetControllerOptions () .UsePriorityQueue , false ) {
224+ if ptr .Deref (options .UsePriorityQueue , false ) {
195225 options .RateLimiter = workqueue .NewTypedItemExponentialFailureRateLimiter [request ](5 * time .Millisecond , 1000 * time .Second )
196226 } else {
197227 options .RateLimiter = workqueue .DefaultTypedControllerRateLimiter [request ]()
@@ -200,9 +230,9 @@ func NewTypedUnmanaged[request comparable](name string, mgr manager.Manager, opt
200230
201231 if options .NewQueue == nil {
202232 options .NewQueue = func (controllerName string , rateLimiter workqueue.TypedRateLimiter [request ]) workqueue.TypedRateLimitingInterface [request ] {
203- if ptr .Deref (mgr . GetControllerOptions () .UsePriorityQueue , false ) {
233+ if ptr .Deref (options .UsePriorityQueue , false ) {
204234 return priorityqueue .New (controllerName , func (o * priorityqueue.Opts [request ]) {
205- o .Log = mgr . GetLogger () .WithValues ("controller" , controllerName )
235+ o .Log = options . Logger .WithValues ("controller" , controllerName )
206236 o .RateLimiter = rateLimiter
207237 })
208238 }
@@ -212,14 +242,6 @@ func NewTypedUnmanaged[request comparable](name string, mgr manager.Manager, opt
212242 }
213243 }
214244
215- if options .RecoverPanic == nil {
216- options .RecoverPanic = mgr .GetControllerOptions ().RecoverPanic
217- }
218-
219- if options .NeedLeaderElection == nil {
220- options .NeedLeaderElection = mgr .GetControllerOptions ().NeedLeaderElection
221- }
222-
223245 // Create controller with dependencies set
224246 return & controller.Controller [request ]{
225247 Do : options .Reconciler ,
0 commit comments