Bumping k8s dependencies to 1.13

This commit is contained in:
Cheng Xing
2018-11-16 14:08:25 -08:00
parent 305407125c
commit b4c0b68ec7
8002 changed files with 884099 additions and 276228 deletions

View File

@@ -18,170 +18,214 @@ package cmd
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"syscall"
"path/filepath"
"runtime"
"strings"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/plugins"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
var (
plugin_long = templates.LongDesc(`
Runs a command-line plugin.
Provides utilities for interacting with plugins.
Plugins are subcommands that are not part of the major command-line distribution
and can even be provided by third-parties. Please refer to the documentation and
examples for more information about how to install and write your own plugins.`)
Plugins provide extended functionality that is not part of the major command-line distribution.
Please refer to the documentation and examples for more information about how write your own plugins.`)
plugin_list_long = templates.LongDesc(`
List all available plugin files on a user's PATH.
Available plugin files are those that are:
- executable
- anywhere on the user's PATH
- begin with "kubectl-"
`)
)
// NewCmdPlugin creates the command that is the top-level for plugin commands.
func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
// Loads plugins and create commands for each plugin identified
loadedPlugins, loadErr := pluginLoader().Load()
if loadErr != nil {
glog.V(1).Infof("Unable to load plugins: %v", loadErr)
}
cmd := &cobra.Command{
Use: "plugin NAME",
Use: "plugin [flags]",
DisableFlagsInUseLine: true,
Short: i18n.T("Runs a command-line plugin"),
Short: i18n.T("Provides utilities for interacting with plugins."),
Long: plugin_long,
Run: func(cmd *cobra.Command, args []string) {
if len(loadedPlugins) == 0 {
cmdutil.CheckErr(fmt.Errorf("no plugins installed."))
}
cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args)
},
}
if len(loadedPlugins) > 0 {
pluginRunner := pluginRunner()
for _, p := range loadedPlugins {
cmd.AddCommand(NewCmdForPlugin(f, p, pluginRunner, streams))
}
}
cmd.AddCommand(NewCmdPluginList(f, streams))
return cmd
}
// NewCmdForPlugin creates a command capable of running the provided plugin.
func NewCmdForPlugin(f cmdutil.Factory, plugin *plugins.Plugin, runner plugins.PluginRunner, streams genericclioptions.IOStreams) *cobra.Command {
if !plugin.IsValid() {
return nil
type PluginListOptions struct {
Verifier PathVerifier
NameOnly bool
genericclioptions.IOStreams
}
// NewCmdPluginList provides a way to list all plugin executables visible to kubectl
func NewCmdPluginList(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := &PluginListOptions{
IOStreams: streams,
}
cmd := &cobra.Command{
Use: plugin.Name,
Short: plugin.ShortDesc,
Long: templates.LongDesc(plugin.LongDesc),
Example: templates.Examples(plugin.Example),
Use: "list",
Short: "list all visible plugin executables on a user's PATH",
Long: plugin_list_long,
Run: func(cmd *cobra.Command, args []string) {
if len(plugin.Command) == 0 {
cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args)
return
}
envProvider := &plugins.MultiEnvProvider{
&plugins.PluginCallerEnvProvider{},
&plugins.OSEnvProvider{},
&plugins.PluginDescriptorEnvProvider{
Plugin: plugin,
},
&flagsPluginEnvProvider{
cmd: cmd,
},
&factoryAttrsPluginEnvProvider{
factory: f,
},
}
runningContext := plugins.RunningContext{
IOStreams: streams,
Args: args,
EnvProvider: envProvider,
WorkingDir: plugin.Dir,
}
if err := runner.Run(plugin, runningContext); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
// check for (and exit with) the correct exit code
// from a failed plugin command execution
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
fmt.Fprintf(streams.ErrOut, "error: %v\n", err)
os.Exit(status.ExitStatus())
}
}
cmdutil.CheckErr(err)
}
cmdutil.CheckErr(o.Complete(cmd))
cmdutil.CheckErr(o.Run())
},
}
for _, flag := range plugin.Flags {
cmd.Flags().StringP(flag.Name, flag.Shorthand, flag.DefValue, flag.Desc)
}
for _, childPlugin := range plugin.Tree {
cmd.AddCommand(NewCmdForPlugin(f, childPlugin, runner, streams))
}
cmd.Flags().BoolVar(&o.NameOnly, "name-only", o.NameOnly, "If true, display only the binary name of each plugin, rather than its full path")
return cmd
}
type flagsPluginEnvProvider struct {
cmd *cobra.Command
func (o *PluginListOptions) Complete(cmd *cobra.Command) error {
o.Verifier = &CommandOverrideVerifier{
root: cmd.Root(),
seenPlugins: make(map[string]string, 0),
}
return nil
}
func (p *flagsPluginEnvProvider) Env() (plugins.EnvList, error) {
globalPrefix := "KUBECTL_PLUGINS_GLOBAL_FLAG_"
env := plugins.EnvList{}
p.cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
env = append(env, plugins.FlagToEnv(flag, globalPrefix))
})
localPrefix := "KUBECTL_PLUGINS_LOCAL_FLAG_"
p.cmd.LocalFlags().VisitAll(func(flag *pflag.Flag) {
env = append(env, plugins.FlagToEnv(flag, localPrefix))
})
return env, nil
func (o *PluginListOptions) Run() error {
path := "PATH"
if runtime.GOOS == "windows" {
path = "path"
}
pluginsFound := false
isFirstFile := true
pluginWarnings := 0
paths := sets.NewString(filepath.SplitList(os.Getenv(path))...)
for _, dir := range paths.List() {
files, err := ioutil.ReadDir(dir)
if err != nil {
continue
}
for _, f := range files {
if f.IsDir() {
continue
}
if !strings.HasPrefix(f.Name(), "kubectl-") {
continue
}
if isFirstFile {
fmt.Fprintf(o.ErrOut, "The following kubectl-compatible plugins are available:\n\n")
pluginsFound = true
isFirstFile = false
}
pluginPath := f.Name()
if !o.NameOnly {
pluginPath = filepath.Join(dir, pluginPath)
}
fmt.Fprintf(o.Out, "%s\n", pluginPath)
if errs := o.Verifier.Verify(filepath.Join(dir, f.Name())); len(errs) != 0 {
for _, err := range errs {
fmt.Fprintf(o.ErrOut, " - %s\n", err)
pluginWarnings++
}
}
}
}
if !pluginsFound {
return fmt.Errorf("error: unable to find any kubectl plugins in your PATH")
}
if pluginWarnings > 0 {
fmt.Fprintln(o.ErrOut)
if pluginWarnings == 1 {
return fmt.Errorf("one plugin warning was found")
}
return fmt.Errorf("%v plugin warnings were found", pluginWarnings)
}
return nil
}
type factoryAttrsPluginEnvProvider struct {
factory cmdutil.Factory
// pathVerifier receives a path and determines if it is valid or not
type PathVerifier interface {
// Verify determines if a given path is valid
Verify(path string) []error
}
func (p *factoryAttrsPluginEnvProvider) Env() (plugins.EnvList, error) {
cmdNamespace, _, err := p.factory.ToRawKubeConfigLoader().Namespace()
type CommandOverrideVerifier struct {
root *cobra.Command
seenPlugins map[string]string
}
// Verify implements PathVerifier and determines if a given path
// is valid depending on whether or not it overwrites an existing
// kubectl command path, or a previously seen plugin.
func (v *CommandOverrideVerifier) Verify(path string) []error {
if v.root == nil {
return []error{fmt.Errorf("unable to verify path with nil root")}
}
// extract the plugin binary name
segs := strings.Split(path, "/")
binName := segs[len(segs)-1]
cmdPath := strings.Split(binName, "-")
if len(cmdPath) > 1 {
// the first argument is always "kubectl" for a plugin binary
cmdPath = cmdPath[1:]
}
errors := []error{}
if isExec, err := isExecutable(path); err == nil && !isExec {
errors = append(errors, fmt.Errorf("warning: %s identified as a kubectl plugin, but it is not executable", path))
} else if err != nil {
errors = append(errors, fmt.Errorf("error: unable to identify %s as an executable file: %v", path, err))
}
if existingPath, ok := v.seenPlugins[binName]; ok {
errors = append(errors, fmt.Errorf("warning: %s is overshadowed by a similarly named plugin: %s", path, existingPath))
} else {
v.seenPlugins[binName] = path
}
if cmd, _, err := v.root.Find(cmdPath); err == nil {
errors = append(errors, fmt.Errorf("warning: %s overwrites existing command: %q", binName, cmd.CommandPath()))
}
return errors
}
func isExecutable(fullPath string) (bool, error) {
info, err := os.Stat(fullPath)
if err != nil {
return plugins.EnvList{}, err
return false, err
}
return plugins.EnvList{
plugins.Env{N: "KUBECTL_PLUGINS_CURRENT_NAMESPACE", V: cmdNamespace},
}, nil
}
// pluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var.
// If this env var is not set, it defaults to
// "~/.kube/plugins", plus
// "./kubectl/plugins" directory under the "data dir" directory specified by the XDG
// system directory structure spec for the given platform.
func pluginLoader() plugins.PluginLoader {
if len(os.Getenv("KUBECTL_PLUGINS_PATH")) > 0 {
return plugins.KubectlPluginsPathPluginLoader()
if runtime.GOOS == "windows" {
if strings.HasSuffix(info.Name(), ".exe") {
return true, nil
}
return false, nil
}
return plugins.TolerantMultiPluginLoader{
plugins.XDGDataDirsPluginLoader(),
plugins.UserDirPluginLoader(),
}
}
func pluginRunner() plugins.PluginRunner {
return &plugins.ExecPluginRunner{}
if m := info.Mode(); !m.IsDir() && m&0111 != 0 {
return true, nil
}
return false, nil
}