Last active
April 24, 2022 22:59
-
-
Save washtubs/616a16f2a0039e2168cfc2007cde3c8b to your computer and use it in GitHub Desktop.
kubectl namespace completion for bash and zsh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The result of putting this snippet in your bashrc is working completion | |
# for kubernetes aliases of the following form: | |
# + k == kubectl | |
# + kfoo == kubectl -n foo (where foo is a namespace on your cluster) | |
source <(kubectl completion bash) | |
alias k=kubectl | |
complete -F __start_kubectl k | |
function define_kubectl_alias() { | |
alias=$1 # e.g. kfoo | |
ns=$2 # e.g. foo | |
alias $alias="kubectl -n $ns" | |
# Normally you call this here: | |
# complete -F __start_kubectl kfoo | |
# Unfortunately, when kubectl dispatches off to get a list of pods in a situation like | |
# % kfoo get pod <TAB> | |
# ...Your alias buries the -n $ns, so it will try to find pods in the default namespace | |
# which might just be empty. | |
# | |
# So we dynamically create a function with eval | |
# to delegate off to __start_kubectl after modifying *ALL* bash completion input variables. | |
# Documented here: https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html | |
# For the following explanation consider | |
# an *alias* would be "kfoo", | |
# and the *alias content* would be "kubectl -n foo" | |
# | |
# For the COMP_LINE we replace the alias with the alias content: | |
# kfoo becomes kubectl -n foo | |
# | |
# For the COMP_CWORD we add the difference in words between just the alias | |
# and the alias content since the current word is after substitution, that many words ahead, | |
# which is normally just 2 unless you changed the content | |
# | |
# For the COMP_WORDS we replace the first word with the 3 from the alias content | |
# | |
# For the COMP_POINT we add the difference in characters between the content and the alias | |
fn=__start_kubectl_$ns | |
definition=' | |
function '$fn'() { | |
local ns='$ns' | |
local alias='$alias' | |
# This can be whatever you want as long as it is simple. Below logic is quite generic. | |
local alias_content="kubectl -n $ns" | |
local alias_words=( $alias_content ) | |
local alias_content_words=$(printf %s $alias_content | wc -w) | |
local new_comp_line=$(printf %s "$COMP_LINE" | sed "s/^$alias/$alias_content/") | |
COMP_LINE=$new_comp_line | |
new_comp_words=() | |
for i in $(seq 0 $((${#alias_words[@]}-1))); do | |
new_comp_words+=( ${alias_words[$i]} ) | |
done | |
for i in $(seq 1 $((${#COMP_WORDS[@]}-1))); do | |
new_comp_words+=( ${COMP_WORDS[$i]} ) | |
done | |
COMP_WORDS=( "${new_comp_words[@]}" ) | |
COMP_CWORD=$((COMP_CWORD + ${#alias_words[@]} - 1)) | |
COMP_POINT=$((COMP_POINT + ${#alias_content} - ${#alias})) | |
__start_kubectl \"$@\" | |
}' | |
eval "$definition" | |
complete -F $fn $alias | |
} | |
# This part is optional, feel free to just use the function above to define your own aliases | |
# | |
# Loop through each namespace on the cluster and create an alias dynamically | |
# Note k8 namespaces will be passed to eval but there is no risk of anything malicious from that. | |
# They are limited to 63 characters, alphanumeric plus hyphens. | |
for ns in $(kubectl get ns --no-headers | awk '{print $1}') | |
do | |
define_kubectl_alias k$ns $ns | |
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The result of putting this snippet in your bashrc is working completion | |
# for kubernetes aliases of the following form: | |
# + k == kubectl | |
# + kfoo == kubectl -n foo (where foo is a namespace on your cluster) | |
alias k=kubectl | |
if [ $(zsh --version | awk '{print $2}') = "5.0.2" ]; then | |
# Bug in zsh 5.0.2. | |
# | |
# local tab=$(printf '\t') | |
# | |
# Makes an empty string in that version specifically, | |
# so we just patch what `kubectl completion zsh` gives us by throwing quotes around it. | |
source <(kubectl completion zsh | sed 's/local tab=$(printf .\\t.)/local tab="$(printf '"'"'\\t'"'"')"/') | |
else | |
source <(kubectl completion zsh) | |
fi | |
# This part is optional, feel free to just use the function above to define your own aliases | |
# | |
# Loop through each namespace on the cluster and create an alias dynamically | |
for ns in $(kubectl get ns --no-headers | awk '{print $1}') | |
do | |
alias k$ns="kubectl -n $ns" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note these are just snippets meant for copying. Spending startup time scanning kubectl namespaces every time your shell inits may or may not be appropriate depending on your use case. There are a couple machines I exclusively do kubectl on, so it makes sense there.
Also feel free to drop the handling for zsh 5.0.2 which is currently what I'm stuck with on RHEL 7. zsh is otherwise very simple and everything just works and you probably don't need this snippet.