...

Source file src/sigs.k8s.io/controller-runtime/pkg/webhook/admission/multi.go

Documentation: sigs.k8s.io/controller-runtime/pkg/webhook/admission

     1  /*
     2  Copyright 2018 The Kubernetes 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 admission
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"net/http"
    24  
    25  	jsonpatch "gomodules.xyz/jsonpatch/v2"
    26  	admissionv1 "k8s.io/api/admission/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  )
    29  
    30  type multiMutating []Handler
    31  
    32  func (hs multiMutating) Handle(ctx context.Context, req Request) Response {
    33  	patches := []jsonpatch.JsonPatchOperation{}
    34  	for _, handler := range hs {
    35  		resp := handler.Handle(ctx, req)
    36  		if !resp.Allowed {
    37  			return resp
    38  		}
    39  		if resp.PatchType != nil && *resp.PatchType != admissionv1.PatchTypeJSONPatch {
    40  			return Errored(http.StatusInternalServerError,
    41  				fmt.Errorf("unexpected patch type returned by the handler: %v, only allow: %v",
    42  					resp.PatchType, admissionv1.PatchTypeJSONPatch))
    43  		}
    44  		patches = append(patches, resp.Patches...)
    45  	}
    46  	var err error
    47  	marshaledPatch, err := json.Marshal(patches)
    48  	if err != nil {
    49  		return Errored(http.StatusBadRequest, fmt.Errorf("error when marshaling the patch: %w", err))
    50  	}
    51  	return Response{
    52  		AdmissionResponse: admissionv1.AdmissionResponse{
    53  			Allowed: true,
    54  			Result: &metav1.Status{
    55  				Code: http.StatusOK,
    56  			},
    57  			Patch:     marshaledPatch,
    58  			PatchType: func() *admissionv1.PatchType { pt := admissionv1.PatchTypeJSONPatch; return &pt }(),
    59  		},
    60  	}
    61  }
    62  
    63  // MultiMutatingHandler combines multiple mutating webhook handlers into a single
    64  // mutating webhook handler.  Handlers are called in sequential order, and the first
    65  // `allowed: false`	response may short-circuit the rest.  Users must take care to
    66  // ensure patches are disjoint.
    67  func MultiMutatingHandler(handlers ...Handler) Handler {
    68  	return multiMutating(handlers)
    69  }
    70  
    71  type multiValidating []Handler
    72  
    73  func (hs multiValidating) Handle(ctx context.Context, req Request) Response {
    74  	for _, handler := range hs {
    75  		resp := handler.Handle(ctx, req)
    76  		if !resp.Allowed {
    77  			return resp
    78  		}
    79  	}
    80  	return Response{
    81  		AdmissionResponse: admissionv1.AdmissionResponse{
    82  			Allowed: true,
    83  			Result: &metav1.Status{
    84  				Code: http.StatusOK,
    85  			},
    86  		},
    87  	}
    88  }
    89  
    90  // MultiValidatingHandler combines multiple validating webhook handlers into a single
    91  // validating webhook handler.  Handlers are called in sequential order, and the first
    92  // `allowed: false`	response may short-circuit the rest.
    93  func MultiValidatingHandler(handlers ...Handler) Handler {
    94  	return multiValidating(handlers)
    95  }
    96  

View as plain text