diff --git a/pkg/builder/controller.go b/pkg/builder/controller.go index d5d486dca0..70eda6298b 100644 --- a/pkg/builder/controller.go +++ b/pkg/builder/controller.go @@ -132,6 +132,11 @@ func (blder *TypedBuilder[request]) Owns(object client.Object, opts ...OwnsOptio return blder } +type untypedWatchesInput interface { + setPredicates([]predicate.Predicate) + setObjectProjection(objectProjection) +} + // WatchesInput represents the information set by Watches method. type WatchesInput[request comparable] struct { obj client.Object @@ -140,6 +145,14 @@ type WatchesInput[request comparable] struct { objectProjection objectProjection } +func (w *WatchesInput[request]) setPredicates(predicates []predicate.Predicate) { + w.predicates = predicates +} + +func (w *WatchesInput[request]) setObjectProjection(objectProjection objectProjection) { + w.objectProjection = objectProjection +} + // Watches defines the type of Object to watch, and configures the ControllerManagedBy to respond to create / delete / // update events by *reconciling the object* with the given EventHandler. // @@ -148,7 +161,7 @@ type WatchesInput[request comparable] struct { func (blder *TypedBuilder[request]) Watches( object client.Object, eventHandler handler.TypedEventHandler[client.Object, request], - opts ...WatchesOption[request], + opts ...WatchesOption, ) *TypedBuilder[request] { input := WatchesInput[request]{ obj: object, @@ -193,9 +206,9 @@ func (blder *TypedBuilder[request]) Watches( func (blder *TypedBuilder[request]) WatchesMetadata( object client.Object, eventHandler handler.TypedEventHandler[client.Object, request], - opts ...WatchesOption[request], + opts ...WatchesOption, ) *TypedBuilder[request] { - opts = append(opts, projectAs[request](projectAsMetadata)) + opts = append(opts, projectAs(projectAsMetadata)) return blder.Watches(object, eventHandler, opts...) } diff --git a/pkg/builder/controller_test.go b/pkg/builder/controller_test.go index 84cd4bae1c..840bb18513 100644 --- a/pkg/builder/controller_test.go +++ b/pkg/builder/controller_test.go @@ -47,6 +47,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/scheme" ) +var _ untypedWatchesInput = (*WatchesInput[struct{}])(nil) + type typedNoop struct{} func (typedNoop) Reconcile(context.Context, reconcile.Request) (reconcile.Result, error) { diff --git a/pkg/builder/options.go b/pkg/builder/options.go index d2e7f311cc..b907b5d020 100644 --- a/pkg/builder/options.go +++ b/pkg/builder/options.go @@ -18,7 +18,6 @@ package builder import ( "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/reconcile" ) // {{{ "Functional" Option Interfaces @@ -36,9 +35,9 @@ type OwnsOption interface { } // WatchesOption is some configuration that modifies options for a watches request. -type WatchesOption[request comparable] interface { +type WatchesOption interface { // ApplyToWatches applies this configuration to the given watches options. - ApplyToWatches(*WatchesInput[request]) + ApplyToWatches(untypedWatchesInput) } // }}} @@ -53,31 +52,28 @@ func WithPredicates(predicates ...predicate.Predicate) Predicates { } // Predicates filters events before enqueuing the keys. -type Predicates = TypedPredicates[reconcile.Request] - -// TypedPredicates filters events before enqueuing the keys. -type TypedPredicates[request comparable] struct { +type Predicates struct { predicates []predicate.Predicate } // ApplyToFor applies this configuration to the given ForInput options. -func (w TypedPredicates[request]) ApplyToFor(opts *ForInput) { +func (w Predicates) ApplyToFor(opts *ForInput) { opts.predicates = w.predicates } // ApplyToOwns applies this configuration to the given OwnsInput options. -func (w TypedPredicates[request]) ApplyToOwns(opts *OwnsInput) { +func (w Predicates) ApplyToOwns(opts *OwnsInput) { opts.predicates = w.predicates } // ApplyToWatches applies this configuration to the given WatchesInput options. -func (w TypedPredicates[request]) ApplyToWatches(opts *WatchesInput[request]) { - opts.predicates = w.predicates +func (w Predicates) ApplyToWatches(opts untypedWatchesInput) { + opts.setPredicates(w.predicates) } var _ ForOption = &Predicates{} var _ OwnsOption = &Predicates{} -var _ WatchesOption[reconcile.Request] = &Predicates{} +var _ WatchesOption = &Predicates{} // }}} @@ -86,21 +82,21 @@ var _ WatchesOption[reconcile.Request] = &Predicates{} // projectAs configures the projection on the input. // Currently only OnlyMetadata is supported. We might want to expand // this to arbitrary non-special local projections in the future. -type projectAs[request comparable] objectProjection +type projectAs objectProjection // ApplyToFor applies this configuration to the given ForInput options. -func (p projectAs[request]) ApplyToFor(opts *ForInput) { +func (p projectAs) ApplyToFor(opts *ForInput) { opts.objectProjection = objectProjection(p) } // ApplyToOwns applies this configuration to the given OwnsInput options. -func (p projectAs[request]) ApplyToOwns(opts *OwnsInput) { +func (p projectAs) ApplyToOwns(opts *OwnsInput) { opts.objectProjection = objectProjection(p) } // ApplyToWatches applies this configuration to the given WatchesInput options. -func (p projectAs[request]) ApplyToWatches(opts *WatchesInput[request]) { - opts.objectProjection = objectProjection(p) +func (p projectAs) ApplyToWatches(opts untypedWatchesInput) { + opts.setObjectProjection(objectProjection(p)) } var ( @@ -134,11 +130,11 @@ var ( // In the first case, controller-runtime will create another cache for the // concrete type on top of the metadata cache; this increases memory // consumption and leads to race conditions as caches are not in sync. - OnlyMetadata = projectAs[reconcile.Request](projectAsMetadata) + OnlyMetadata = projectAs(projectAsMetadata) - _ ForOption = OnlyMetadata - _ OwnsOption = OnlyMetadata - _ WatchesOption[reconcile.Request] = OnlyMetadata + _ ForOption = OnlyMetadata + _ OwnsOption = OnlyMetadata + _ WatchesOption = OnlyMetadata ) // }}}