knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/webhook/testing/factory.go (about)

     1  /*
     2  Copyright 2019 The Knative Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testing
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	fakeapixclient "knative.dev/pkg/client/injection/apiextensions/client/fake"
    24  	fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
    25  	fakedynamicclient "knative.dev/pkg/injection/clients/dynamicclient/fake"
    26  	"knative.dev/pkg/reconciler"
    27  
    28  	"knative.dev/pkg/configmap"
    29  	"knative.dev/pkg/controller"
    30  	"knative.dev/pkg/logging"
    31  	logtesting "knative.dev/pkg/logging/testing"
    32  
    33  	"k8s.io/apimachinery/pkg/runtime"
    34  	"k8s.io/apimachinery/pkg/types"
    35  	ktesting "k8s.io/client-go/testing"
    36  	"k8s.io/client-go/tools/record"
    37  
    38  	rtesting "knative.dev/pkg/reconciler/testing"
    39  )
    40  
    41  const (
    42  	// maxEventBufferSize is the estimated max number of event notifications that
    43  	// can be buffered during reconciliation.
    44  	maxEventBufferSize = 10
    45  )
    46  
    47  // Ctor functions create a k8s controller with given params.
    48  type Ctor func(context.Context, *Listers, configmap.Watcher) controller.Reconciler
    49  
    50  // MakeFactory creates a reconciler factory with fake clients and controller created by `ctor`.
    51  func MakeFactory(ctor Ctor) rtesting.Factory {
    52  	return func(t *testing.T, r *rtesting.TableRow) (
    53  		controller.Reconciler, rtesting.ActionRecorderList, rtesting.EventList,
    54  	) {
    55  		ls := NewListers(r.Objects)
    56  
    57  		ctx := r.Ctx
    58  		if ctx == nil {
    59  			ctx = context.Background()
    60  		}
    61  		logger := logtesting.TestLogger(t)
    62  		ctx = logging.WithLogger(ctx, logger)
    63  
    64  		ctx, kubeClient := fakekubeclient.With(ctx, ls.GetKubeObjects()...)
    65  		ctx, apixClient := fakeapixclient.With(ctx, ls.GetAPIExtensionsObjects()...)
    66  		ctx, dynamicClient := fakedynamicclient.With(ctx, ls.NewScheme(), r.Objects...)
    67  
    68  		// The dynamic client's support for patching is BS.  Implement it
    69  		// here via PrependReactor (this can be overridden below by the
    70  		// provided reactors).
    71  		dynamicClient.PrependReactor("patch", "*",
    72  			func(action ktesting.Action) (bool, runtime.Object, error) {
    73  				return true, nil, nil
    74  			})
    75  
    76  		eventRecorder := record.NewFakeRecorder(maxEventBufferSize)
    77  		ctx = controller.WithEventRecorder(ctx, eventRecorder)
    78  
    79  		// This is needed for the tests that use generated names and
    80  		// the object cannot be created beforehand.
    81  		kubeClient.PrependReactor("create", "*",
    82  			func(action ktesting.Action) (bool, runtime.Object, error) {
    83  				ca := action.(ktesting.CreateAction)
    84  				ls.IndexerFor(ca.GetObject()).Add(ca.GetObject())
    85  				return false, nil, nil
    86  			},
    87  		)
    88  		apixClient.PrependReactor("create", "*",
    89  			func(action ktesting.Action) (bool, runtime.Object, error) {
    90  				ca := action.(ktesting.CreateAction)
    91  				ls.IndexerFor(ca.GetObject()).Add(ca.GetObject())
    92  				return false, nil, nil
    93  			},
    94  		)
    95  
    96  		// Set up our Controller from the fakes.
    97  		c := ctor(ctx, &ls, configmap.NewStaticWatcher())
    98  		// Update the context with the stuff we decorated it with.
    99  		r.Ctx = ctx
   100  
   101  		// If the reconcilers is leader aware, then promote it.
   102  		if la, ok := c.(reconciler.LeaderAware); ok {
   103  			la.Promote(reconciler.UniversalBucket(), func(reconciler.Bucket, types.NamespacedName) {})
   104  		}
   105  
   106  		for _, reactor := range r.WithReactors {
   107  			kubeClient.PrependReactor("*", "*", reactor)
   108  			apixClient.PrependReactor("*", "*", reactor)
   109  			dynamicClient.PrependReactor("*", "*", reactor)
   110  		}
   111  
   112  		actionRecorderList := rtesting.ActionRecorderList{dynamicClient, kubeClient, apixClient}
   113  		eventList := rtesting.EventList{Recorder: eventRecorder}
   114  
   115  		return c, actionRecorderList, eventList
   116  	}
   117  }