forked from kubernetes/kubernetes
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request kubernetes#1246 from eparis/bash_completions
Introduce bash completions for kubecfg
- Loading branch information
Showing
1 changed file
with
202 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
#!bash | ||
# | ||
# bash completion file for core kubecfg commands | ||
# | ||
# This script provides completion of non replication controller options | ||
# | ||
# To enable the completions either: | ||
# - place this file in /etc/bash_completion.d | ||
# or | ||
# - copy this file and add the line below to your .bashrc after | ||
# bash completion features are loaded | ||
# . kubecfg | ||
# | ||
# Note: | ||
# Currently, the completions will not work if the apiserver daemon is not | ||
# running on localhost on the standard port 8080 | ||
|
||
__contains_word () { | ||
local w word=$1; shift | ||
for w in "$@"; do | ||
[[ $w = "$word" ]] && return | ||
done | ||
return 1 | ||
} | ||
|
||
# This should be provided by the bash-completions, but give a really simple | ||
# stoopid version just in case. It works most of the time. | ||
if ! declare -F _get_comp_words_by_ref >/dev/null 2>&1; then | ||
_get_comp_words_by_ref () | ||
{ | ||
while [ $# -gt 0 ]; do | ||
case "$1" in | ||
cur) | ||
cur=${COMP_WORDS[COMP_CWORD]} | ||
;; | ||
prev) | ||
prev=${COMP_WORDS[COMP_CWORD-1]} | ||
;; | ||
words) | ||
words=("${COMP_WORDS[@]}") | ||
;; | ||
cword) | ||
cword=$COMP_CWORD | ||
;; | ||
-n) | ||
shift # we don't handle excludes | ||
;; | ||
esac | ||
shift | ||
done | ||
} | ||
fi | ||
|
||
|
||
__has_service() { | ||
local i | ||
for ((i=0; i < cword; i++)); do | ||
local word=${words[i]} | ||
# strip everything after a / so things like pods/[id] match | ||
word=${word%%/*} | ||
if __contains_word "${word}" "${services[@]}" && | ||
! __contains_word "${words[i-1]}" "${opts[@]}"; then | ||
return 0 | ||
fi | ||
done | ||
return 1 | ||
} | ||
|
||
# call kubecfg list $1, | ||
# exclude blank lines | ||
# skip the header stuff kubecfg prints on the first 2 lines | ||
# append $1/ to the first column and use that in compgen | ||
__kubecfg_parse_list() | ||
{ | ||
local kubecfg_output | ||
if kubecfg_output=$(kubecfg list "$1" 2>/dev/null); then | ||
out=($(echo "${kubecfg_output}" | awk -v prefix="$1" '/^$/ {next} NR > 2 {print prefix"/"$1}')) | ||
COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) | ||
fi | ||
} | ||
|
||
_kubecfg_specific_service_match() | ||
{ | ||
case "$cur" in | ||
pods/*) | ||
__kubecfg_parse_list pods | ||
;; | ||
minions/*) | ||
__kubecfg_parse_list minions | ||
;; | ||
replicationControllers/*) | ||
__kubecfg_parse_list replicationControllers | ||
;; | ||
services/*) | ||
__kubecfg_parse_list services | ||
;; | ||
*) | ||
if __has_service; then | ||
return 0 | ||
fi | ||
compopt -o nospace | ||
COMPREPLY=( $( compgen -S / -W "${services[*]}" -- "$cur" ) ) | ||
;; | ||
esac | ||
} | ||
|
||
_kubecfg_service_match() | ||
{ | ||
if __has_service; then | ||
return 0 | ||
fi | ||
|
||
COMPREPLY=( $( compgen -W "${services[*]}" -- "$cur" ) ) | ||
} | ||
|
||
_kubecfg() | ||
{ | ||
local opts=( | ||
-h | ||
-c | ||
) | ||
local -A all_services=( | ||
[CREATE]="pods replicationControllers services" | ||
[UPDATE]="replicationControllers" | ||
[ALL]="pods replicationControllers services minions" | ||
) | ||
local services=(${all_services[ALL]}) | ||
local -A all_commands=( | ||
[WITH_JSON]="create update" | ||
[ALL]="create update get list delete stop rm rollingupdate resize" | ||
) | ||
local commands=(${all_commands[ALL]}) | ||
|
||
COMPREPLY=() | ||
local command | ||
local cur prev words cword | ||
_get_comp_words_by_ref -n : cur prev words cword | ||
|
||
if __contains_word "$prev" "${opts[@]}"; then | ||
case $prev in | ||
-c) | ||
_filedir '@(json|yml|yaml)' | ||
return 0 | ||
;; | ||
-h) | ||
return 0 | ||
;; | ||
esac | ||
fi | ||
|
||
if [[ "$cur" = -* ]]; then | ||
COMPREPLY=( $(compgen -W "${opts[*]}" -- "$cur") ) | ||
return 0 | ||
fi | ||
|
||
# if you passed -c, you are limited to create or update | ||
if __contains_word "-c" "${words[@]}"; then | ||
services=(${all_services[CREATE]} ${all_services[UPDATE]}) | ||
commands=(${all_commands[WITH_JSON]}) | ||
fi | ||
|
||
# figure out which command they are running, remembering that arguments to | ||
# options don't count as the command! So a hostname named 'create' won't | ||
# trip things up | ||
local i | ||
for ((i=0; i < cword; i++)); do | ||
if __contains_word "${words[i]}" "${commands[@]}" && | ||
! __contains_word "${words[i-1]}" "${opts[@]}"; then | ||
command=${words[i]} | ||
break | ||
fi | ||
done | ||
|
||
# tell the list of possible commands | ||
if [[ -z ${command} ]]; then | ||
COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) | ||
return 0 | ||
fi | ||
|
||
# remove services which you can't update given your command | ||
if [[ ${command} == "create" ]]; then | ||
services=(${all_services[CREATE]}) | ||
elif [[ ${command} == "update" ]]; then | ||
services=(${all_services[UPDATE]}) | ||
fi | ||
|
||
case $command in | ||
create | list) | ||
_kubecfg_service_match | ||
;; | ||
update | get | delete) | ||
_kubecfg_specific_service_match | ||
;; | ||
*) | ||
;; | ||
esac | ||
|
||
return 0 | ||
} | ||
|
||
complete -F _kubecfg kubecfg | ||
# ex: ts=4 sw=4 et filetype=sh |