github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/etc/bash_completion.d/juju2 (about) 1 # juju-core.bash_completion.sh: dynamic bash completion for juju cmdline, 2 # from parsed (and cached) juju status output. 3 # 4 # Author: JuanJo Ciarlante <jjo@canonical.com> 5 # Copyright 2013+, Canonical Ltd. 6 # License: GPLv3 7 # 8 9 # Print (return) all machines 10 _juju_machines_from_file() { 11 python -c ' 12 import json, sys; j=json.load(sys.stdin) 13 print "\n".join(j["machines"].keys());' < ${1?} 14 } 15 16 # Print (return) all units, each optionally postfixed by $2 (eg. 'myservice/0:') 17 _juju_units_from_file() { 18 python -c ' 19 trail="'${2}'" 20 import json, sys; j=json.load(sys.stdin) 21 all_units=[] 22 for k,v in j["services"].items(): 23 if v.get("units"): 24 all_units.extend(v.get("units",{}).keys()) 25 print "\n".join([unit + trail for unit in all_units]) 26 ' < ${1?} 27 } 28 29 # Print (return) all services 30 _juju_services_from_file() { 31 python -c ' 32 import json, sys; j=json.load(sys.stdin) 33 print "\n".join(j["services"].keys());' < ${1?} 34 } 35 36 # Print (return) both services and units, currently used for juju status completion 37 _juju_services_and_units_from_file() { 38 _juju_services_from_file "$@" 39 _juju_units_from_file "$@" 40 } 41 42 # Print (return) all juju commands 43 _juju_list_commands() { 44 juju help commands 2>/dev/null | awk '{print $1}' 45 } 46 47 # Print (return) flags for juju action, shamelessly excluding 48 # -m/--model for cleaner completion for common usage cases 49 # (e.g. juju ssh <TAB>, etc) 50 _juju_flags_for() { 51 test -z "${1}" && return 0 52 juju help ${1} 2>/dev/null |egrep -o -- '(^|-)-[a-z-]+'|egrep -v -- '^(-m|--model)'|sort -u 53 } 54 55 # Print (return) guessed completion function for cmd. 56 # Guessing is done by parsing 1st line of juju help <cmd>, 57 # see case switch below. 58 _juju_completion_func_for_cmd() { 59 local action=${1} cword=${2} 60 # if cword==1 or action==help, use _juju_list_commands 61 if [ "${cword}" -eq 1 -o "${action}" = help ]; then 62 echo _juju_list_commands 63 return 0 64 fi 65 # parse 1st line of juju help <cmd>, to guess the completion function 66 case $(juju help ${action} 2>/dev/null| head -1) in 67 # special case for ssh, scp which have 'service' in 1st line of help: 68 *\<unit*|*juju?ssh*|*juju?scp*) echo _juju_units_from_file;; 69 *\<service*) echo _juju_services_from_file;; 70 *\<machine*) echo _juju_machines_from_file;; 71 *pattern*) echo _juju_services_and_units_from_file;; # e.g. status 72 ?*) echo true ;; # help ok, existing command, no more expansion 73 *) echo false;; # failed, not a command 74 esac 75 } 76 77 # Print (return) filename from juju status cached output (if not expired), 78 # create cache dirs if needed 79 # - setups caching dir if non-existent 80 # - caches juju status output, $cache_mins minutes max 81 _juju_get_status_filename() { 82 local cache_mins=60 # ttl=60 mins 83 local cache_dir=$HOME/.cache/juju 84 local juju_status_file=${cache_dir}/juju-status-${JUJU_MODEL:-default} 85 # setup caching dir under ~/.cache/juju 86 test -d ${cache_dir} || install -d ${cache_dir} -m 700 87 # if can't find a fresh (age < $cache_mins) saved file, with a ~reasonable size ... 88 if [[ -z $(find "${juju_status_file}" -mmin -${cache_mins} -a -size +32c 2> /dev/null) ]]; then 89 # ... create it 90 juju status --format=json > "${juju_status_file}".tmp && \ 91 mv "${juju_status_file}".tmp "${juju_status_file}" 92 rm -f "${juju_status_file}".tmp 93 fi 94 if [ -r "${juju_status_file}" ]; then 95 echo "${juju_status_file}" 96 else 97 return 1 98 fi 99 } 100 # Main completion function wrap: 101 # calls passed completion function, also adding flags for cmd 102 _juju_complete_with_func() { 103 local action="${1}" func=${2?} 104 local cur 105 106 # scp is special, as we want ':' appended to unit names, 107 # and filename completion also. 108 local postfix_str= compgen_xtra= 109 if [ "${action}" = "scp" ]; then 110 local orig_comp_wordbreaks="${COMP_WORDBREAKS}" 111 COMP_WORDBREAKS="${COMP_WORDBREAKS/:/}" 112 postfix_str=':' 113 compgen_xtra='-A file' 114 compopt -o nospace 115 fi 116 juju_status_file= 117 # if func name ends with 'from_file', set juju_status_file 118 [[ ${func} =~ .*from_file ]] && juju_status_file=$(_juju_get_status_filename) 119 # build COMPREPLY from passed function stdout, and _juju_flags_for $action 120 cur="${COMP_WORDS[COMP_CWORD]}" 121 COMPREPLY=( $( compgen ${compgen_xtra} -W "$(${func} ${juju_status_file} ${postfix_str}) $(_juju_flags_for "${action}")" -- ${cur} )) 122 if [ "${action}" = "scp" ]; then 123 COMP_WORDBREAKS="${orig_comp_wordbreaks}" 124 compopt +o nospace 125 fi 126 return 0 127 } 128 129 # Not used here, available to the user for quick cache removal 130 _juju_completion_cache_rm() { 131 rm -fv $HOME/.cache/juju/juju-status-${JUJU_MODEL:-default} 132 } 133 134 # main completion function entry point 135 _juju() { 136 local action parsing_func 137 action="${COMP_WORDS[1]}" 138 COMPREPLY=() 139 parsing_func=$(_juju_completion_func_for_cmd "${action}" ${COMP_CWORD}) 140 test -z "${parsing_func}" && return 0 141 _juju_complete_with_func "${action}" "${parsing_func}" 142 return $? 143 } 144 complete -F _juju juju 145 # vim: ai et sw=2 ts=2