knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/webhook/psbinding/controller.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 psbinding
    18  
    19  import (
    20  	"context"
    21  
    22  	// Injection stuff
    23  	kubeclient "knative.dev/pkg/client/injection/kube/client"
    24  	mwhinformer "knative.dev/pkg/client/injection/kube/informers/admissionregistration/v1/mutatingwebhookconfiguration"
    25  	secretinformer "knative.dev/pkg/injection/clients/namespacedkube/informers/core/v1/secret"
    26  
    27  	"k8s.io/apimachinery/pkg/types"
    28  	"k8s.io/client-go/tools/cache"
    29  	"knative.dev/pkg/apis/duck"
    30  	duckv1 "knative.dev/pkg/apis/duck/v1"
    31  	"knative.dev/pkg/controller"
    32  	"knative.dev/pkg/logging"
    33  	pkgreconciler "knative.dev/pkg/reconciler"
    34  	"knative.dev/pkg/system"
    35  	"knative.dev/pkg/webhook"
    36  )
    37  
    38  // Bindable is implemented by Binding resources whose subjects are PodSpecable
    39  // and that want to leverage this shared logic to simplify binding authorship.
    40  type Bindable interface {
    41  	duck.Bindable
    42  
    43  	// Do performs this binding's mutation with the specified context on the
    44  	// provided PodSpecable.  The provided context may be decorated by
    45  	// passing a BindableContext to both NewAdmissionController and
    46  	// BaseReconciler.
    47  	Do(context.Context, *duckv1.WithPod)
    48  
    49  	// Undo is the dual of Do, it undoes the binding.
    50  	Undo(context.Context, *duckv1.WithPod)
    51  }
    52  
    53  // Mutation is the type of the Do/Undo methods.
    54  type Mutation func(context.Context, *duckv1.WithPod)
    55  
    56  // ListAll is the type of methods for enumerating all of the Bindables on the
    57  // cluster in order to index the covered types to program the admission webhook.
    58  type ListAll func() ([]Bindable, error)
    59  
    60  // GetListAll is a factory method for the ListAll method, which may also be
    61  // supplied with a ResourceEventHandler to register a callback with the Informer
    62  // that sits behind the returned ListAll so that the handler can queue work
    63  // whenever the result of ListAll changes.
    64  type GetListAll func(context.Context, cache.ResourceEventHandler) ListAll
    65  
    66  // BindableContext is the type of context decorator methods that may be supplied
    67  // to NewAdmissionController and BaseReconciler.
    68  type BindableContext func(context.Context, Bindable) (context.Context, error)
    69  
    70  var sentinel = types.NamespacedName{}
    71  
    72  // NewAdmissionController constructs the webhook portion of the pair of
    73  // reconcilers that implement the semantics of our Binding.
    74  func NewAdmissionController(
    75  	ctx context.Context,
    76  	name, path string,
    77  	gla GetListAll,
    78  	withContext BindableContext,
    79  	reconcilerOptions ...ReconcilerOption,
    80  ) *controller.Impl {
    81  	// Extract the assorted things from our context.
    82  	client := kubeclient.Get(ctx)
    83  	mwhInformer := mwhinformer.Get(ctx)
    84  	secretInformer := secretinformer.Get(ctx)
    85  	options := webhook.GetOptions(ctx)
    86  
    87  	// Construct the reconciler for the mutating webhook configuration.
    88  	wh := NewReconciler(name, path, options.SecretName, client, mwhInformer.Lister(), secretInformer.Lister(), withContext, reconcilerOptions...)
    89  	c := controller.NewContext(ctx, wh, controller.ControllerOptions{WorkQueueName: name, Logger: logging.FromContext(ctx).Named(name)})
    90  
    91  	// Enqueue a sentinel when we become leader.
    92  	wh.PromoteFunc = func(bkt pkgreconciler.Bucket, enq func(pkgreconciler.Bucket, types.NamespacedName)) error {
    93  		enq(bkt, sentinel)
    94  		return nil
    95  	}
    96  
    97  	// It doesn't matter what we enqueue because we will always Reconcile
    98  	// the named MWH resource.
    99  	handler := controller.HandleAll(c.EnqueueSentinel(sentinel))
   100  
   101  	// Reconcile when the named MutatingWebhookConfiguration changes.
   102  	mwhInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
   103  		FilterFunc: controller.FilterWithName(name),
   104  		Handler:    handler,
   105  	})
   106  
   107  	// Reconcile when the cert bundle changes.
   108  	secretInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
   109  		FilterFunc: controller.FilterWithNameAndNamespace(system.Namespace(), wh.SecretName),
   110  		Handler:    handler,
   111  	})
   112  
   113  	// Give the reconciler a way to list all of the Bindable resources,
   114  	// and configure the controller to handle changes to those resources.
   115  	wh.ListAll = gla(ctx, handler)
   116  
   117  	return c
   118  }