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