@@ -23,10 +23,13 @@ import (
2323
2424 "k8s.io/apimachinery/pkg/api/meta"
2525 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2627 "k8s.io/apimachinery/pkg/runtime"
2728 "k8s.io/apimachinery/pkg/runtime/schema"
29+ "k8s.io/apimachinery/pkg/watch"
2830 clientgotesting "k8s.io/client-go/testing"
2931 ref "k8s.io/client-go/tools/reference"
32+ "reconciler.io/runtime/duck"
3033 "sigs.k8s.io/controller-runtime/pkg/client"
3134)
3235
@@ -146,6 +149,20 @@ func (w *clientWrapper) react(action Action) error {
146149 return nil
147150}
148151
152+ func (w * clientWrapper ) reactWatcherFunc (action Action ) error {
153+ for _ , reactor := range w .watchReactionChain {
154+ if ! reactor .Handles (action ) {
155+ continue
156+ }
157+ handled , _ , err := reactor .React (action )
158+ if ! handled {
159+ continue
160+ }
161+ return err
162+ }
163+ return nil
164+ }
165+
149166func (w * clientWrapper ) Scheme () * runtime.Scheme {
150167 return w .client .Scheme ()
151168}
@@ -313,6 +330,55 @@ func (w *clientWrapper) DeleteAllOf(ctx context.Context, obj client.Object, opts
313330 return w .client .DeleteAllOf (ctx , obj , opts ... )
314331}
315332
333+ func (w * clientWrapper ) Watch (ctx context.Context , list client.ObjectList , opts ... client.ListOption ) (watch.Interface , error ) {
334+
335+ ww , ok := w .client .(client.WithWatch )
336+ if ! ok {
337+ panic (fmt .Errorf ("unable to call Watch with wrapped client that does not implement client.WithWatch" ))
338+ }
339+
340+ gvr , namespace , name , err := w .objmeta (list )
341+ if err != nil {
342+ return nil , err
343+ }
344+
345+ // call reactor chain
346+ err = w .reactWatcherFunc (clientgotesting .NewGetAction (gvr , namespace , name ))
347+ if err != nil {
348+ return nil , err
349+ }
350+ err = w .reactWatcherFunc (clientgotesting .NewCreateAction (gvr , namespace , list ))
351+ if err != nil {
352+ return nil , err
353+ }
354+ err = w .reactWatcherFunc (clientgotesting .NewDeleteAction (gvr , namespace , name ))
355+ if err != nil {
356+ return nil , err
357+ }
358+ err = w .reactWatcherFunc (clientgotesting .NewUpdateAction (gvr , namespace , list ))
359+ if err != nil {
360+ return nil , err
361+ }
362+
363+ if ! duck .IsDuck (list , w .Scheme ()) {
364+ return ww .Watch (ctx , list , opts ... )
365+ }
366+
367+ uObj , err := runtime .DefaultUnstructuredConverter .ToUnstructured (list )
368+ if err != nil {
369+ return nil , err
370+ }
371+ u := & unstructured.UnstructuredList {Object : uObj }
372+ watcher , err := ww .Watch (ctx , u , opts ... )
373+ if err != nil {
374+ return nil , err
375+ }
376+ if err := runtime .DefaultUnstructuredConverter .FromUnstructured (u .Object , list ); err != nil {
377+ return nil , err
378+ }
379+ return watcher , nil
380+ }
381+
316382func (w * clientWrapper ) Status () client.StatusWriter {
317383 return & statusWriterWrapper {
318384 statusWriter : w .client .Status (),
0 commit comments