From a79a420fde1ef3179dc29aaf9fcd5bd1aa64d0f4 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Sun, 3 Apr 2016 19:24:58 +0200 Subject: [PATCH] Move shell completion generation into 'kubectl completion' command --- build/common.sh | 3 - cmd/genbashcomp/gen_kubectl_bash_comp.go | 49 ------- contrib/completions/bash/MAINTAINERS.md | 6 - hack/lib/golang.sh | 1 - hack/lib/util.sh | 5 +- hack/update-generated-docs.sh | 1 - hack/verify-generated-docs.sh | 1 - pkg/kubectl/cmd/cmd.go | 1 + .../kubectl => pkg/kubectl/cmd/completion.go | 126 ++++++++++++++++-- 9 files changed, 119 insertions(+), 74 deletions(-) delete mode 100644 cmd/genbashcomp/gen_kubectl_bash_comp.go delete mode 100644 contrib/completions/bash/MAINTAINERS.md rename contrib/completions/zsh/kubectl => pkg/kubectl/cmd/completion.go (54%) mode change 100755 => 100644 diff --git a/build/common.sh b/build/common.sh index 7bc18ce04ba..2a40f21a964 100755 --- a/build/common.sh +++ b/build/common.sh @@ -478,7 +478,6 @@ function kube::build::source_targets() { test third_party vendor - contrib/completions/bash/kubectl contrib/mesos .generated_docs ) @@ -1022,8 +1021,6 @@ function kube::release::package_full_tarball() { cp "${KUBE_ROOT}/README.md" "${release_stage}/" cp "${KUBE_ROOT}/Godeps/LICENSES" "${release_stage}/" cp "${KUBE_ROOT}/Vagrantfile" "${release_stage}/" - mkdir -p "${release_stage}/contrib/completions/bash" - cp "${KUBE_ROOT}/contrib/completions/bash/kubectl" "${release_stage}/contrib/completions/bash" echo "${KUBE_GIT_VERSION}" > "${release_stage}/version" diff --git a/cmd/genbashcomp/gen_kubectl_bash_comp.go b/cmd/genbashcomp/gen_kubectl_bash_comp.go deleted file mode 100644 index c3b40b5e56f..00000000000 --- a/cmd/genbashcomp/gen_kubectl_bash_comp.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors All rights reserved. - -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 main - -import ( - "fmt" - "io/ioutil" - "os" - - "k8s.io/kubernetes/cmd/genutils" - "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -func main() { - // use os.Args instead of "flags" because "flags" will mess up the man pages! - path := "contrib/completions/bash/" - if len(os.Args) == 2 { - path = os.Args[1] - } else if len(os.Args) > 2 { - fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0]) - os.Exit(1) - } - - outDir, err := genutils.OutDir(path) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err) - os.Exit(1) - } - outFile := outDir + "kubectl" - - // TODO os.Stdin should really be something like ioutil.Discard, but a Reader - kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) - kubectl.GenBashCompletionFile(outFile) -} diff --git a/contrib/completions/bash/MAINTAINERS.md b/contrib/completions/bash/MAINTAINERS.md deleted file mode 100644 index db61ffbd91a..00000000000 --- a/contrib/completions/bash/MAINTAINERS.md +++ /dev/null @@ -1,6 +0,0 @@ -# Maintainers - -Eric Paris - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/contrib/completions/bash/MAINTAINERS.md?pixel)]() diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh index e130e75f1e4..b8bfabceb83 100755 --- a/hack/lib/golang.sh +++ b/hack/lib/golang.sh @@ -111,7 +111,6 @@ kube::golang::test_targets() { cmd/genman cmd/genyaml cmd/mungedocs - cmd/genbashcomp cmd/genswaggertypedocs cmd/linkcheck examples/k8petstore/web-server/src diff --git a/hack/lib/util.sh b/hack/lib/util.sh index 27b76bada25..e38c9b3b343 100755 --- a/hack/lib/util.sh +++ b/hack/lib/util.sh @@ -176,7 +176,7 @@ kube::util::find-binary() { echo -n "${bin}" } -# Run all known doc generators (today gendocs, genman, and genbashcomp for kubectl) +# Run all known doc generators (today gendocs and genman for kubectl) # $1 is the directory to put those generated documents kube::util::gen-docs() { local dest="$1" @@ -186,7 +186,6 @@ kube::util::gen-docs() { genkubedocs=$(kube::util::find-binary "genkubedocs") genman=$(kube::util::find-binary "genman") genyaml=$(kube::util::find-binary "genyaml") - genbashcomp=$(kube::util::find-binary "genbashcomp") genfeddocs=$(kube::util::find-binary "genfeddocs") mkdir -p "${dest}/docs/user-guide/kubectl/" @@ -203,8 +202,6 @@ kube::util::gen-docs() { "${genman}" "${dest}/docs/man/man1/" mkdir -p "${dest}/docs/yaml/kubectl/" "${genyaml}" "${dest}/docs/yaml/kubectl/" - mkdir -p "${dest}/contrib/completions/bash/" - "${genbashcomp}" "${dest}/contrib/completions/bash/" # create the list of generated files pushd "${dest}" > /dev/null diff --git a/hack/update-generated-docs.sh b/hack/update-generated-docs.sh index 1cad9eb0ccd..f97dcd781be 100755 --- a/hack/update-generated-docs.sh +++ b/hack/update-generated-docs.sh @@ -28,7 +28,6 @@ kube::golang::setup_env cmd/genkubedocs \ cmd/genman \ cmd/genyaml \ - cmd/genbashcomp \ cmd/mungedocs \ federation/cmd/genfeddocs diff --git a/hack/verify-generated-docs.sh b/hack/verify-generated-docs.sh index 58a93d308f3..e4b38b3fafd 100755 --- a/hack/verify-generated-docs.sh +++ b/hack/verify-generated-docs.sh @@ -28,7 +28,6 @@ kube::golang::setup_env cmd/genkubedocs \ cmd/genman \ cmd/genyaml \ - cmd/genbashcomp \ cmd/mungedocs # Find binary diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 4f717dbac45..75b935b881d 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -235,6 +235,7 @@ Find more information at https://github.com/kubernetes/kubernetes.`, cmds.AddCommand(NewCmdVersion(f, out)) cmds.AddCommand(NewCmdExplain(f, out)) cmds.AddCommand(NewCmdConvert(f, out)) + cmds.AddCommand(NewCmdCompletion(f, out)) if cmds.Flag("namespace") != nil { if cmds.Flag("namespace").Annotations == nil { diff --git a/contrib/completions/zsh/kubectl b/pkg/kubectl/cmd/completion.go old mode 100755 new mode 100644 similarity index 54% rename from contrib/completions/zsh/kubectl rename to pkg/kubectl/cmd/completion.go index b7aa9264c23..678a0791779 --- a/contrib/completions/zsh/kubectl +++ b/pkg/kubectl/cmd/completion.go @@ -1,6 +1,101 @@ -#!/bin/zsh +/* +Copyright 2014 The Kubernetes Authors All rights reserved. -# Copyright 2016 The Kubernetes Authors All rights reserved. +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 cmd + +import ( + "bytes" + "io" + + "github.com/spf13/cobra" + + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" +) + +const ( + completion_long = `Output shell completion code for the given shell (bash or zsh). + +This command prints shell code which must be evaluation to provide interactive +completion of kubectl commands. +` + completion_example = ` +$ source <(kubectl completion bash) + +will load the kubectl completion code for bash. Note that this depends on the bash-completion +framework. It must be sourced before sourcing the kubectl completion, i.e. on the Mac: + +$ brew install bash-completion +$ source $(brew --prefix)/etc/bash_completion +$ source <(kubectl completion bash) + +If you use zsh, the following will load kubectl zsh completion: + +$ source <(kubectl completion zsh) +` +) + +var ( + completion_shells = map[string]func(out io.Writer, cmd *cobra.Command) error{ + "bash": runCompletionBash, + "zsh": runCompletionZsh, + } +) + +func NewCmdCompletion(f *cmdutil.Factory, out io.Writer) *cobra.Command { + shells := []string{} + for s := range completion_shells { + shells = append(shells, s) + } + + cmd := &cobra.Command{ + Use: "completion SHELL", + Short: "Output shell completion code for the given shell (bash or zsh)", + Long: completion_long, + Example: completion_example, + Run: func(cmd *cobra.Command, args []string) { + err := RunCompletion(f, out, cmd, args) + cmdutil.CheckErr(err) + }, + ValidArgs: shells, + } + + return cmd +} + +func RunCompletion(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return cmdutil.UsageError(cmd, "Shell not specified.") + } + if len(args) > 1 { + return cmdutil.UsageError(cmd, "Too many arguments. Expected only the shell type.") + } + run, found := completion_shells[args[0]] + if !found { + return cmdutil.UsageError(cmd, "Unsupported shell type %q.", args[0]) + } + + return run(out, cmd.Parent()) +} + +func runCompletionBash(out io.Writer, kubectl *cobra.Command) error { + return kubectl.GenBashCompletion(out) +} + +func runCompletionZsh(out io.Writer, kubectl *cobra.Command) error { + zsh_initialilzation := `# Copyright 2016 The Kubernetes Authors All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,13 +110,13 @@ # limitations under the License. __kubectl_bash_source() { - alias shopt=':' - alias _expand=_bash_expand - alias _complete=_bash_comp - emulate -L sh - setopt kshglob noshglob braceexpand + alias shopt=':' + alias _expand=_bash_expand + alias _complete=_bash_comp + emulate -L sh + setopt kshglob noshglob braceexpand - source "$@" + source "$@" } __kubectl_type() { @@ -160,5 +255,18 @@ __kubectl_bash_source <(sed \ -e "s/${LWORD}compopt${RWORD}/__kubectl_compopt/g" \ -e "s/${LWORD}declare${RWORD}/__kubectl_declare/g" \ -e "s/\\\$(type${RWORD}/\$(__kubectl_type/g" \ - $(dirname $0)/../bash/kubectl + <<'BASH_COMPLETION_EOF' +` + out.Write([]byte(zsh_initialilzation)) + + buf := new(bytes.Buffer) + kubectl.GenBashCompletion(buf) + out.Write(buf.Bytes()) + + zsh_tail := ` +BASH_COMPLETION_EOF ) +` + out.Write([]byte(zsh_tail)) + return nil +}