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