...

Source file src/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission.go

Documentation: k8s.io/kubernetes/plugin/pkg/admission/eventratelimit

     1  /*
     2  Copyright 2017 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 eventratelimit
    18  
    19  import (
    20  	"context"
    21  	"io"
    22  
    23  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    24  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    25  	"k8s.io/apiserver/pkg/admission"
    26  	"k8s.io/client-go/util/flowcontrol"
    27  	api "k8s.io/kubernetes/pkg/apis/core"
    28  	eventratelimitapi "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit"
    29  	"k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation"
    30  	"k8s.io/utils/clock"
    31  )
    32  
    33  // PluginName indicates name of admission plugin.
    34  const PluginName = "EventRateLimit"
    35  
    36  // Register registers a plugin
    37  func Register(plugins *admission.Plugins) {
    38  	plugins.Register(PluginName,
    39  		func(config io.Reader) (admission.Interface, error) {
    40  			// load the configuration provided (if any)
    41  			configuration, err := LoadConfiguration(config)
    42  			if err != nil {
    43  				return nil, err
    44  			}
    45  			// validate the configuration (if any)
    46  			if configuration != nil {
    47  				if errs := validation.ValidateConfiguration(configuration); len(errs) != 0 {
    48  					return nil, errs.ToAggregate()
    49  				}
    50  			}
    51  			return newEventRateLimit(configuration, clock.RealClock{})
    52  		})
    53  }
    54  
    55  // Plugin implements an admission controller that can enforce event rate limits
    56  type Plugin struct {
    57  	*admission.Handler
    58  	// limitEnforcers is the collection of limit enforcers. There is one limit enforcer for each
    59  	// active limit type. As there are 4 limit types, the length of the array will be at most 4.
    60  	// The array is read-only after construction.
    61  	limitEnforcers []*limitEnforcer
    62  }
    63  
    64  var _ admission.ValidationInterface = &Plugin{}
    65  
    66  // newEventRateLimit configures an admission controller that can enforce event rate limits
    67  func newEventRateLimit(config *eventratelimitapi.Configuration, clock flowcontrol.Clock) (*Plugin, error) {
    68  	limitEnforcers := make([]*limitEnforcer, 0, len(config.Limits))
    69  	for _, limitConfig := range config.Limits {
    70  		enforcer, err := newLimitEnforcer(limitConfig, clock)
    71  		if err != nil {
    72  			return nil, err
    73  		}
    74  		limitEnforcers = append(limitEnforcers, enforcer)
    75  	}
    76  
    77  	eventRateLimitAdmission := &Plugin{
    78  		Handler:        admission.NewHandler(admission.Create, admission.Update),
    79  		limitEnforcers: limitEnforcers,
    80  	}
    81  
    82  	return eventRateLimitAdmission, nil
    83  }
    84  
    85  // Validate makes admission decisions while enforcing event rate limits
    86  func (a *Plugin) Validate(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) (err error) {
    87  	// ignore all operations that do not correspond to an Event kind
    88  	if attr.GetKind().GroupKind() != api.Kind("Event") {
    89  		return nil
    90  	}
    91  
    92  	// ignore all requests that specify dry-run
    93  	// because they don't correspond to any calls to etcd,
    94  	// they should not be affected by the ratelimit
    95  	if attr.IsDryRun() {
    96  		return nil
    97  	}
    98  
    99  	var errors []error
   100  	// give each limit enforcer a chance to reject the event
   101  	for _, enforcer := range a.limitEnforcers {
   102  		if err := enforcer.accept(attr); err != nil {
   103  			errors = append(errors, err)
   104  		}
   105  	}
   106  
   107  	if aggregatedErr := utilerrors.NewAggregate(errors); aggregatedErr != nil {
   108  		return apierrors.NewTooManyRequestsError(aggregatedErr.Error())
   109  	}
   110  
   111  	return nil
   112  }
   113  

View as plain text