mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 01:38:10 +00:00
vendor: revendor
This commit is contained in:
parent
269295a414
commit
9f0440be0f
669 changed files with 58447 additions and 20021 deletions
2
vendor/k8s.io/apiserver/pkg/util/apihelpers/helpers.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/util/apihelpers/helpers.go
generated
vendored
|
|
@ -19,7 +19,7 @@ package apihelpers
|
|||
import (
|
||||
"sort"
|
||||
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1alpha1"
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1beta1"
|
||||
)
|
||||
|
||||
// SetFlowSchemaCondition sets conditions.
|
||||
|
|
|
|||
169
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller.go
generated
vendored
169
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller.go
generated
vendored
|
|
@ -47,9 +47,9 @@ import (
|
|||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
fctypesv1a1 "k8s.io/api/flowcontrol/v1alpha1"
|
||||
fcclientv1a1 "k8s.io/client-go/kubernetes/typed/flowcontrol/v1alpha1"
|
||||
fclistersv1a1 "k8s.io/client-go/listers/flowcontrol/v1alpha1"
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1beta1"
|
||||
flowcontrolclient "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta1"
|
||||
flowcontrollister "k8s.io/client-go/listers/flowcontrol/v1beta1"
|
||||
)
|
||||
|
||||
// This file contains a simple local (to the apiserver) controller
|
||||
|
|
@ -91,13 +91,13 @@ type configController struct {
|
|||
// objects need to be reprocessed.
|
||||
configQueue workqueue.RateLimitingInterface
|
||||
|
||||
plLister fclistersv1a1.PriorityLevelConfigurationLister
|
||||
plLister flowcontrollister.PriorityLevelConfigurationLister
|
||||
plInformerSynced cache.InformerSynced
|
||||
|
||||
fsLister fclistersv1a1.FlowSchemaLister
|
||||
fsLister flowcontrollister.FlowSchemaLister
|
||||
fsInformerSynced cache.InformerSynced
|
||||
|
||||
flowcontrolClient fcclientv1a1.FlowcontrolV1alpha1Interface
|
||||
flowcontrolClient flowcontrolclient.FlowcontrolV1beta1Interface
|
||||
|
||||
// serverConcurrencyLimit is the limit on the server's total
|
||||
// number of non-exempt requests being served at once. This comes
|
||||
|
|
@ -127,7 +127,7 @@ type configController struct {
|
|||
type priorityLevelState struct {
|
||||
// the API object or prototype prescribing this level. Nothing
|
||||
// reached through this pointer is mutable.
|
||||
pl *fctypesv1a1.PriorityLevelConfiguration
|
||||
pl *flowcontrol.PriorityLevelConfiguration
|
||||
|
||||
// qsCompleter holds the QueueSetCompleter derived from `config`
|
||||
// and `queues` if config is not exempt, nil otherwise.
|
||||
|
|
@ -153,7 +153,7 @@ type priorityLevelState struct {
|
|||
// NewTestableController is extra flexible to facilitate testing
|
||||
func newTestableController(
|
||||
informerFactory kubeinformers.SharedInformerFactory,
|
||||
flowcontrolClient fcclientv1a1.FlowcontrolV1alpha1Interface,
|
||||
flowcontrolClient flowcontrolclient.FlowcontrolV1beta1Interface,
|
||||
serverConcurrencyLimit int,
|
||||
requestWaitLimit time.Duration,
|
||||
obsPairGenerator metrics.TimedObserverPairGenerator,
|
||||
|
|
@ -178,7 +178,7 @@ func newTestableController(
|
|||
// config API objects.
|
||||
func (cfgCtlr *configController) initializeConfigController(informerFactory kubeinformers.SharedInformerFactory) {
|
||||
cfgCtlr.configQueue = workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(200*time.Millisecond, 8*time.Hour), "priority_and_fairness_config_queue")
|
||||
fci := informerFactory.Flowcontrol().V1alpha1()
|
||||
fci := informerFactory.Flowcontrol().V1beta1()
|
||||
pli := fci.PriorityLevelConfigurations()
|
||||
fsi := fci.FlowSchemas()
|
||||
cfgCtlr.plLister = pli.Lister()
|
||||
|
|
@ -187,13 +187,13 @@ func (cfgCtlr *configController) initializeConfigController(informerFactory kube
|
|||
cfgCtlr.fsInformerSynced = fsi.Informer().HasSynced
|
||||
pli.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
pl := obj.(*fctypesv1a1.PriorityLevelConfiguration)
|
||||
pl := obj.(*flowcontrol.PriorityLevelConfiguration)
|
||||
klog.V(7).Infof("Triggered API priority and fairness config reloading due to creation of PLC %s", pl.Name)
|
||||
cfgCtlr.configQueue.Add(0)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
newPL := newObj.(*fctypesv1a1.PriorityLevelConfiguration)
|
||||
oldPL := oldObj.(*fctypesv1a1.PriorityLevelConfiguration)
|
||||
newPL := newObj.(*flowcontrol.PriorityLevelConfiguration)
|
||||
oldPL := oldObj.(*flowcontrol.PriorityLevelConfiguration)
|
||||
if !apiequality.Semantic.DeepEqual(oldPL.Spec, newPL.Spec) {
|
||||
klog.V(7).Infof("Triggered API priority and fairness config reloading due to spec update of PLC %s", newPL.Name)
|
||||
cfgCtlr.configQueue.Add(0)
|
||||
|
|
@ -207,13 +207,13 @@ func (cfgCtlr *configController) initializeConfigController(informerFactory kube
|
|||
}})
|
||||
fsi.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
fs := obj.(*fctypesv1a1.FlowSchema)
|
||||
fs := obj.(*flowcontrol.FlowSchema)
|
||||
klog.V(7).Infof("Triggered API priority and fairness config reloading due to creation of FS %s", fs.Name)
|
||||
cfgCtlr.configQueue.Add(0)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
newFS := newObj.(*fctypesv1a1.FlowSchema)
|
||||
oldFS := oldObj.(*fctypesv1a1.FlowSchema)
|
||||
newFS := newObj.(*flowcontrol.FlowSchema)
|
||||
oldFS := oldObj.(*flowcontrol.FlowSchema)
|
||||
if !apiequality.Semantic.DeepEqual(oldFS.Spec, newFS.Spec) {
|
||||
klog.V(7).Infof("Triggered API priority and fairness config reloading due to spec update of FS %s", newFS.Name)
|
||||
cfgCtlr.configQueue.Add(0)
|
||||
|
|
@ -332,14 +332,14 @@ type cfgMeal struct {
|
|||
|
||||
// A buffered set of status updates for a FlowSchema
|
||||
type fsStatusUpdate struct {
|
||||
flowSchema *fctypesv1a1.FlowSchema
|
||||
condition fctypesv1a1.FlowSchemaCondition
|
||||
oldValue fctypesv1a1.FlowSchemaCondition
|
||||
flowSchema *flowcontrol.FlowSchema
|
||||
condition flowcontrol.FlowSchemaCondition
|
||||
oldValue flowcontrol.FlowSchemaCondition
|
||||
}
|
||||
|
||||
// digestConfigObjects is given all the API objects that configure
|
||||
// cfgCtlr and writes its consequent new configState.
|
||||
func (cfgCtlr *configController) digestConfigObjects(newPLs []*fctypesv1a1.PriorityLevelConfiguration, newFSs []*fctypesv1a1.FlowSchema) error {
|
||||
func (cfgCtlr *configController) digestConfigObjects(newPLs []*flowcontrol.PriorityLevelConfiguration, newFSs []*flowcontrol.FlowSchema) error {
|
||||
fsStatusUpdates := cfgCtlr.lockAndDigestConfigObjects(newPLs, newFSs)
|
||||
var errs []error
|
||||
for _, fsu := range fsStatusUpdates {
|
||||
|
|
@ -360,7 +360,7 @@ func (cfgCtlr *configController) digestConfigObjects(newPLs []*fctypesv1a1.Prior
|
|||
return apierrors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func (cfgCtlr *configController) lockAndDigestConfigObjects(newPLs []*fctypesv1a1.PriorityLevelConfiguration, newFSs []*fctypesv1a1.FlowSchema) []fsStatusUpdate {
|
||||
func (cfgCtlr *configController) lockAndDigestConfigObjects(newPLs []*flowcontrol.PriorityLevelConfiguration, newFSs []*flowcontrol.FlowSchema) []fsStatusUpdate {
|
||||
cfgCtlr.lock.Lock()
|
||||
defer cfgCtlr.lock.Unlock()
|
||||
meal := cfgMeal{
|
||||
|
|
@ -390,7 +390,7 @@ func (cfgCtlr *configController) lockAndDigestConfigObjects(newPLs []*fctypesv1a
|
|||
|
||||
// Digest the new set of PriorityLevelConfiguration objects.
|
||||
// Pretend broken ones do not exist.
|
||||
func (meal *cfgMeal) digestNewPLsLocked(newPLs []*fctypesv1a1.PriorityLevelConfiguration) {
|
||||
func (meal *cfgMeal) digestNewPLsLocked(newPLs []*flowcontrol.PriorityLevelConfiguration) {
|
||||
for _, pl := range newPLs {
|
||||
state := meal.cfgCtlr.priorityLevelStates[pl.Name]
|
||||
if state == nil {
|
||||
|
|
@ -411,8 +411,8 @@ func (meal *cfgMeal) digestNewPLsLocked(newPLs []*fctypesv1a1.PriorityLevelConfi
|
|||
if state.pl.Spec.Limited != nil {
|
||||
meal.shareSum += float64(state.pl.Spec.Limited.AssuredConcurrencyShares)
|
||||
}
|
||||
meal.haveExemptPL = meal.haveExemptPL || pl.Name == fctypesv1a1.PriorityLevelConfigurationNameExempt
|
||||
meal.haveCatchAllPL = meal.haveCatchAllPL || pl.Name == fctypesv1a1.PriorityLevelConfigurationNameCatchAll
|
||||
meal.haveExemptPL = meal.haveExemptPL || pl.Name == flowcontrol.PriorityLevelConfigurationNameExempt
|
||||
meal.haveCatchAllPL = meal.haveCatchAllPL || pl.Name == flowcontrol.PriorityLevelConfigurationNameCatchAll
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,9 +423,9 @@ func (meal *cfgMeal) digestNewPLsLocked(newPLs []*fctypesv1a1.PriorityLevelConfi
|
|||
// reflect this. This function also adds any missing mandatory
|
||||
// FlowSchema objects. The given objects must all have distinct
|
||||
// names.
|
||||
func (meal *cfgMeal) digestFlowSchemasLocked(newFSs []*fctypesv1a1.FlowSchema) {
|
||||
func (meal *cfgMeal) digestFlowSchemasLocked(newFSs []*flowcontrol.FlowSchema) {
|
||||
fsSeq := make(apihelpers.FlowSchemaSequence, 0, len(newFSs))
|
||||
fsMap := make(map[string]*fctypesv1a1.FlowSchema, len(newFSs))
|
||||
fsMap := make(map[string]*flowcontrol.FlowSchema, len(newFSs))
|
||||
var haveExemptFS, haveCatchAllFS bool
|
||||
for i, fs := range newFSs {
|
||||
otherFS := fsMap[fs.Name]
|
||||
|
|
@ -448,8 +448,8 @@ func (meal *cfgMeal) digestFlowSchemasLocked(newFSs []*fctypesv1a1.FlowSchema) {
|
|||
continue
|
||||
}
|
||||
fsSeq = append(fsSeq, newFSs[i])
|
||||
haveExemptFS = haveExemptFS || fs.Name == fctypesv1a1.FlowSchemaNameExempt
|
||||
haveCatchAllFS = haveCatchAllFS || fs.Name == fctypesv1a1.FlowSchemaNameCatchAll
|
||||
haveExemptFS = haveExemptFS || fs.Name == flowcontrol.FlowSchemaNameExempt
|
||||
haveCatchAllFS = haveCatchAllFS || fs.Name == flowcontrol.FlowSchemaNameCatchAll
|
||||
}
|
||||
// sort into the order to be used for matching
|
||||
sort.Sort(fsSeq)
|
||||
|
|
@ -481,7 +481,7 @@ func (meal *cfgMeal) processOldPLsLocked() {
|
|||
// Still desired and already updated
|
||||
continue
|
||||
}
|
||||
if plName == fctypesv1a1.PriorityLevelConfigurationNameExempt && !meal.haveExemptPL || plName == fctypesv1a1.PriorityLevelConfigurationNameCatchAll && !meal.haveCatchAllPL {
|
||||
if plName == flowcontrol.PriorityLevelConfigurationNameExempt && !meal.haveExemptPL || plName == flowcontrol.PriorityLevelConfigurationNameCatchAll && !meal.haveCatchAllPL {
|
||||
// BTW, we know the Spec has not changed because the
|
||||
// mandatory objects have immutable Specs
|
||||
klog.V(3).Infof("Retaining mandatory priority level %q despite lack of API object", plName)
|
||||
|
|
@ -513,8 +513,8 @@ func (meal *cfgMeal) processOldPLsLocked() {
|
|||
// regular way.
|
||||
meal.shareSum += float64(plState.pl.Spec.Limited.AssuredConcurrencyShares)
|
||||
}
|
||||
meal.haveExemptPL = meal.haveExemptPL || plName == fctypesv1a1.PriorityLevelConfigurationNameExempt
|
||||
meal.haveCatchAllPL = meal.haveCatchAllPL || plName == fctypesv1a1.PriorityLevelConfigurationNameCatchAll
|
||||
meal.haveExemptPL = meal.haveExemptPL || plName == flowcontrol.PriorityLevelConfigurationNameExempt
|
||||
meal.haveCatchAllPL = meal.haveCatchAllPL || plName == flowcontrol.PriorityLevelConfigurationNameCatchAll
|
||||
meal.newPLStates[plName] = plState
|
||||
}
|
||||
}
|
||||
|
|
@ -548,18 +548,18 @@ func (meal *cfgMeal) finishQueueSetReconfigsLocked() {
|
|||
// given priority level configuration. Returns nil if that config
|
||||
// does not call for limiting. Returns nil and an error if the given
|
||||
// object is malformed in a way that is a problem for this package.
|
||||
func queueSetCompleterForPL(qsf fq.QueueSetFactory, queues fq.QueueSet, pl *fctypesv1a1.PriorityLevelConfiguration, requestWaitLimit time.Duration, intPair metrics.TimedObserverPair) (fq.QueueSetCompleter, error) {
|
||||
if (pl.Spec.Type == fctypesv1a1.PriorityLevelEnablementExempt) != (pl.Spec.Limited == nil) {
|
||||
func queueSetCompleterForPL(qsf fq.QueueSetFactory, queues fq.QueueSet, pl *flowcontrol.PriorityLevelConfiguration, requestWaitLimit time.Duration, intPair metrics.TimedObserverPair) (fq.QueueSetCompleter, error) {
|
||||
if (pl.Spec.Type == flowcontrol.PriorityLevelEnablementExempt) != (pl.Spec.Limited == nil) {
|
||||
return nil, errors.New("broken union structure at the top")
|
||||
}
|
||||
if (pl.Spec.Type == fctypesv1a1.PriorityLevelEnablementExempt) != (pl.Name == fctypesv1a1.PriorityLevelConfigurationNameExempt) {
|
||||
if (pl.Spec.Type == flowcontrol.PriorityLevelEnablementExempt) != (pl.Name == flowcontrol.PriorityLevelConfigurationNameExempt) {
|
||||
// This package does not attempt to cope with a priority level dynamically switching between exempt and not.
|
||||
return nil, errors.New("non-alignment between name and type")
|
||||
}
|
||||
if pl.Spec.Limited == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if (pl.Spec.Limited.LimitResponse.Type == fctypesv1a1.LimitResponseTypeReject) != (pl.Spec.Limited.LimitResponse.Queuing == nil) {
|
||||
if (pl.Spec.Limited.LimitResponse.Type == flowcontrol.LimitResponseTypeReject) != (pl.Spec.Limited.LimitResponse.Queuing == nil) {
|
||||
return nil, errors.New("broken union structure for limit response")
|
||||
}
|
||||
qcAPI := pl.Spec.Limited.LimitResponse.Queuing
|
||||
|
|
@ -585,17 +585,17 @@ func queueSetCompleterForPL(qsf fq.QueueSetFactory, queues fq.QueueSet, pl *fcty
|
|||
return qsc, err
|
||||
}
|
||||
|
||||
func (meal *cfgMeal) presyncFlowSchemaStatus(fs *fctypesv1a1.FlowSchema, isDangling bool, plName string) {
|
||||
danglingCondition := apihelpers.GetFlowSchemaConditionByType(fs, fctypesv1a1.FlowSchemaConditionDangling)
|
||||
func (meal *cfgMeal) presyncFlowSchemaStatus(fs *flowcontrol.FlowSchema, isDangling bool, plName string) {
|
||||
danglingCondition := apihelpers.GetFlowSchemaConditionByType(fs, flowcontrol.FlowSchemaConditionDangling)
|
||||
if danglingCondition == nil {
|
||||
danglingCondition = &fctypesv1a1.FlowSchemaCondition{
|
||||
Type: fctypesv1a1.FlowSchemaConditionDangling,
|
||||
danglingCondition = &flowcontrol.FlowSchemaCondition{
|
||||
Type: flowcontrol.FlowSchemaConditionDangling,
|
||||
}
|
||||
}
|
||||
desiredStatus := fctypesv1a1.ConditionFalse
|
||||
desiredStatus := flowcontrol.ConditionFalse
|
||||
var desiredReason, desiredMessage string
|
||||
if isDangling {
|
||||
desiredStatus = fctypesv1a1.ConditionTrue
|
||||
desiredStatus = flowcontrol.ConditionTrue
|
||||
desiredReason = "NotFound"
|
||||
desiredMessage = fmt.Sprintf("This FlowSchema references the PriorityLevelConfiguration object named %q but there is no such object", plName)
|
||||
} else {
|
||||
|
|
@ -607,8 +607,8 @@ func (meal *cfgMeal) presyncFlowSchemaStatus(fs *fctypesv1a1.FlowSchema, isDangl
|
|||
}
|
||||
meal.fsStatusUpdates = append(meal.fsStatusUpdates, fsStatusUpdate{
|
||||
flowSchema: fs,
|
||||
condition: fctypesv1a1.FlowSchemaCondition{
|
||||
Type: fctypesv1a1.FlowSchemaConditionDangling,
|
||||
condition: flowcontrol.FlowSchemaCondition{
|
||||
Type: flowcontrol.FlowSchemaConditionDangling,
|
||||
Status: desiredStatus,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: desiredReason,
|
||||
|
|
@ -619,7 +619,7 @@ func (meal *cfgMeal) presyncFlowSchemaStatus(fs *fctypesv1a1.FlowSchema, isDangl
|
|||
|
||||
// imaginePL adds a priority level based on one of the mandatory ones
|
||||
// that does not actually exist (right now) as a real API object.
|
||||
func (meal *cfgMeal) imaginePL(proto *fctypesv1a1.PriorityLevelConfiguration, requestWaitLimit time.Duration) {
|
||||
func (meal *cfgMeal) imaginePL(proto *flowcontrol.PriorityLevelConfiguration, requestWaitLimit time.Duration) {
|
||||
klog.V(3).Infof("No %s PriorityLevelConfiguration found, imagining one", proto.Name)
|
||||
obsPair := meal.cfgCtlr.obsPairGenerator.Generate(1, 1, []string{proto.Name})
|
||||
qsCompleter, err := queueSetCompleterForPL(meal.cfgCtlr.queueSetFactory, nil, proto, requestWaitLimit, obsPair)
|
||||
|
|
@ -651,48 +651,59 @@ func (immediateRequest) Finish(execute func()) bool {
|
|||
// The returned bool indicates whether the request is exempt from
|
||||
// limitation. The startWaitingTime is when the request started
|
||||
// waiting in its queue, or `Time{}` if this did not happen.
|
||||
func (cfgCtlr *configController) startRequest(ctx context.Context, rd RequestDigest, queueNoteFn fq.QueueNoteFn) (fs *fctypesv1a1.FlowSchema, pl *fctypesv1a1.PriorityLevelConfiguration, isExempt bool, req fq.Request, startWaitingTime time.Time) {
|
||||
func (cfgCtlr *configController) startRequest(ctx context.Context, rd RequestDigest, queueNoteFn fq.QueueNoteFn) (fs *flowcontrol.FlowSchema, pl *flowcontrol.PriorityLevelConfiguration, isExempt bool, req fq.Request, startWaitingTime time.Time) {
|
||||
klog.V(7).Infof("startRequest(%#+v)", rd)
|
||||
cfgCtlr.lock.Lock()
|
||||
defer cfgCtlr.lock.Unlock()
|
||||
var selectedFlowSchema *flowcontrol.FlowSchema
|
||||
for _, fs := range cfgCtlr.flowSchemas {
|
||||
if matchesFlowSchema(rd, fs) {
|
||||
plName := fs.Spec.PriorityLevelConfiguration.Name
|
||||
plState := cfgCtlr.priorityLevelStates[plName]
|
||||
if plState.pl.Spec.Type == fctypesv1a1.PriorityLevelEnablementExempt {
|
||||
klog.V(7).Infof("startRequest(%#+v) => fsName=%q, distMethod=%#+v, plName=%q, immediate", rd, fs.Name, fs.Spec.DistinguisherMethod, plName)
|
||||
return fs, plState.pl, true, immediateRequest{}, time.Time{}
|
||||
}
|
||||
var numQueues int32
|
||||
if plState.pl.Spec.Limited.LimitResponse.Type == fctypesv1a1.LimitResponseTypeQueue {
|
||||
numQueues = plState.pl.Spec.Limited.LimitResponse.Queuing.Queues
|
||||
|
||||
}
|
||||
var flowDistinguisher string
|
||||
var hashValue uint64
|
||||
if numQueues > 1 {
|
||||
flowDistinguisher = computeFlowDistinguisher(rd, fs.Spec.DistinguisherMethod)
|
||||
hashValue = hashFlowID(fs.Name, flowDistinguisher)
|
||||
}
|
||||
startWaitingTime = time.Now()
|
||||
klog.V(7).Infof("startRequest(%#+v) => fsName=%q, distMethod=%#+v, plName=%q, numQueues=%d", rd, fs.Name, fs.Spec.DistinguisherMethod, plName, numQueues)
|
||||
req, idle := plState.queues.StartRequest(ctx, hashValue, flowDistinguisher, fs.Name, rd.RequestInfo, rd.User, queueNoteFn)
|
||||
if idle {
|
||||
cfgCtlr.maybeReapLocked(plName, plState)
|
||||
}
|
||||
return fs, plState.pl, false, req, startWaitingTime
|
||||
selectedFlowSchema = fs
|
||||
break
|
||||
}
|
||||
}
|
||||
// This can never happen because every configState has a
|
||||
// FlowSchema that matches everything. If somehow control reaches
|
||||
// here, panic with some relevant information.
|
||||
var catchAll *fctypesv1a1.FlowSchema
|
||||
for _, fs := range cfgCtlr.flowSchemas {
|
||||
if fs.Name == fctypesv1a1.FlowSchemaNameCatchAll {
|
||||
catchAll = fs
|
||||
if selectedFlowSchema == nil {
|
||||
// This should never happen. If the requestDigest's User is a part of
|
||||
// system:authenticated or system:unauthenticated, the catch-all flow
|
||||
// schema should match it. However, if that invariant somehow fails,
|
||||
// fallback to the catch-all flow schema anyway.
|
||||
for _, fs := range cfgCtlr.flowSchemas {
|
||||
if fs.Name == flowcontrol.FlowSchemaNameCatchAll {
|
||||
selectedFlowSchema = fs
|
||||
break
|
||||
}
|
||||
}
|
||||
if selectedFlowSchema == nil {
|
||||
// This should absolutely never, ever happen! APF guarantees two
|
||||
// undeletable flow schemas at all times: an exempt flow schema and a
|
||||
// catch-all flow schema.
|
||||
panic(fmt.Sprintf("no fallback catch-all flow schema found for request %#+v and user %#+v", rd.RequestInfo, rd.User))
|
||||
}
|
||||
klog.Warningf("no match found for request %#+v and user %#+v; selecting catchAll=%s as fallback flow schema", rd.RequestInfo, rd.User, fcfmt.Fmt(selectedFlowSchema))
|
||||
}
|
||||
panic(fmt.Sprintf("No match; rd=%#+v, catchAll=%s", rd, fcfmt.Fmt(catchAll)))
|
||||
plName := selectedFlowSchema.Spec.PriorityLevelConfiguration.Name
|
||||
plState := cfgCtlr.priorityLevelStates[plName]
|
||||
if plState.pl.Spec.Type == flowcontrol.PriorityLevelEnablementExempt {
|
||||
klog.V(7).Infof("startRequest(%#+v) => fsName=%q, distMethod=%#+v, plName=%q, immediate", rd, selectedFlowSchema.Name, selectedFlowSchema.Spec.DistinguisherMethod, plName)
|
||||
return selectedFlowSchema, plState.pl, true, immediateRequest{}, time.Time{}
|
||||
}
|
||||
var numQueues int32
|
||||
if plState.pl.Spec.Limited.LimitResponse.Type == flowcontrol.LimitResponseTypeQueue {
|
||||
numQueues = plState.pl.Spec.Limited.LimitResponse.Queuing.Queues
|
||||
}
|
||||
var flowDistinguisher string
|
||||
var hashValue uint64
|
||||
if numQueues > 1 {
|
||||
flowDistinguisher = computeFlowDistinguisher(rd, selectedFlowSchema.Spec.DistinguisherMethod)
|
||||
hashValue = hashFlowID(selectedFlowSchema.Name, flowDistinguisher)
|
||||
}
|
||||
startWaitingTime = time.Now()
|
||||
klog.V(7).Infof("startRequest(%#+v) => fsName=%q, distMethod=%#+v, plName=%q, numQueues=%d", rd, selectedFlowSchema.Name, selectedFlowSchema.Spec.DistinguisherMethod, plName, numQueues)
|
||||
req, idle := plState.queues.StartRequest(ctx, hashValue, flowDistinguisher, selectedFlowSchema.Name, rd.RequestInfo, rd.User, queueNoteFn)
|
||||
if idle {
|
||||
cfgCtlr.maybeReapLocked(plName, plState)
|
||||
}
|
||||
return selectedFlowSchema, plState.pl, false, req, startWaitingTime
|
||||
}
|
||||
|
||||
// Call this after getting a clue that the given priority level is undesired and idle
|
||||
|
|
@ -726,14 +737,14 @@ func (cfgCtlr *configController) maybeReapLocked(plName string, plState *priorit
|
|||
}
|
||||
|
||||
// computeFlowDistinguisher extracts the flow distinguisher according to the given method
|
||||
func computeFlowDistinguisher(rd RequestDigest, method *fctypesv1a1.FlowDistinguisherMethod) string {
|
||||
func computeFlowDistinguisher(rd RequestDigest, method *flowcontrol.FlowDistinguisherMethod) string {
|
||||
if method == nil {
|
||||
return ""
|
||||
}
|
||||
switch method.Type {
|
||||
case fctypesv1a1.FlowDistinguisherMethodByUserType:
|
||||
case flowcontrol.FlowDistinguisherMethodByUserType:
|
||||
return rd.User.GetName()
|
||||
case fctypesv1a1.FlowDistinguisherMethodByNamespaceType:
|
||||
case flowcontrol.FlowDistinguisherMethodByNamespaceType:
|
||||
return rd.RequestInfo.Namespace
|
||||
default:
|
||||
// this line shall never reach
|
||||
|
|
|
|||
22
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller_debug.go
generated
vendored
22
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller_debug.go
generated
vendored
|
|
@ -164,28 +164,6 @@ func (cfgCtlr *configController) dumpRequests(w http.ResponseWriter, r *http.Req
|
|||
endLine(tabWriter)
|
||||
for _, plState := range cfgCtlr.priorityLevelStates {
|
||||
if plState.queues == nil {
|
||||
tabPrint(tabWriter, row(
|
||||
plState.pl.Name, // 1
|
||||
"<none>", // 2
|
||||
"<none>", // 3
|
||||
"<none>", // 4
|
||||
"<none>", // 5
|
||||
"<none>", // 6
|
||||
))
|
||||
if includeRequestDetails {
|
||||
continueLine(tabWriter)
|
||||
tabPrint(tabWriter, row(
|
||||
"<none>", // 7
|
||||
"<none>", // 8
|
||||
"<none>", // 9
|
||||
"<none>", // 10
|
||||
"<none>", // 11
|
||||
"<none>", // 12
|
||||
"<none>", // 13
|
||||
"<none>", // 14
|
||||
))
|
||||
}
|
||||
endLine(tabWriter)
|
||||
continue
|
||||
}
|
||||
queueSetDigest := plState.queues.Dump(includeRequestDetails)
|
||||
|
|
|
|||
12
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_filter.go
generated
vendored
12
vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_filter.go
generated
vendored
|
|
@ -30,8 +30,8 @@ import (
|
|||
kubeinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
fctypesv1a1 "k8s.io/api/flowcontrol/v1alpha1"
|
||||
fcclientv1a1 "k8s.io/client-go/kubernetes/typed/flowcontrol/v1alpha1"
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1beta1"
|
||||
flowcontrolclient "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta1"
|
||||
)
|
||||
|
||||
// Interface defines how the API Priority and Fairness filter interacts with the underlying system.
|
||||
|
|
@ -47,7 +47,7 @@ type Interface interface {
|
|||
// not be invoked.
|
||||
Handle(ctx context.Context,
|
||||
requestDigest RequestDigest,
|
||||
noteFn func(fs *fctypesv1a1.FlowSchema, pl *fctypesv1a1.PriorityLevelConfiguration),
|
||||
noteFn func(fs *flowcontrol.FlowSchema, pl *flowcontrol.PriorityLevelConfiguration),
|
||||
queueNoteFn fq.QueueNoteFn,
|
||||
execFn func(),
|
||||
)
|
||||
|
|
@ -69,7 +69,7 @@ type Interface interface {
|
|||
// New creates a new instance to implement API priority and fairness
|
||||
func New(
|
||||
informerFactory kubeinformers.SharedInformerFactory,
|
||||
flowcontrolClient fcclientv1a1.FlowcontrolV1alpha1Interface,
|
||||
flowcontrolClient flowcontrolclient.FlowcontrolV1beta1Interface,
|
||||
serverConcurrencyLimit int,
|
||||
requestWaitLimit time.Duration,
|
||||
) Interface {
|
||||
|
|
@ -87,7 +87,7 @@ func New(
|
|||
// NewTestable is extra flexible to facilitate testing
|
||||
func NewTestable(
|
||||
informerFactory kubeinformers.SharedInformerFactory,
|
||||
flowcontrolClient fcclientv1a1.FlowcontrolV1alpha1Interface,
|
||||
flowcontrolClient flowcontrolclient.FlowcontrolV1beta1Interface,
|
||||
serverConcurrencyLimit int,
|
||||
requestWaitLimit time.Duration,
|
||||
obsPairGenerator metrics.TimedObserverPairGenerator,
|
||||
|
|
@ -97,7 +97,7 @@ func NewTestable(
|
|||
}
|
||||
|
||||
func (cfgCtlr *configController) Handle(ctx context.Context, requestDigest RequestDigest,
|
||||
noteFn func(fs *fctypesv1a1.FlowSchema, pl *fctypesv1a1.PriorityLevelConfiguration),
|
||||
noteFn func(fs *flowcontrol.FlowSchema, pl *flowcontrol.PriorityLevelConfiguration),
|
||||
queueNoteFn fq.QueueNoteFn,
|
||||
execFn func()) {
|
||||
fs, pl, isExempt, req, startWaitingTime := cfgCtlr.startRequest(ctx, requestDigest, queueNoteFn)
|
||||
|
|
|
|||
3
vendor/k8s.io/apiserver/pkg/util/flowcontrol/debug/dump.go
generated
vendored
3
vendor/k8s.io/apiserver/pkg/util/flowcontrol/debug/dump.go
generated
vendored
|
|
@ -17,8 +17,9 @@ limitations under the License.
|
|||
package debug
|
||||
|
||||
import (
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"time"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// QueueSetDump is an instant dump of queue-set.
|
||||
|
|
|
|||
18
vendor/k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset/queueset.go
generated
vendored
18
vendor/k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset/queueset.go
generated
vendored
|
|
@ -645,6 +645,7 @@ func (qs *queueSet) selectQueueLocked() *queue {
|
|||
qs.robinIndex = (qs.robinIndex + 1) % nq
|
||||
queue := qs.queues[qs.robinIndex]
|
||||
if len(queue.requests) != 0 {
|
||||
|
||||
currentVirtualFinish := queue.GetVirtualFinish(0, qs.estimatedServiceTime)
|
||||
if currentVirtualFinish < minVirtualFinish {
|
||||
minVirtualFinish = currentVirtualFinish
|
||||
|
|
@ -657,6 +658,23 @@ func (qs *queueSet) selectQueueLocked() *queue {
|
|||
// for the next round. This way the non-selected queues
|
||||
// win in the case that the virtual finish times are the same
|
||||
qs.robinIndex = minIndex
|
||||
// according to the original FQ formula:
|
||||
//
|
||||
// Si = MAX(R(t), Fi-1)
|
||||
//
|
||||
// the virtual start (excluding the estimated cost) of the chose
|
||||
// queue should always be greater or equal to the global virtual
|
||||
// time.
|
||||
//
|
||||
// hence we're refreshing the per-queue virtual time for the chosen
|
||||
// queue here. if the last virtual start time (excluded estimated cost)
|
||||
// falls behind the global virtual time, we update the latest virtual
|
||||
// start by: <latest global virtual time> + <previously estimated cost>
|
||||
previouslyEstimatedServiceTime := float64(minQueue.requestsExecuting) * qs.estimatedServiceTime
|
||||
if qs.virtualTime > minQueue.virtualStart-previouslyEstimatedServiceTime {
|
||||
// per-queue virtual time should not fall behind the global
|
||||
minQueue.virtualStart = qs.virtualTime + previouslyEstimatedServiceTime
|
||||
}
|
||||
return minQueue
|
||||
}
|
||||
|
||||
|
|
|
|||
74
vendor/k8s.io/apiserver/pkg/util/flowcontrol/format/formatting.go
generated
vendored
74
vendor/k8s.io/apiserver/pkg/util/flowcontrol/format/formatting.go
generated
vendored
|
|
@ -21,7 +21,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
fcv1a1 "k8s.io/api/flowcontrol/v1alpha1"
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1beta1"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
|
@ -46,25 +46,25 @@ func (sr Stringer) String() string {
|
|||
return "nil"
|
||||
}
|
||||
switch typed := sr.val.(type) {
|
||||
case *fcv1a1.FlowSchema,
|
||||
fcv1a1.FlowSchema,
|
||||
fcv1a1.FlowSchemaSpec,
|
||||
fcv1a1.FlowDistinguisherMethod,
|
||||
*fcv1a1.FlowDistinguisherMethod,
|
||||
*fcv1a1.PolicyRulesWithSubjects,
|
||||
fcv1a1.PolicyRulesWithSubjects,
|
||||
fcv1a1.Subject,
|
||||
fcv1a1.ResourcePolicyRule,
|
||||
fcv1a1.NonResourcePolicyRule,
|
||||
fcv1a1.FlowSchemaCondition,
|
||||
*fcv1a1.PriorityLevelConfiguration,
|
||||
fcv1a1.PriorityLevelConfiguration,
|
||||
fcv1a1.PriorityLevelConfigurationSpec,
|
||||
*fcv1a1.LimitedPriorityLevelConfiguration,
|
||||
fcv1a1.LimitedPriorityLevelConfiguration,
|
||||
fcv1a1.LimitResponse,
|
||||
*fcv1a1.QueuingConfiguration,
|
||||
fcv1a1.QueuingConfiguration:
|
||||
case *flowcontrol.FlowSchema,
|
||||
flowcontrol.FlowSchema,
|
||||
flowcontrol.FlowSchemaSpec,
|
||||
flowcontrol.FlowDistinguisherMethod,
|
||||
*flowcontrol.FlowDistinguisherMethod,
|
||||
*flowcontrol.PolicyRulesWithSubjects,
|
||||
flowcontrol.PolicyRulesWithSubjects,
|
||||
flowcontrol.Subject,
|
||||
flowcontrol.ResourcePolicyRule,
|
||||
flowcontrol.NonResourcePolicyRule,
|
||||
flowcontrol.FlowSchemaCondition,
|
||||
*flowcontrol.PriorityLevelConfiguration,
|
||||
flowcontrol.PriorityLevelConfiguration,
|
||||
flowcontrol.PriorityLevelConfigurationSpec,
|
||||
*flowcontrol.LimitedPriorityLevelConfiguration,
|
||||
flowcontrol.LimitedPriorityLevelConfiguration,
|
||||
flowcontrol.LimitResponse,
|
||||
*flowcontrol.QueuingConfiguration,
|
||||
flowcontrol.QueuingConfiguration:
|
||||
return ToJSON(sr.val)
|
||||
case []user.Info:
|
||||
return FmtUsers(typed)
|
||||
|
|
@ -88,12 +88,12 @@ func ToJSON(val interface{}) string {
|
|||
|
||||
// FmtPriorityLevelConfiguration returns a golang source expression
|
||||
// equivalent to the given value
|
||||
func FmtPriorityLevelConfiguration(pl *fcv1a1.PriorityLevelConfiguration) string {
|
||||
func FmtPriorityLevelConfiguration(pl *flowcontrol.PriorityLevelConfiguration) string {
|
||||
if pl == nil {
|
||||
return "nil"
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(fmt.Sprintf("&v1alpha1.PriorityLevelConfiguration{ObjectMeta: %#+v, Spec: ",
|
||||
buf.WriteString(fmt.Sprintf("&flowcontrolv1beta1.PriorityLevelConfiguration{ObjectMeta: %#+v, Spec: ",
|
||||
pl.ObjectMeta))
|
||||
BufferPriorityLevelConfigurationSpec(&buf, &pl.Spec)
|
||||
buf.WriteString(fmt.Sprintf(", Status: %#+v}", pl.Status))
|
||||
|
|
@ -102,7 +102,7 @@ func FmtPriorityLevelConfiguration(pl *fcv1a1.PriorityLevelConfiguration) string
|
|||
|
||||
// FmtPriorityLevelConfigurationSpec returns a golang source
|
||||
// expression equivalent to the given value
|
||||
func FmtPriorityLevelConfigurationSpec(plSpec *fcv1a1.PriorityLevelConfigurationSpec) string {
|
||||
func FmtPriorityLevelConfigurationSpec(plSpec *flowcontrol.PriorityLevelConfigurationSpec) string {
|
||||
var buf bytes.Buffer
|
||||
BufferPriorityLevelConfigurationSpec(&buf, plSpec)
|
||||
return buf.String()
|
||||
|
|
@ -110,10 +110,10 @@ func FmtPriorityLevelConfigurationSpec(plSpec *fcv1a1.PriorityLevelConfiguration
|
|||
|
||||
// BufferPriorityLevelConfigurationSpec writes a golang source
|
||||
// expression for the given value to the given buffer
|
||||
func BufferPriorityLevelConfigurationSpec(buf *bytes.Buffer, plSpec *fcv1a1.PriorityLevelConfigurationSpec) {
|
||||
buf.WriteString(fmt.Sprintf("v1alpha1.PriorityLevelConfigurationSpec{Type: %#v", plSpec.Type))
|
||||
func BufferPriorityLevelConfigurationSpec(buf *bytes.Buffer, plSpec *flowcontrol.PriorityLevelConfigurationSpec) {
|
||||
buf.WriteString(fmt.Sprintf("flowcontrolv1beta1.PriorityLevelConfigurationSpec{Type: %#v", plSpec.Type))
|
||||
if plSpec.Limited != nil {
|
||||
buf.WriteString(fmt.Sprintf(", Limited: &v1alpha1.LimitedPriorityLevelConfiguration{AssuredConcurrencyShares:%d, LimitResponse:v1alpha1.LimitResponse{Type:%#v", plSpec.Limited.AssuredConcurrencyShares, plSpec.Limited.LimitResponse.Type))
|
||||
buf.WriteString(fmt.Sprintf(", Limited: &flowcontrol.LimitedPriorityLevelConfiguration{AssuredConcurrencyShares:%d, LimitResponse:flowcontrol.LimitResponse{Type:%#v", plSpec.Limited.AssuredConcurrencyShares, plSpec.Limited.LimitResponse.Type))
|
||||
if plSpec.Limited.LimitResponse.Queuing != nil {
|
||||
buf.WriteString(fmt.Sprintf(", Queuing:&%#+v", *plSpec.Limited.LimitResponse.Queuing))
|
||||
}
|
||||
|
|
@ -123,12 +123,12 @@ func BufferPriorityLevelConfigurationSpec(buf *bytes.Buffer, plSpec *fcv1a1.Prio
|
|||
}
|
||||
|
||||
// FmtFlowSchema produces a golang source expression of the value.
|
||||
func FmtFlowSchema(fs *fcv1a1.FlowSchema) string {
|
||||
func FmtFlowSchema(fs *flowcontrol.FlowSchema) string {
|
||||
if fs == nil {
|
||||
return "nil"
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(fmt.Sprintf("&v1alpha1.FlowSchema{ObjectMeta: %#+v, Spec: ",
|
||||
buf.WriteString(fmt.Sprintf("&flowcontrolv1beta1.FlowSchema{ObjectMeta: %#+v, Spec: ",
|
||||
fs.ObjectMeta))
|
||||
BufferFlowSchemaSpec(&buf, &fs.Spec)
|
||||
buf.WriteString(fmt.Sprintf(", Status: %#+v}", fs.Status))
|
||||
|
|
@ -137,7 +137,7 @@ func FmtFlowSchema(fs *fcv1a1.FlowSchema) string {
|
|||
|
||||
// FmtFlowSchemaSpec produces a golang source expression equivalent to
|
||||
// the given spec
|
||||
func FmtFlowSchemaSpec(fsSpec *fcv1a1.FlowSchemaSpec) string {
|
||||
func FmtFlowSchemaSpec(fsSpec *flowcontrol.FlowSchemaSpec) string {
|
||||
var buf bytes.Buffer
|
||||
BufferFlowSchemaSpec(&buf, fsSpec)
|
||||
return buf.String()
|
||||
|
|
@ -145,8 +145,8 @@ func FmtFlowSchemaSpec(fsSpec *fcv1a1.FlowSchemaSpec) string {
|
|||
|
||||
// BufferFlowSchemaSpec writes a golang source expression for the
|
||||
// given value to the given buffer
|
||||
func BufferFlowSchemaSpec(buf *bytes.Buffer, fsSpec *fcv1a1.FlowSchemaSpec) {
|
||||
buf.WriteString(fmt.Sprintf("v1alpha1.FlowSchemaSpec{PriorityLevelConfiguration: %#+v, MatchingPrecedence: %d, DistinguisherMethod: ",
|
||||
func BufferFlowSchemaSpec(buf *bytes.Buffer, fsSpec *flowcontrol.FlowSchemaSpec) {
|
||||
buf.WriteString(fmt.Sprintf("flowcontrolv1beta1.FlowSchemaSpec{PriorityLevelConfiguration: %#+v, MatchingPrecedence: %d, DistinguisherMethod: ",
|
||||
fsSpec.PriorityLevelConfiguration,
|
||||
fsSpec.MatchingPrecedence))
|
||||
if fsSpec.DistinguisherMethod == nil {
|
||||
|
|
@ -154,7 +154,7 @@ func BufferFlowSchemaSpec(buf *bytes.Buffer, fsSpec *fcv1a1.FlowSchemaSpec) {
|
|||
} else {
|
||||
buf.WriteString(fmt.Sprintf("&%#+v", *fsSpec.DistinguisherMethod))
|
||||
}
|
||||
buf.WriteString(", Rules: []v1alpha1.PolicyRulesWithSubjects{")
|
||||
buf.WriteString(", Rules: []flowcontrol.PolicyRulesWithSubjects{")
|
||||
for idx, rule := range fsSpec.Rules {
|
||||
if idx > 0 {
|
||||
buf.WriteString(", ")
|
||||
|
|
@ -165,14 +165,14 @@ func BufferFlowSchemaSpec(buf *bytes.Buffer, fsSpec *fcv1a1.FlowSchemaSpec) {
|
|||
}
|
||||
|
||||
// FmtPolicyRulesWithSubjects produces a golang source expression of the value.
|
||||
func FmtPolicyRulesWithSubjects(rule fcv1a1.PolicyRulesWithSubjects) string {
|
||||
return "v1alpha1.PolicyRulesWithSubjects" + FmtPolicyRulesWithSubjectsSlim(rule)
|
||||
func FmtPolicyRulesWithSubjects(rule flowcontrol.PolicyRulesWithSubjects) string {
|
||||
return "flowcontrolv1beta1.PolicyRulesWithSubjects" + FmtPolicyRulesWithSubjectsSlim(rule)
|
||||
}
|
||||
|
||||
// FmtPolicyRulesWithSubjectsSlim produces a golang source expression
|
||||
// of the value but without the leading type name. See above for an
|
||||
// example context where this is useful.
|
||||
func FmtPolicyRulesWithSubjectsSlim(rule fcv1a1.PolicyRulesWithSubjects) string {
|
||||
func FmtPolicyRulesWithSubjectsSlim(rule flowcontrol.PolicyRulesWithSubjects) string {
|
||||
var buf bytes.Buffer
|
||||
BufferFmtPolicyRulesWithSubjectsSlim(&buf, rule)
|
||||
return buf.String()
|
||||
|
|
@ -181,8 +181,8 @@ func FmtPolicyRulesWithSubjectsSlim(rule fcv1a1.PolicyRulesWithSubjects) string
|
|||
// BufferFmtPolicyRulesWithSubjectsSlim writes a golang source
|
||||
// expression for the given value to the given buffer but excludes the
|
||||
// leading type name
|
||||
func BufferFmtPolicyRulesWithSubjectsSlim(buf *bytes.Buffer, rule fcv1a1.PolicyRulesWithSubjects) {
|
||||
buf.WriteString("{Subjects: []v1alpha1.Subject{")
|
||||
func BufferFmtPolicyRulesWithSubjectsSlim(buf *bytes.Buffer, rule flowcontrol.PolicyRulesWithSubjects) {
|
||||
buf.WriteString("{Subjects: []flowcontrolv1beta1.Subject{")
|
||||
for jdx, subj := range rule.Subjects {
|
||||
if jdx > 0 {
|
||||
buf.WriteString(", ")
|
||||
|
|
|
|||
82
vendor/k8s.io/apiserver/pkg/util/flowcontrol/metrics/metrics.go
generated
vendored
82
vendor/k8s.io/apiserver/pkg/util/flowcontrol/metrics/metrics.go
generated
vendored
|
|
@ -34,8 +34,8 @@ const (
|
|||
|
||||
const (
|
||||
requestKind = "request_kind"
|
||||
priorityLevel = "priorityLevel"
|
||||
flowSchema = "flowSchema"
|
||||
priorityLevel = "priority_level"
|
||||
flowSchema = "flow_schema"
|
||||
phase = "phase"
|
||||
mark = "mark"
|
||||
)
|
||||
|
|
@ -84,19 +84,21 @@ func (rs Registerables) Append(more ...compbasemetrics.Registerable) Registerabl
|
|||
var (
|
||||
apiserverRejectedRequestsTotal = compbasemetrics.NewCounterVec(
|
||||
&compbasemetrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "rejected_requests_total",
|
||||
Help: "Number of requests rejected by API Priority and Fairness system",
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "rejected_requests_total",
|
||||
Help: "Number of requests rejected by API Priority and Fairness system",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema, "reason"},
|
||||
)
|
||||
apiserverDispatchedRequestsTotal = compbasemetrics.NewCounterVec(
|
||||
&compbasemetrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "dispatched_requests_total",
|
||||
Help: "Number of requests released by API Priority and Fairness system for service",
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "dispatched_requests_total",
|
||||
Help: "Number of requests released by API Priority and Fairness system for service",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema},
|
||||
)
|
||||
|
|
@ -143,58 +145,64 @@ var (
|
|||
|
||||
apiserverCurrentInqueueRequests = compbasemetrics.NewGaugeVec(
|
||||
&compbasemetrics.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "current_inqueue_requests",
|
||||
Help: "Number of requests currently pending in queues of the API Priority and Fairness system",
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "current_inqueue_requests",
|
||||
Help: "Number of requests currently pending in queues of the API Priority and Fairness system",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema},
|
||||
)
|
||||
apiserverRequestQueueLength = compbasemetrics.NewHistogramVec(
|
||||
&compbasemetrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_queue_length_after_enqueue",
|
||||
Help: "Length of queue in the API Priority and Fairness system, as seen by each request after it is enqueued",
|
||||
Buckets: queueLengthBuckets,
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_queue_length_after_enqueue",
|
||||
Help: "Length of queue in the API Priority and Fairness system, as seen by each request after it is enqueued",
|
||||
Buckets: queueLengthBuckets,
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema},
|
||||
)
|
||||
apiserverRequestConcurrencyLimit = compbasemetrics.NewGaugeVec(
|
||||
&compbasemetrics.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_concurrency_limit",
|
||||
Help: "Shared concurrency limit in the API Priority and Fairness system",
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_concurrency_limit",
|
||||
Help: "Shared concurrency limit in the API Priority and Fairness system",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel},
|
||||
)
|
||||
apiserverCurrentExecutingRequests = compbasemetrics.NewGaugeVec(
|
||||
&compbasemetrics.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "current_executing_requests",
|
||||
Help: "Number of requests currently executing in the API Priority and Fairness system",
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "current_executing_requests",
|
||||
Help: "Number of requests currently executing in the API Priority and Fairness system",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema},
|
||||
)
|
||||
apiserverRequestWaitingSeconds = compbasemetrics.NewHistogramVec(
|
||||
&compbasemetrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_wait_duration_seconds",
|
||||
Help: "Length of time a request spent waiting in its queue",
|
||||
Buckets: requestDurationSecondsBuckets,
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_wait_duration_seconds",
|
||||
Help: "Length of time a request spent waiting in its queue",
|
||||
Buckets: requestDurationSecondsBuckets,
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema, "execute"},
|
||||
)
|
||||
apiserverRequestExecutionSeconds = compbasemetrics.NewHistogramVec(
|
||||
&compbasemetrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_execution_seconds",
|
||||
Help: "Duration of request execution in the API Priority and Fairness system",
|
||||
Buckets: requestDurationSecondsBuckets,
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "request_execution_seconds",
|
||||
Help: "Duration of request execution in the API Priority and Fairness system",
|
||||
Buckets: requestDurationSecondsBuckets,
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{priorityLevel, flowSchema},
|
||||
)
|
||||
|
|
|
|||
55
vendor/k8s.io/apiserver/pkg/util/flowcontrol/metrics/sample_and_watermark.go
generated
vendored
55
vendor/k8s.io/apiserver/pkg/util/flowcontrol/metrics/sample_and_watermark.go
generated
vendored
|
|
@ -64,13 +64,16 @@ func (spg SampleAndWaterMarkPairGenerator) metrics() Registerables {
|
|||
// SampleAndWaterMarkObserverGenerator creates TimedObservers that
|
||||
// populate histograms of samples and low- and high-water-marks. The
|
||||
// generator has a samplePeriod, and the histograms get an observation
|
||||
// every samplePeriod.
|
||||
// every samplePeriod. The sampling windows are quantized based on
|
||||
// the monotonic rather than wall-clock times. The `t0` field is
|
||||
// there so to provide a baseline for monotonic clock differences.
|
||||
type SampleAndWaterMarkObserverGenerator struct {
|
||||
*sampleAndWaterMarkObserverGenerator
|
||||
}
|
||||
|
||||
type sampleAndWaterMarkObserverGenerator struct {
|
||||
clock clock.PassiveClock
|
||||
t0 time.Time
|
||||
samplePeriod time.Duration
|
||||
samples *compbasemetrics.HistogramVec
|
||||
waterMarks *compbasemetrics.HistogramVec
|
||||
|
|
@ -83,6 +86,7 @@ func NewSampleAndWaterMarkHistogramsGenerator(clock clock.PassiveClock, samplePe
|
|||
return SampleAndWaterMarkObserverGenerator{
|
||||
&sampleAndWaterMarkObserverGenerator{
|
||||
clock: clock,
|
||||
t0: clock.Now(),
|
||||
samplePeriod: samplePeriod,
|
||||
samples: compbasemetrics.NewHistogramVec(sampleOpts, labelNames),
|
||||
waterMarks: compbasemetrics.NewHistogramVec(waterMarkOpts, append([]string{labelNameMark}, labelNames...)),
|
||||
|
|
@ -90,7 +94,7 @@ func NewSampleAndWaterMarkHistogramsGenerator(clock clock.PassiveClock, samplePe
|
|||
}
|
||||
|
||||
func (swg *sampleAndWaterMarkObserverGenerator) quantize(when time.Time) int64 {
|
||||
return when.UnixNano() / int64(swg.samplePeriod)
|
||||
return int64(when.Sub(swg.t0) / swg.samplePeriod)
|
||||
}
|
||||
|
||||
// Generate makes a new TimedObserver
|
||||
|
|
@ -156,31 +160,46 @@ func (saw *sampleAndWaterMarkHistograms) SetX1(x1 float64) {
|
|||
}
|
||||
|
||||
func (saw *sampleAndWaterMarkHistograms) innerSet(updateXOrX1 func()) {
|
||||
saw.Lock()
|
||||
when := saw.clock.Now()
|
||||
whenInt := saw.quantize(when)
|
||||
acc := saw.sampleAndWaterMarkAccumulator
|
||||
wellOrdered := !when.Before(acc.lastSet)
|
||||
if wellOrdered {
|
||||
var when time.Time
|
||||
var whenInt int64
|
||||
var acc sampleAndWaterMarkAccumulator
|
||||
var wellOrdered bool
|
||||
func() {
|
||||
saw.Lock()
|
||||
defer saw.Unlock()
|
||||
when = saw.clock.Now()
|
||||
whenInt = saw.quantize(when)
|
||||
acc = saw.sampleAndWaterMarkAccumulator
|
||||
wellOrdered = !when.Before(acc.lastSet)
|
||||
updateXOrX1()
|
||||
saw.relX = saw.x / saw.x1
|
||||
if acc.lastSetInt < whenInt {
|
||||
saw.loRelX, saw.hiRelX = acc.relX, acc.relX
|
||||
saw.lastSetInt = whenInt
|
||||
if wellOrdered {
|
||||
if acc.lastSetInt < whenInt {
|
||||
saw.loRelX, saw.hiRelX = acc.relX, acc.relX
|
||||
saw.lastSetInt = whenInt
|
||||
}
|
||||
saw.lastSet = when
|
||||
}
|
||||
// `wellOrdered` should always be true because we are using
|
||||
// monotonic clock readings and they never go backwards. Yet
|
||||
// very small backwards steps (under 1 microsecond) have been
|
||||
// observed
|
||||
// (https://github.com/kubernetes/kubernetes/issues/96459).
|
||||
// In the backwards case, treat the current reading as if it
|
||||
// had occurred at time `saw.lastSet` and log an error. It
|
||||
// would be wrong to update `saw.lastSet` in this case because
|
||||
// that plants a time bomb for future updates to
|
||||
// `saw.lastSetInt`.
|
||||
if saw.relX < saw.loRelX {
|
||||
saw.loRelX = saw.relX
|
||||
} else if saw.relX > saw.hiRelX {
|
||||
saw.hiRelX = saw.relX
|
||||
}
|
||||
saw.lastSet = when
|
||||
}
|
||||
saw.Unlock()
|
||||
}()
|
||||
if !wellOrdered {
|
||||
lastSetS := acc.lastSet.Format(time.RFC3339Nano)
|
||||
whenS := when.Format(time.RFC3339Nano)
|
||||
klog.Fatalf("Time went backwards from %s to %s for labelValues=%#+v", lastSetS, whenS, saw.labelValues)
|
||||
panic(append([]string{lastSetS, whenS}, saw.labelValues...))
|
||||
lastSetS := acc.lastSet.String()
|
||||
whenS := when.String()
|
||||
klog.Errorf("Time went backwards from %s to %s for labelValues=%#+v", lastSetS, whenS, saw.labelValues)
|
||||
}
|
||||
for acc.lastSetInt < whenInt {
|
||||
saw.samples.WithLabelValues(saw.labelValues...).Observe(acc.relX)
|
||||
|
|
|
|||
38
vendor/k8s.io/apiserver/pkg/util/flowcontrol/rule.go
generated
vendored
38
vendor/k8s.io/apiserver/pkg/util/flowcontrol/rule.go
generated
vendored
|
|
@ -19,7 +19,7 @@ package flowcontrol
|
|||
import (
|
||||
"strings"
|
||||
|
||||
fctypesv1a1 "k8s.io/api/flowcontrol/v1alpha1"
|
||||
flowcontrol "k8s.io/api/flowcontrol/v1beta1"
|
||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
// Tests whether a given request and FlowSchema match. Nobody mutates
|
||||
// either input.
|
||||
func matchesFlowSchema(digest RequestDigest, flowSchema *fctypesv1a1.FlowSchema) bool {
|
||||
func matchesFlowSchema(digest RequestDigest, flowSchema *flowcontrol.FlowSchema) bool {
|
||||
for _, policyRule := range flowSchema.Spec.Rules {
|
||||
if matchesPolicyRule(digest, &policyRule) {
|
||||
return true
|
||||
|
|
@ -36,7 +36,7 @@ func matchesFlowSchema(digest RequestDigest, flowSchema *fctypesv1a1.FlowSchema)
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesPolicyRule(digest RequestDigest, policyRule *fctypesv1a1.PolicyRulesWithSubjects) bool {
|
||||
func matchesPolicyRule(digest RequestDigest, policyRule *flowcontrol.PolicyRulesWithSubjects) bool {
|
||||
if !matchesASubject(digest.User, policyRule.Subjects) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ func matchesPolicyRule(digest RequestDigest, policyRule *fctypesv1a1.PolicyRules
|
|||
return matchesANonResourceRule(digest.RequestInfo, policyRule.NonResourceRules)
|
||||
}
|
||||
|
||||
func matchesASubject(user user.Info, subjects []fctypesv1a1.Subject) bool {
|
||||
func matchesASubject(user user.Info, subjects []flowcontrol.Subject) bool {
|
||||
for _, subject := range subjects {
|
||||
if matchesSubject(user, subject) {
|
||||
return true
|
||||
|
|
@ -55,11 +55,11 @@ func matchesASubject(user user.Info, subjects []fctypesv1a1.Subject) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesSubject(user user.Info, subject fctypesv1a1.Subject) bool {
|
||||
func matchesSubject(user user.Info, subject flowcontrol.Subject) bool {
|
||||
switch subject.Kind {
|
||||
case fctypesv1a1.SubjectKindUser:
|
||||
return subject.User != nil && (subject.User.Name == fctypesv1a1.NameAll || subject.User.Name == user.GetName())
|
||||
case fctypesv1a1.SubjectKindGroup:
|
||||
case flowcontrol.SubjectKindUser:
|
||||
return subject.User != nil && (subject.User.Name == flowcontrol.NameAll || subject.User.Name == user.GetName())
|
||||
case flowcontrol.SubjectKindGroup:
|
||||
if subject.Group == nil {
|
||||
return false
|
||||
}
|
||||
|
|
@ -73,11 +73,11 @@ func matchesSubject(user user.Info, subject fctypesv1a1.Subject) bool {
|
|||
}
|
||||
}
|
||||
return false
|
||||
case fctypesv1a1.SubjectKindServiceAccount:
|
||||
case flowcontrol.SubjectKindServiceAccount:
|
||||
if subject.ServiceAccount == nil {
|
||||
return false
|
||||
}
|
||||
if subject.ServiceAccount.Name == fctypesv1a1.NameAll {
|
||||
if subject.ServiceAccount.Name == flowcontrol.NameAll {
|
||||
return serviceAccountMatchesNamespace(subject.ServiceAccount.Namespace, user.GetName())
|
||||
}
|
||||
return serviceaccount.MatchesUsername(subject.ServiceAccount.Namespace, subject.ServiceAccount.Name, user.GetName())
|
||||
|
|
@ -107,7 +107,7 @@ func serviceAccountMatchesNamespace(namespace string, username string) bool {
|
|||
return strings.HasPrefix(username, ServiceAccountUsernameSeparator)
|
||||
}
|
||||
|
||||
func matchesAResourceRule(ri *request.RequestInfo, rules []fctypesv1a1.ResourcePolicyRule) bool {
|
||||
func matchesAResourceRule(ri *request.RequestInfo, rules []flowcontrol.ResourcePolicyRule) bool {
|
||||
for _, rr := range rules {
|
||||
if matchesResourcePolicyRule(ri, rr) {
|
||||
return true
|
||||
|
|
@ -116,7 +116,7 @@ func matchesAResourceRule(ri *request.RequestInfo, rules []fctypesv1a1.ResourceP
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesResourcePolicyRule(ri *request.RequestInfo, policyRule fctypesv1a1.ResourcePolicyRule) bool {
|
||||
func matchesResourcePolicyRule(ri *request.RequestInfo, policyRule flowcontrol.ResourcePolicyRule) bool {
|
||||
if !matchPolicyRuleVerb(policyRule.Verbs, ri.Verb) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -129,10 +129,10 @@ func matchesResourcePolicyRule(ri *request.RequestInfo, policyRule fctypesv1a1.R
|
|||
if len(ri.Namespace) == 0 {
|
||||
return policyRule.ClusterScope
|
||||
}
|
||||
return containsString(ri.Namespace, policyRule.Namespaces, fctypesv1a1.NamespaceEvery)
|
||||
return containsString(ri.Namespace, policyRule.Namespaces, flowcontrol.NamespaceEvery)
|
||||
}
|
||||
|
||||
func matchesANonResourceRule(ri *request.RequestInfo, rules []fctypesv1a1.NonResourcePolicyRule) bool {
|
||||
func matchesANonResourceRule(ri *request.RequestInfo, rules []flowcontrol.NonResourcePolicyRule) bool {
|
||||
for _, rr := range rules {
|
||||
if matchesNonResourcePolicyRule(ri, rr) {
|
||||
return true
|
||||
|
|
@ -141,7 +141,7 @@ func matchesANonResourceRule(ri *request.RequestInfo, rules []fctypesv1a1.NonRes
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesNonResourcePolicyRule(ri *request.RequestInfo, policyRule fctypesv1a1.NonResourcePolicyRule) bool {
|
||||
func matchesNonResourcePolicyRule(ri *request.RequestInfo, policyRule flowcontrol.NonResourcePolicyRule) bool {
|
||||
if !matchPolicyRuleVerb(policyRule.Verbs, ri.Verb) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -149,12 +149,12 @@ func matchesNonResourcePolicyRule(ri *request.RequestInfo, policyRule fctypesv1a
|
|||
}
|
||||
|
||||
func matchPolicyRuleVerb(policyRuleVerbs []string, requestVerb string) bool {
|
||||
return containsString(requestVerb, policyRuleVerbs, fctypesv1a1.VerbAll)
|
||||
return containsString(requestVerb, policyRuleVerbs, flowcontrol.VerbAll)
|
||||
}
|
||||
|
||||
func matchPolicyRuleNonResourceURL(policyRuleRequestURLs []string, requestPath string) bool {
|
||||
for _, rulePath := range policyRuleRequestURLs {
|
||||
if rulePath == fctypesv1a1.NonResourceAll || rulePath == requestPath {
|
||||
if rulePath == flowcontrol.NonResourceAll || rulePath == requestPath {
|
||||
return true
|
||||
}
|
||||
rulePrefix := strings.TrimSuffix(rulePath, "*")
|
||||
|
|
@ -169,7 +169,7 @@ func matchPolicyRuleNonResourceURL(policyRuleRequestURLs []string, requestPath s
|
|||
}
|
||||
|
||||
func matchPolicyRuleAPIGroup(policyRuleAPIGroups []string, requestAPIGroup string) bool {
|
||||
return containsString(requestAPIGroup, policyRuleAPIGroups, fctypesv1a1.APIGroupAll)
|
||||
return containsString(requestAPIGroup, policyRuleAPIGroups, flowcontrol.APIGroupAll)
|
||||
}
|
||||
|
||||
func rsJoin(requestResource, requestSubresource string) string {
|
||||
|
|
@ -181,7 +181,7 @@ func rsJoin(requestResource, requestSubresource string) string {
|
|||
}
|
||||
|
||||
func matchPolicyRuleResource(policyRuleRequestResources []string, requestResource, requestSubresource string) bool {
|
||||
return containsString(rsJoin(requestResource, requestSubresource), policyRuleRequestResources, fctypesv1a1.ResourceAll)
|
||||
return containsString(rsJoin(requestResource, requestSubresource), policyRuleRequestResources, flowcontrol.ResourceAll)
|
||||
}
|
||||
|
||||
// containsString returns true if either `x` or `wildcard` is in
|
||||
|
|
|
|||
2
vendor/k8s.io/apiserver/pkg/util/webhook/authentication.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/util/webhook/authentication.go
generated
vendored
|
|
@ -55,7 +55,7 @@ func NewDefaultAuthenticationInfoResolverWrapper(
|
|||
}
|
||||
|
||||
if egressSelector != nil {
|
||||
networkContext := egressselector.Master.AsNetworkContext()
|
||||
networkContext := egressselector.ControlPlane.AsNetworkContext()
|
||||
var egressDialer utilnet.DialFunc
|
||||
egressDialer, err = egressSelector.Lookup(networkContext)
|
||||
|
||||
|
|
|
|||
72
vendor/k8s.io/apiserver/pkg/util/webhook/webhook.go
generated
vendored
72
vendor/k8s.io/apiserver/pkg/util/webhook/webhook.go
generated
vendored
|
|
@ -36,12 +36,23 @@ import (
|
|||
// timeout of the HTTP request, including reading the response body.
|
||||
const defaultRequestTimeout = 30 * time.Second
|
||||
|
||||
// DefaultRetryBackoffWithInitialDelay returns the default backoff parameters for webhook retry from a given initial delay.
|
||||
// Handy for the client that provides a custom initial delay only.
|
||||
func DefaultRetryBackoffWithInitialDelay(initialBackoffDelay time.Duration) wait.Backoff {
|
||||
return wait.Backoff{
|
||||
Duration: initialBackoffDelay,
|
||||
Factor: 1.5,
|
||||
Jitter: 0.2,
|
||||
Steps: 5,
|
||||
}
|
||||
}
|
||||
|
||||
// GenericWebhook defines a generic client for webhooks with commonly used capabilities,
|
||||
// such as retry requests.
|
||||
type GenericWebhook struct {
|
||||
RestClient *rest.RESTClient
|
||||
InitialBackoff time.Duration
|
||||
ShouldRetry func(error) bool
|
||||
RestClient *rest.RESTClient
|
||||
RetryBackoff wait.Backoff
|
||||
ShouldRetry func(error) bool
|
||||
}
|
||||
|
||||
// DefaultShouldRetry is a default implementation for the GenericWebhook ShouldRetry function property.
|
||||
|
|
@ -61,11 +72,11 @@ func DefaultShouldRetry(err error) bool {
|
|||
}
|
||||
|
||||
// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
|
||||
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
|
||||
return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout, customDial)
|
||||
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*GenericWebhook, error) {
|
||||
return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, retryBackoff, defaultRequestTimeout, customDial)
|
||||
}
|
||||
|
||||
func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
|
||||
func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, retryBackoff wait.Backoff, requestTimeout time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
|
||||
for _, groupVersion := range groupVersions {
|
||||
if !scheme.IsVersionRegistered(groupVersion) {
|
||||
return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
|
||||
|
|
@ -102,19 +113,20 @@ func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &GenericWebhook{restClient, initialBackoff, DefaultShouldRetry}, nil
|
||||
return &GenericWebhook{restClient, retryBackoff, DefaultShouldRetry}, nil
|
||||
}
|
||||
|
||||
// WithExponentialBackoff will retry webhookFn() up to 5 times with exponentially increasing backoff when
|
||||
// it returns an error for which this GenericWebhook's ShouldRetry function returns true, confirming it to
|
||||
// be retriable. If no ShouldRetry has been defined for the webhook, then the default one is used (DefaultShouldRetry).
|
||||
// WithExponentialBackoff will retry webhookFn() as specified by the given backoff parameters with exponentially
|
||||
// increasing backoff when it returns an error for which this GenericWebhook's ShouldRetry function returns true,
|
||||
// confirming it to be retriable. If no ShouldRetry has been defined for the webhook,
|
||||
// then the default one is used (DefaultShouldRetry).
|
||||
func (g *GenericWebhook) WithExponentialBackoff(ctx context.Context, webhookFn func() rest.Result) rest.Result {
|
||||
var result rest.Result
|
||||
shouldRetry := g.ShouldRetry
|
||||
if shouldRetry == nil {
|
||||
shouldRetry = DefaultShouldRetry
|
||||
}
|
||||
WithExponentialBackoff(ctx, g.InitialBackoff, func() error {
|
||||
WithExponentialBackoff(ctx, g.RetryBackoff, func() error {
|
||||
result = webhookFn()
|
||||
return result.Error()
|
||||
}, shouldRetry)
|
||||
|
|
@ -123,28 +135,28 @@ func (g *GenericWebhook) WithExponentialBackoff(ctx context.Context, webhookFn f
|
|||
|
||||
// WithExponentialBackoff will retry webhookFn up to 5 times with exponentially increasing backoff when
|
||||
// it returns an error for which shouldRetry returns true, confirming it to be retriable.
|
||||
func WithExponentialBackoff(ctx context.Context, initialBackoff time.Duration, webhookFn func() error, shouldRetry func(error) bool) error {
|
||||
backoff := wait.Backoff{
|
||||
Duration: initialBackoff,
|
||||
Factor: 1.5,
|
||||
Jitter: 0.2,
|
||||
Steps: 5,
|
||||
}
|
||||
|
||||
var err error
|
||||
wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
err = webhookFn()
|
||||
if ctx.Err() != nil {
|
||||
// we timed out or were cancelled, we should not retry
|
||||
return true, err
|
||||
}
|
||||
if shouldRetry(err) {
|
||||
func WithExponentialBackoff(ctx context.Context, retryBackoff wait.Backoff, webhookFn func() error, shouldRetry func(error) bool) error {
|
||||
// having a webhook error allows us to track the last actual webhook error for requests that
|
||||
// are later cancelled or time out.
|
||||
var webhookErr error
|
||||
err := wait.ExponentialBackoffWithContext(ctx, retryBackoff, func() (bool, error) {
|
||||
webhookErr = webhookFn()
|
||||
if shouldRetry(webhookErr) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
if webhookErr != nil {
|
||||
return false, webhookErr
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
return err
|
||||
|
||||
switch {
|
||||
// we check for webhookErr first, if webhookErr is set it's the most important error to return.
|
||||
case webhookErr != nil:
|
||||
return webhookErr
|
||||
case err != nil:
|
||||
return fmt.Errorf("webhook call failed: %s", err.Error())
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue