...

Source file src/sigs.k8s.io/cli-utils/cmd/main.go

Documentation: sigs.k8s.io/cli-utils/cmd

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package main
     5  
     6  import (
     7  	"context"
     8  	"flag"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/spf13/cobra"
    15  	"k8s.io/cli-runtime/pkg/genericclioptions"
    16  	"k8s.io/client-go/rest"
    17  	"k8s.io/component-base/cli"
    18  	"k8s.io/klog/v2"
    19  	"k8s.io/kubectl/pkg/cmd/util"
    20  	"sigs.k8s.io/cli-utils/cmd/apply"
    21  	"sigs.k8s.io/cli-utils/cmd/destroy"
    22  	"sigs.k8s.io/cli-utils/cmd/diff"
    23  	"sigs.k8s.io/cli-utils/cmd/initcmd"
    24  	"sigs.k8s.io/cli-utils/cmd/preview"
    25  	"sigs.k8s.io/cli-utils/cmd/status"
    26  	"sigs.k8s.io/cli-utils/pkg/flowcontrol"
    27  	"sigs.k8s.io/cli-utils/pkg/inventory"
    28  	"sigs.k8s.io/cli-utils/pkg/manifestreader"
    29  
    30  	// This is here rather than in the libraries because of
    31  	// https://github.com/kubernetes-sigs/kustomize/issues/2060
    32  	_ "k8s.io/client-go/plugin/pkg/client/auth"
    33  )
    34  
    35  func main() {
    36  	cmd := &cobra.Command{
    37  		Use:   "kapply",
    38  		Short: "Perform cluster operations using declarative configuration",
    39  		Long:  "Perform cluster operations using declarative configuration",
    40  		// We silence error reporting from Cobra here since we want to improve
    41  		// the error messages coming from the commands.
    42  		SilenceErrors: true,
    43  		SilenceUsage:  true,
    44  	}
    45  
    46  	// configure kubectl dependencies and flags
    47  	flags := cmd.PersistentFlags()
    48  	kubeConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
    49  	kubeConfigFlags.AddFlags(flags)
    50  	matchVersionKubeConfigFlags := util.NewMatchVersionFlags(kubeConfigFlags)
    51  	matchVersionKubeConfigFlags.AddFlags(flags)
    52  	flags.AddGoFlagSet(flag.CommandLine)
    53  	f := util.NewFactory(matchVersionKubeConfigFlags)
    54  
    55  	// Update ConfigFlags before subcommands run that talk to the server.
    56  	preRunE := newConfigFilerPreRunE(f, kubeConfigFlags)
    57  
    58  	ioStreams := genericclioptions.IOStreams{
    59  		In:     os.Stdin,
    60  		Out:    os.Stdout,
    61  		ErrOut: os.Stderr,
    62  	}
    63  
    64  	loader := manifestreader.NewManifestLoader(f)
    65  	invFactory := inventory.ClusterClientFactory{StatusPolicy: inventory.StatusPolicyNone}
    66  
    67  	names := []string{"init", "apply", "destroy", "diff", "preview", "status"}
    68  	subCmds := []*cobra.Command{
    69  		initcmd.NewCmdInit(f, ioStreams),
    70  		apply.Command(f, invFactory, loader, ioStreams),
    71  		destroy.Command(f, invFactory, loader, ioStreams),
    72  		diff.NewCommand(f, ioStreams),
    73  		preview.Command(f, invFactory, loader, ioStreams),
    74  		status.Command(context.TODO(), f, invFactory, status.NewInventoryLoader(loader)),
    75  	}
    76  	for _, subCmd := range subCmds {
    77  		subCmd.PreRunE = preRunE
    78  		updateHelp(names, subCmd)
    79  		cmd.AddCommand(subCmd)
    80  	}
    81  
    82  	code := cli.Run(cmd)
    83  	os.Exit(code)
    84  }
    85  
    86  // updateHelp replaces `kubectl` help messaging with `kapply` help messaging
    87  func updateHelp(names []string, c *cobra.Command) {
    88  	for i := range names {
    89  		name := names[i]
    90  		c.Short = strings.ReplaceAll(c.Short, "kubectl "+name, "kapply "+name)
    91  		c.Long = strings.ReplaceAll(c.Long, "kubectl "+name, "kapply "+name)
    92  		c.Example = strings.ReplaceAll(c.Example, "kubectl "+name, "kapply "+name)
    93  	}
    94  }
    95  
    96  // newConfigFilerPreRunE returns a cobra command PreRunE function that
    97  // performs a lookup to determine if server-side throttling is enabled. If so,
    98  // client-side throttling is disabled in the ConfigFlags.
    99  func newConfigFilerPreRunE(f util.Factory, configFlags *genericclioptions.ConfigFlags) func(*cobra.Command, []string) error {
   100  	return func(_ *cobra.Command, args []string) error {
   101  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   102  		defer cancel()
   103  
   104  		restConfig, err := f.ToRESTConfig()
   105  		if err != nil {
   106  			return err
   107  		}
   108  		enabled, err := flowcontrol.IsEnabled(ctx, restConfig)
   109  		if err != nil {
   110  			return fmt.Errorf("checking server-side throttling enablement: %w", err)
   111  		}
   112  		if enabled {
   113  			// Disable client-side throttling.
   114  			klog.V(3).Infof("Client-side throttling disabled")
   115  			// WrapConfigFn will affect future Factory.ToRESTConfig() calls.
   116  			configFlags.WrapConfigFn = func(cfg *rest.Config) *rest.Config {
   117  				cfg.QPS = -1
   118  				cfg.Burst = -1
   119  				return cfg
   120  			}
   121  		}
   122  		return nil
   123  	}
   124  }
   125  

View as plain text