github.com/SamarSidharth/kpt@v0.0.0-20231122062228-c7d747ae3ace/commands/util/factory.go (about) 1 // Copyright 2020 The kpt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package util 16 17 import ( 18 "context" 19 "flag" 20 "fmt" 21 "time" 22 23 "github.com/GoogleContainerTools/kpt/internal/util/cfgflags" 24 "github.com/spf13/cobra" 25 "k8s.io/cli-runtime/pkg/genericclioptions" 26 "k8s.io/client-go/rest" 27 "k8s.io/klog/v2" 28 cluster "k8s.io/kubectl/pkg/cmd/util" 29 "sigs.k8s.io/cli-utils/pkg/flowcontrol" 30 ) 31 32 func NewFactory(cmd *cobra.Command, version string) cluster.Factory { 33 flags := cmd.PersistentFlags() 34 kubeConfigFlags := genericclioptions.NewConfigFlags(true). 35 WithDeprecatedPasswordFlag() 36 kubeConfigFlags.AddFlags(flags) 37 UpdateQPS(kubeConfigFlags) 38 userAgentKubeConfigFlags := &cfgflags.UserAgentKubeConfigFlags{ 39 Delegate: kubeConfigFlags, 40 UserAgent: fmt.Sprintf("kpt/%s", version), 41 } 42 cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine) 43 return cluster.NewFactory(userAgentKubeConfigFlags) 44 } 45 46 // UpdateQPS modifies a genericclioptions.ConfigFlags to update the client-side 47 // throttling QPS and Burst QPS (including for discovery). 48 // 49 // If Flow Control is enabled on the apiserver, client-side throttling is 50 // disabled! 51 // 52 // If Flow Control is disabled or undetected on the apiserver, client-side 53 // throttling QPS will be increased to at least 30 (burst: 60). 54 // 55 // Flow Control is enabled by default on Kubernetes v1.20+. 56 // https://kubernetes.io/docs/concepts/cluster-administration/flow-control/ 57 func UpdateQPS(flags *genericclioptions.ConfigFlags) { 58 flags. 59 WithWrapConfigFn(func(c *rest.Config) *rest.Config { 60 // Timeout if the query takes too long, defaulting to the lower QPS limits. 61 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 62 defer cancel() 63 64 enabled, err := flowcontrol.IsEnabled(ctx, c) 65 if err != nil { 66 klog.Warning("Failed to query apiserver to check for flow control enablement: %v", err) 67 // Default to the lower QPS limits. 68 } 69 70 qps := float32(-1) 71 burst := -1 72 if enabled { 73 klog.V(1).Infof("Flow control enabled on apiserver: client-side throttling QPS set to %.0f (burst: %d)", qps, burst) 74 } else { 75 qps = maxIfNotNegative(c.QPS, 30) 76 burst = int(maxIfNotNegative(float32(c.Burst), 60)) 77 klog.V(1).Infof("Flow control disabled on apiserver: client-side throttling QPS set to %.0f (burst: %d)", qps, burst) 78 } 79 80 c.QPS = qps 81 c.Burst = burst 82 flags. 83 WithDiscoveryQPS(qps). 84 WithDiscoveryBurst(burst) 85 86 return c 87 }) 88 } 89 90 func maxIfNotNegative(a, b float32) float32 { 91 switch { 92 case a < 0: 93 return a 94 case a > b: 95 return a 96 default: 97 return b 98 } 99 }