Ensure RateLimiter is preserved across all built Contexts

Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
This commit is contained in:
joshvanl 2022-01-31 13:37:46 +00:00
parent 834e6bcb04
commit 364c02d36e
2 changed files with 58 additions and 0 deletions

View File

@ -18,6 +18,7 @@ package controller
import (
"context"
"errors"
"fmt"
"time"
@ -31,6 +32,7 @@ import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/flowcontrol"
"k8s.io/utils/clock"
gwapi "sigs.k8s.io/gateway-api/apis/v1alpha1"
gwclient "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
@ -229,6 +231,8 @@ type ContextFactory struct {
// NewContextFactory builds a ContextFactory that builds controller Contexts
// that have been configured for that components User Agent.
// All resulting Context's and clients contain the same RateLimiter and
// corresponding QPS and Burst buckets.
func NewContextFactory(ctx context.Context, opts ContextOptions) (*ContextFactory, error) {
// Load the users Kubernetes config
restConfig, err := clientcmd.BuildConfigFromFlags(opts.APIServerHost, opts.Kubeconfig)
@ -239,6 +243,18 @@ func NewContextFactory(ctx context.Context, opts ContextOptions) (*ContextFactor
restConfig.QPS = opts.KubernetesAPIQPS
restConfig.Burst = opts.KubernetesAPIBurst
// Construct a single RateLimiter used across all built Context's clients. A
// single rate limiter (with corresponding QPS and Burst buckets) are
// preserved for all Contexts.
// Adapted from
// https://github.com/kubernetes/client-go/blob/v0.23.3/kubernetes/clientset.go#L431-L435
if restConfig.RateLimiter == nil && restConfig.QPS > 0 {
if restConfig.Burst <= 0 {
return nil, errors.New("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
restConfig.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(restConfig.QPS, restConfig.Burst)
}
clients, err := buildClients(restConfig)
if err != nil {
return nil, err

View File

@ -0,0 +1,42 @@
/*
Copyright 2020 The cert-manager Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_NewContextFactory(t *testing.T) {
ctxFactory, err := NewContextFactory(context.TODO(), ContextOptions{
APIServerHost: "localhost:8443",
KubernetesAPIQPS: 10,
KubernetesAPIBurst: 10,
})
assert.NoError(t, err)
// Ensure a single RateLimiter is preserved across Contexts.
ctx1, err := ctxFactory.Build("test-1")
assert.NoError(t, err)
ctx2, err := ctxFactory.Build("test-2")
assert.NoError(t, err)
assert.NotNil(t, ctx1.RESTConfig.RateLimiter)
assert.Equal(t, ctx1.RESTConfig.RateLimiter, ctx2.RESTConfig.RateLimiter)
}