1/* 2Copyright 2016 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package completion 18 19import ( 20 "io" 21 22 "github.com/spf13/cobra" 23 24 cmdutil "k8s.io/kubectl/pkg/cmd/util" 25 "k8s.io/kubectl/pkg/util/i18n" 26 "k8s.io/kubectl/pkg/util/templates" 27) 28 29const defaultBoilerPlate = ` 30# Copyright 2016 The Kubernetes Authors. 31# 32# Licensed under the Apache License, Version 2.0 (the "License"); 33# you may not use this file except in compliance with the License. 34# You may obtain a copy of the License at 35# 36# http://www.apache.org/licenses/LICENSE-2.0 37# 38# Unless required by applicable law or agreed to in writing, software 39# distributed under the License is distributed on an "AS IS" BASIS, 40# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 41# See the License for the specific language governing permissions and 42# limitations under the License. 43` 44 45var ( 46 completionLong = templates.LongDesc(i18n.T(` 47 Output shell completion code for the specified shell (bash or zsh). 48 The shell code must be evaluated to provide interactive 49 completion of kubectl commands. This can be done by sourcing it from 50 the .bash_profile. 51 52 Detailed instructions on how to do this are available here: 53 54 for macOS: 55 https://kubernetes.io/docs/tasks/tools/install-kubectl-macos/#enable-shell-autocompletion 56 57 for linux: 58 https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#enable-shell-autocompletion 59 60 for windows: 61 https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/#enable-shell-autocompletion 62 63 Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2.`)) 64 65 completionExample = templates.Examples(i18n.T(` 66 # Installing bash completion on macOS using homebrew 67 ## If running Bash 3.2 included with macOS 68 brew install bash-completion 69 ## or, if running Bash 4.1+ 70 brew install bash-completion@2 71 ## If kubectl is installed via homebrew, this should start working immediately 72 ## If you've installed via other means, you may need add the completion to your completion directory 73 kubectl completion bash > $(brew --prefix)/etc/bash_completion.d/kubectl 74 75 76 # Installing bash completion on Linux 77 ## If bash-completion is not installed on Linux, install the 'bash-completion' package 78 ## via your distribution's package manager. 79 ## Load the kubectl completion code for bash into the current shell 80 source <(kubectl completion bash) 81 ## Write bash completion code to a file and source it from .bash_profile 82 kubectl completion bash > ~/.kube/completion.bash.inc 83 printf " 84 # Kubectl shell completion 85 source '$HOME/.kube/completion.bash.inc' 86 " >> $HOME/.bash_profile 87 source $HOME/.bash_profile 88 89 # Load the kubectl completion code for zsh[1] into the current shell 90 source <(kubectl completion zsh) 91 # Set the kubectl completion code for zsh[1] to autoload on startup 92 kubectl completion zsh > "${fpath[1]}/_kubectl"`)) 93) 94 95var ( 96 completionShells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{ 97 "bash": runCompletionBash, 98 "zsh": runCompletionZsh, 99 } 100) 101 102// NewCmdCompletion creates the `completion` command 103func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { 104 shells := []string{} 105 for s := range completionShells { 106 shells = append(shells, s) 107 } 108 109 cmd := &cobra.Command{ 110 Use: "completion SHELL", 111 DisableFlagsInUseLine: true, 112 Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)"), 113 Long: completionLong, 114 Example: completionExample, 115 Run: func(cmd *cobra.Command, args []string) { 116 cmdutil.CheckErr(RunCompletion(out, boilerPlate, cmd, args)) 117 }, 118 ValidArgs: shells, 119 } 120 121 return cmd 122} 123 124// RunCompletion checks given arguments and executes command 125func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error { 126 if len(args) == 0 { 127 return cmdutil.UsageErrorf(cmd, "Shell not specified.") 128 } 129 if len(args) > 1 { 130 return cmdutil.UsageErrorf(cmd, "Too many arguments. Expected only the shell type.") 131 } 132 run, found := completionShells[args[0]] 133 if !found { 134 return cmdutil.UsageErrorf(cmd, "Unsupported shell type %q.", args[0]) 135 } 136 137 return run(out, boilerPlate, cmd.Parent()) 138} 139 140func runCompletionBash(out io.Writer, boilerPlate string, kubectl *cobra.Command) error { 141 if len(boilerPlate) == 0 { 142 boilerPlate = defaultBoilerPlate 143 } 144 if _, err := out.Write([]byte(boilerPlate)); err != nil { 145 return err 146 } 147 148 return kubectl.GenBashCompletion(out) 149} 150 151func runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) error { 152 zshHead := "#compdef kubectl\ncompdef _kubectl kubectl\n" 153 out.Write([]byte(zshHead)) 154 155 if len(boilerPlate) == 0 { 156 boilerPlate = defaultBoilerPlate 157 } 158 if _, err := out.Write([]byte(boilerPlate)); err != nil { 159 return err 160 } 161 162 return kubectl.GenZshCompletion(out) 163} 164