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