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