diff --git a/contrib/completion/bash/README.md b/contrib/completion/bash/README.md new file mode 100644 index 0000000000..b8b7386fe4 --- /dev/null +++ b/contrib/completion/bash/README.md @@ -0,0 +1,23 @@ +# Bash completion of Scaleway command-line + +This script helps you use `scw` command-line easily by generating a bash completion everytime you hit the `tab` key. + +## How it works + +- Simply copy the script named `scw.bash` to `/etc/bash_completion.d` it will be sourced everytime you login or you simulate a login. +- You can also put it in your `HOMEDIR` and source it with your login shell option by adding the following line in your `~/.bash_profile`: +``` +source ~/.scw.bash +``` + +## Tuning variables + +For more flexibility the behaviour of the completion if controlled by the following vars: + +- **GET_SCW_SRVS**: it could be an env variable in your shell set by the command `export GET_SCW_SRVS="yes"`. If this option is enabled the completion will call Scaleway API to fetch for your managed servers and displays them. It default to "no" because fetching servers names takes around 1s which is quite long for command-line completion. +- **GET_SCW_IMGS**: it could be an env variable in your shell set by the command `export GET_SCW_IMGS="yes"`. If this option is enabled the completion will call Scaleway API to fetch for the available images and displays them. It default to "no" because fetching images takes around 1s which is quite long for command-line completion. +- **nospace**: this is a built-in shell completion option when set to `-o nospace` allows you to remove the space add to word when the completion happens. + +## TODO + +- Tune every function completion for more parsing options by tracking all the sub-options and handle them. diff --git a/contrib/completion/bash/scw b/contrib/completion/bash/scw deleted file mode 100755 index 7ccdea9bf7..0000000000 --- a/contrib/completion/bash/scw +++ /dev/null @@ -1,1238 +0,0 @@ -#!/bin/bash -# -# bash completion file for core scw commands -# -# This script provides completion of: -# - commands and their options -# - server ids and names -# - image repos and tags -# - filepaths -# -# To enable the completions either: -# - place this file in /etc/bash_completion.d -# or -# - copy this file to e.g. ~/.scw-completion.sh and add the line -# below to your .bashrc after bash completion features are loaded -# . ~/.scw-completion.sh -# -# Note: -# Currently, the completions will not work unless `scw login` were completed -# -# Note for developers: -# Please arrange options sorted alphabetically by long name with the short -# options immediately following their corresponding long form. -# This order should be applied to lists, alternatives and code blocks. -# -# Inspired from https://github.com/docker/docker/blob/master/contrib/completion/bash/docker - -__scw_q() { - scw $@ 2>/dev/null -} - -__scw_servers_all() { - local IFS=$'\n' - local servers=( $(__scw_q _completion servers-all) ) - unset IFS - COMPREPLY=( $(compgen -W "${servers[*]}" -- "$cur") ) -} - -__scw_servers_running() { - __scw_servers_all -} - -__scw_servers_stopped() { - __scw_servers_all -} - -__scw_servers_pauseable() { - __scw_servers_all -} - -__scw_servers_unpauseable() { - __scw_servers_all -} - -__scw_server_names() { - __scw_servers_all -} - -__scw_server_ids() { - __scw_servers_all -} - -__scw_image_repos() { - local repos=( $(__scw_q _completion images-all) ) - COMPREPLY=( $(compgen -W "$repos" -- "$cur") ) -} - -__scw_image_repos_and_tags() { - __scw_image_repos -} - -__scw_image_repos_and_tags_and_ids() { - __scw_image_repos -} - -__scw_servers_and_images() { - __scw_servers_all - local servers=( "${COMPREPLY[@]}" ) - __scw_image_repos_and_tags_and_ids - COMPREPLY+=( "${servers[@]}" ) -} - -__scw_pos_first_nonflag() { - local argument_flags=$1 - - local counter=$cpos - while [ $counter -le $cword ]; do - if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then - (( counter++ )) - else - case "${words[$counter]}" in - -*) - ;; - *) - break - ;; - esac - fi - (( counter++ )) - done - - echo $counter -} - -# Transforms a multiline list of strings into a single line string -# with the words separated by "|". -# This is used to prepare arguments to __scw_pos_first_nonflag(). -__scw_to_alternatives() { - local parts=( $1 ) - local IFS='|' - echo "${parts[*]}" -} - -# Transforms a multiline list of options into an extglob pattern -# suitable for use in case statements. -__scw_to_extglob() { - local extglob=$( __scw_to_alternatives "$1" ) - echo "@($extglob)" -} - -__scw_resolve_hostname() { - command -v host >/dev/null 2>&1 || return - COMPREPLY=( $(host 2>/dev/null "${cur%:}" | awk '/has address/ {print $4}') ) -} - -__scw_capabilities() { - # The list of capabilities is defined in types.go, ALL was added manually. - COMPREPLY=( $( compgen -W " - ALL - AUDIT_CONTROL - AUDIT_WRITE - AUDIT_READ - BLOCK_SUSPEND - CHOWN - DAC_OVERRIDE - DAC_READ_SEARCH - FOWNER - FSETID - IPC_LOCK - IPC_OWNER - KILL - LEASE - LINUX_IMMUTABLE - MAC_ADMIN - MAC_OVERRIDE - MKNOD - NET_ADMIN - NET_BIND_SERVICE - NET_BROADCAST - NET_RAW - SETFCAP - SETGID - SETPCAP - SETUID - SYS_ADMIN - SYS_BOOT - SYS_CHROOT - SYSLOG - SYS_MODULE - SYS_NICE - SYS_PACCT - SYS_PTRACE - SYS_RAWIO - SYS_RESOURCE - SYS_TIME - SYS_TTY_CONFIG - WAKE_ALARM - " -- "$cur" ) ) -} - -# a selection of the available signals that is most likely of interest in the -# context of scw servers. -__scw_signals() { - local signals=( - SIGCONT - SIGHUP - SIGINT - SIGKILL - SIGQUIT - SIGSTOP - SIGTERM - SIGUSR1 - SIGUSR2 - ) - COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) ) -} - -_scw_scw() { - local boolean_options=" - --daemon -d - --debug -D - --help -h - --icc - --ip-forward - --ip-masq - --iptables - --ipv6 - --selinux-enabled - --tls - --tlsverify - --userland-proxy=false - --version -v - " - - case "$prev" in - --exec-root|--graph|-g) - _filedir -d - return - ;; - --log-driver) - COMPREPLY=( $( compgen -W "json-file syslog none" -- "$cur" ) ) - return - ;; - --log-level|-l) - COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) ) - return - ;; - --pidfile|-p|--tlscacert|--tlscert|--tlskey) - _filedir - return - ;; - --storage-driver|-s) - COMPREPLY=( $( compgen -W "aufs devicemapper btrfs overlay" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) ) - return - ;; - $main_options_with_args_glob ) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) ) - ;; - *) - COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) - ;; - esac -} - -_scw_attach() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --no-stdin --sig-proxy" -- "$cur" ) ) - ;; - *) - local counter="$(__scw_pos_first_nonflag)" - if [ $cword -eq $counter ]; then - __scw_servers_running - fi - ;; - esac -} - -_scw_build() { - case "$prev" in - --cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--memory|-m|--memory-swap) - return - ;; - --file|-f) - _filedir - return - ;; - --tag|-t) - __scw_image_repos_and_tags - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) ) - ;; - *) - local counter="$(__scw_pos_first_nonflag '--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--file|-f|--memory|-m|--memory-swap|--tag|-t')" - if [ $cword -eq $counter ]; then - _filedir -d - fi - ;; - esac -} - -_scw_commit() { - case "$prev" in - --author|-a|--change|-c|--message|-m) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--author -a --change -c --help --message -m --pause -p" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag '--author|-a|--change|-c|--message|-m') - - if [ $cword -eq $counter ]; then - __scw_servers_all - return - fi - (( counter++ )) - - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags - return - fi - ;; - esac -} - -_scw_cp() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - case "$cur" in - *:) - return - ;; - *) - __scw_servers_all - COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) - compopt -o nospace - return - ;; - esac - fi - (( counter++ )) - - if [ $cword -eq $counter ]; then - _filedir -d - return - fi - ;; - esac -} - -_scw_create() { - _scw_run -} - -_scw_diff() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_all - fi - ;; - esac -} - -_scw_events() { - case "$prev" in - --filter|-f) - COMPREPLY=( $( compgen -S = -W "server event image" -- "$cur" ) ) - compopt -o nospace - return - ;; - --since|--until) - return - ;; - esac - - # "=" gets parsed to a word and assigned to either $cur or $prev depending on whether - # it is the last character or not. So we search for "xxx=" in the the last two words. - case "${words[$cword-2]}$prev=" in - *server=*) - cur="${cur#=}" - __scw_servers_all - return - ;; - *event=*) - COMPREPLY=( $( compgen -W "create destroy die export kill pause restart start stop unpause" -- "${cur#=}" ) ) - return - ;; - *image=*) - cur="${cur#=}" - __scw_image_repos_and_tags_and_ids - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--filter -f --help --since --until" -- "$cur" ) ) - ;; - esac -} - -_scw_exec() { - case "$prev" in - --user|-u) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty -u --user" -- "$cur" ) ) - ;; - *) - __scw_servers_running - ;; - esac -} - -_scw_export() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_all - fi - ;; - esac -} - -_scw_help() { - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) - fi -} - -_scw_history() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --no-trunc --quiet -q" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags_and_ids - fi - ;; - esac -} - -_scw_images() { - case "$prev" in - --filter|-f) - COMPREPLY=( $( compgen -W "dangling=true label=" -- "$cur" ) ) - if [ "$COMPREPLY" = "label=" ]; then - compopt -o nospace - fi - return - ;; - esac - - case "${words[$cword-2]}$prev=" in - *dangling=*) - COMPREPLY=( $( compgen -W "true false" -- "${cur#=}" ) ) - return - ;; - *label=*) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--all -a --digests --filter -f --help --no-trunc --quiet -q" -- "$cur" ) ) - ;; - =) - return - ;; - *) - __scw_image_repos - ;; - esac -} - -_scw_import() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - return - fi - (( counter++ )) - - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags - return - fi - ;; - esac -} - -_scw_info() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - esac -} - -_scw_inspect() { - case "$prev" in - --format|-f) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) - ;; - *) - __scw_servers_and_images - ;; - esac -} - -_scw_kill() { - case "$prev" in - --signal|-s) - __scw_signals - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --signal -s" -- "$cur" ) ) - ;; - *) - __scw_servers_running - ;; - esac -} - -_scw_load() { - case "$prev" in - --input|-i) - _filedir - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --input -i" -- "$cur" ) ) - ;; - esac -} - -_scw_login() { - case "$prev" in - --email|-e|--password|-p|--username|-u) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--email -e --help --password -p --username -u" -- "$cur" ) ) - ;; - esac -} - -_scw_logout() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - esac -} - -_scw_logs() { - case "$prev" in - --since|--tail) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--follow -f --help --since --tail --timestamps -t" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag '--tail') - if [ $cword -eq $counter ]; then - __scw_servers_all - fi - ;; - esac -} - -_scw_pause() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_pauseable - fi - ;; - esac -} - -_scw_port() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_all - fi - ;; - esac -} - -_scw_products() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help -s --short" -- "$cur" ) ) - ;; - *) - COMPREPLY=( $( compgen -W "servers" -- "$cur" ) ) - ;; - esac -} - -_scw_ps() { - case "$prev" in - --before|--since) - __scw_servers_all - ;; - --filter|-f) - COMPREPLY=( $( compgen -S = -W "exited id label name status" -- "$cur" ) ) - compopt -o nospace - return - ;; - -n) - return - ;; - esac - - case "${words[$cword-2]}$prev=" in - *id=*) - cur="${cur#=}" - __scw_server_ids - return - ;; - *name=*) - cur="${cur#=}" - __scw_server_names - return - ;; - *status=*) - COMPREPLY=( $( compgen -W "exited paused restarting running" -- "${cur#=}" ) ) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--all -a --before --filter -f --help --latest -l -n --no-trunc --quiet -q --size -s --since" -- "$cur" ) ) - ;; - esac -} - -_scw_pull() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--all-tags -a --help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - for arg in "${COMP_WORDS[@]}"; do - case "$arg" in - --all-tags|-a) - __scw_image_repos - return - ;; - esac - done - __scw_image_repos_and_tags - fi - ;; - esac -} - -_scw_push() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags - fi - ;; - esac -} - -_scw_rename() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_all - fi - ;; - esac -} - -_scw_restart() { - case "$prev" in - --time|-t) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) - ;; - *) - __scw_servers_all - ;; - esac -} - -_scw_rm() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--force -f --help --link -l --volumes -v" -- "$cur" ) ) - ;; - *) - for arg in "${COMP_WORDS[@]}"; do - case "$arg" in - --force|-f) - __scw_servers_all - return - ;; - esac - done - __scw_servers_stopped - ;; - esac -} - -_scw_rmi() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) ) - ;; - *) - __scw_image_repos_and_tags_and_ids - ;; - esac -} - -_scw_run() { - local options_with_args=" - --add-host - --blkio-weight - --attach -a - --cap-add - --cap-drop - --cgroup-parent - --cidfile - --cpuset - --cpu-period - --cpu-quota - --cpu-shares -c - --device - --dns - --dns-search - --entrypoint - --env -e - --env-file - --expose - --hostname -h - --ipc - --label -l - --label-file - --link - --log-driver - --lxc-conf - --mac-address - --memory -m - --memory-swap - --name - --net - --pid - --publish -p - --restart - --security-opt - --user -u - --ulimit - --uts - --volumes-from - --volume -v - --workdir -w - " - - local all_options="$options_with_args - --help - --interactive -i - --privileged - --publish-all -P - --read-only - --tty -t - " - - [ "$command" = "run" ] && all_options="$all_options - --detach -d - --rm - --sig-proxy - " - - local options_with_args_glob=$(__scw_to_extglob "$options_with_args") - - case "$prev" in - --add-host) - case "$cur" in - *:) - __scw_resolve_hostname - return - ;; - esac - ;; - --attach|-a) - COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) ) - return - ;; - --cap-add|--cap-drop) - __scw_capabilities - return - ;; - --cidfile|--env-file|--label-file) - _filedir - return - ;; - --device|--volume|-v) - case "$cur" in - *:*) - # TODO somehow do _filedir for stuff inside the image, if it's already specified (which is also somewhat difficult to determine) - ;; - '') - COMPREPLY=( $( compgen -W '/' -- "$cur" ) ) - compopt -o nospace - ;; - /*) - _filedir - compopt -o nospace - ;; - esac - return - ;; - --env|-e) - COMPREPLY=( $( compgen -e -- "$cur" ) ) - compopt -o nospace - return - ;; - --ipc) - case "$cur" in - *:*) - cur="${cur#*:}" - __scw_servers_running - ;; - *) - COMPREPLY=( $( compgen -W 'host server:' -- "$cur" ) ) - if [ "$COMPREPLY" = "server:" ]; then - compopt -o nospace - fi - ;; - esac - return - ;; - --link) - case "$cur" in - *:*) - ;; - *) - __scw_servers_running - COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) - compopt -o nospace - ;; - esac - return - ;; - --log-driver) - COMPREPLY=( $( compgen -W "json-file syslog none" -- "$cur") ) - return - ;; - --net) - case "$cur" in - server:*) - local cur=${cur#*:} - __scw_servers_all - ;; - *) - COMPREPLY=( $( compgen -W "bridge none server: host" -- "$cur") ) - if [ "${COMPREPLY[*]}" = "server:" ] ; then - compopt -o nospace - fi - ;; - esac - return - ;; - --restart) - case "$cur" in - on-failure:*) - ;; - *) - COMPREPLY=( $( compgen -W "no on-failure on-failure: always" -- "$cur") ) - ;; - esac - return - ;; - --security-opt) - case "$cur" in - label:*:*) - ;; - label:*) - local cur=${cur##*:} - COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "$cur") ) - if [ "${COMPREPLY[*]}" != "disable" ] ; then - compopt -o nospace - fi - ;; - *) - COMPREPLY=( $( compgen -W "label apparmor" -S ":" -- "$cur") ) - compopt -o nospace - ;; - esac - return - ;; - --volumes-from) - __scw_servers_all - return - ;; - $options_with_args_glob ) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) - ;; - *) - local counter=$( __scw_pos_first_nonflag $( __scw_to_alternatives "$options_with_args" ) ) - - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags_and_ids - fi - ;; - esac -} - -_scw_save() { - case "$prev" in - --output|-o) - _filedir - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) ) - ;; - *) - __scw_image_repos_and_tags_and_ids - ;; - esac -} - -_scw_search() { - case "$prev" in - --stars|-s) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--automated --help --no-trunc --stars -s" -- "$cur" ) ) - ;; - esac -} - -_scw_start() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--attach -a --help --interactive -i" -- "$cur" ) ) - ;; - *) - __scw_servers_stopped - ;; - esac -} - -_scw_stats() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--no-stream --help" -- "$cur" ) ) - ;; - *) - __scw_servers_running - ;; - esac -} - -_scw_stop() { - case "$prev" in - --time|-t) - return - ;; - esac - - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) - ;; - *) - __scw_servers_running - ;; - esac -} - -_scw_tag() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--force -f --help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags - return - fi - (( counter++ )) - - if [ $cword -eq $counter ]; then - __scw_image_repos_and_tags - return - fi - ;; - esac -} - -_scw_unpause() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_unpauseable - fi - ;; - esac -} - -_scw_top() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__scw_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __scw_servers_running - fi - ;; - esac -} - -_scw_version() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - esac -} - -_scw_wait() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - __scw_servers_all - ;; - esac -} - -_scw() { - local previous_extglob_setting=$(shopt -p extglob) - shopt -s extglob - - local commands=( - attach -# build - commit - cp - create -# diff - events - exec -# export - history - images -# import - info - inspect - kill -# load - login -# logout - logs -# pause - port - products - ps -# pull -# push - rename - restart - rm - rmi - run -# save - search - start -# stats - stop - tag - top -# unpause - version - wait - ) - - local main_options_with_args=" - --api-cors-header - --bip - --bridge -b - --default-gateway - --default-gateway-v6 - --default-ulimit - --dns - --dns-search - --exec-driver -e - --exec-opt - --exec-root - --fixed-cidr - --fixed-cidr-v6 - --graph -g - --group -G - --host -H - --insecure-registry - --ip - --label - --log-driver - --log-level -l - --mtu - --pidfile -p - --registry-mirror - --storage-driver -s - --storage-opt - --tlscacert - --tlscert - --tlskey - " - - local main_options_with_args_glob=$(__scw_to_extglob "$main_options_with_args") - local host - - COMPREPLY=() - local cur prev words cword - _get_comp_words_by_ref -n : cur prev words cword - - local command='scw' cpos=0 - local counter=1 - while [ $counter -lt $cword ]; do - case "${words[$counter]}" in - # save host so that completion can use custom daemon - --host|-H) - (( counter++ )) - host="${words[$counter]}" - ;; - $main_options_with_args_glob ) - (( counter++ )) - ;; - -*) - ;; - =) - (( counter++ )) - ;; - *) - command="${words[$counter]}" - cpos=$counter - (( cpos++ )) - break - ;; - esac - (( counter++ )) - done - - local completions_func=_scw_${command} - declare -F $completions_func >/dev/null && $completions_func - - eval "$previous_extglob_setting" - return 0 -} - -complete -F _scw scw diff --git a/contrib/completion/bash/scw.bash b/contrib/completion/bash/scw.bash new file mode 100644 index 0000000000..729149bfe9 --- /dev/null +++ b/contrib/completion/bash/scw.bash @@ -0,0 +1,778 @@ +# Scaleway command-line bash completion +shopt -s extglob + +# Requesting the servers/images in real time takes almost 1s which is long in a shell +# completion process - the following env variables (toggles) disable that behaviour +#GET_SCW_SRVS="no" +#GET_SCW_IMGS="no" + +# Initialization +servers="" +images="" + +# If you want to remove the inserted space after bash completion uncomment this line +# and comment the line just after it +#_nospace="-o nospace" +_nospace="" + +_get_servers () +{ + # Get a list of servers owned by the user. + + if [[ "${GET_SCW_SRVS}" =~ ^(yes|YES|0)$ ]] + then + servers=$(scw ps | awk '$0 !~ /SERVER/ {print $1}') + fi +} + +_get_images () +{ + # Get a list of available images. + + if [[ "${GET_SCW_IMGS}" =~ ^(yes|YES|0)$ ]] + then + images=$(scw images | awk '$0 !~ /REPOSITORY/ {print $1}') + fi +} + +_scw_attach () +{ + # Attach to a running server serial console. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--no-stdin + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_commit () +{ + # Create a new snapshot from a server's volume. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-v + --volume + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_cp () +{ + # Copy files/folders from a PATH on the server to a HOSTDIR on the host + # running the command. Use '-' to write the data as a tar file to STDOUT. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-g + --gateway + -p + --port + --user + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_create () +{ + #Create a new server but do not start it. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--bootscript + --commercial-type + -e + --env + --ip-address + --ipv6 + --name + --tmp-ssh-key + -v + --volume + -h + --help" + + _get_images + + COMPREPLY=( $(compgen -W "${words} ${images}" -- ${cur}) ) + return 0 +} + +_scw_events () +{ + # Get real time events from the API. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_exec () +{ + # Run a command on a running server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--A + --g + --gateway + -p + --port + -T + --timeout + --user + -w + --wait + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_history () +{ + # Show the history of an image. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--arch + --no-trunc + -q + --quiet + -h + --help" + + _get_images + + COMPREPLY=( $(compgen -W "${words} ${images}" -- ${cur}) ) + return 0 +} + +_scw_images () +{ + # List images. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-a + --all + -f + --filter + --no-trunc + -q + --quiet + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_info () +{ + # Display system-wide information. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_inspect () +{ + # Return low-level information on a server, image, snapshot, volume or bootscript. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--arch + -b + --browser + -f + --format + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_kill () +{ + # Kill a running server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-g + --gateway + -p + --port + -u + --user + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_login () +{ + # Generates a configuration file in '/home/$USER/.scwrc' + # containing credentials used to interact with the Scaleway API. This + # configuration file is automatically used by the 'scw' commands. + # + # You can get your credentials on https://cloud.scaleway.com/#/credentials + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-o + --organization + -s + --skip-ssh-key + -t + --token + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_logout () +{ + # Log out from the Scaleway API. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_logs () +{ + # Fetch the logs of a server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-g + --gateway + -p + --port + --user + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_port () +{ + # List port mappings for the SERVER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-g + --gateway + -p + --port + --user + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_products () +{ + # Display products PRODUCT information. At the moment only `servers` is supported. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="servers + -s + --short + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_ps () +{ + # List servers. By default, only running servers are displayed. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-a + --all + -f + --filter + -l + --latest + -n + --no-trunc + -q + --quit + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_rename () +{ + # Rename a server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_restart () +{ + # Restart a running server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-T + --timeout + -w + --wait + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_rm () +{ + # Remove one or more servers. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-f + --force + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_rmi () +{ + # Remove one or more image(s)/volume(s)/snapshot(s) + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_run () +{ + # Run a command in a new server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-a + --attach + --bootscript + --commercial-type + -d + --detach + -e + --env + -g + --gateway + --ip-address + --ipv6 + --name + -p + --port + --rm + --show-boot + -T + --timeout + --tmp-ssh-key + -u + --userdata + --user + -v + --volume + -h + --help" + + _get_images + + COMPREPLY=( $(compgen -W "${words} ${images}" -- ${cur}) ) + return 0 +} + +_scw_search () +{ + # Search the Scaleway Hub for images. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--no-trunc + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_start () +{ + # Start a stopped server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--set-state + -T + --timeout + -w + --wait + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_stop () +{ + # Stop a running server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-t + --terminate + -w + --wait + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_tag () +{ + # Tag a snapshot into an image. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="--arch + --bootscript + -h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_top () +{ + # Lookup the running processes of a server. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-g + --gateway + -p + --port + -h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw_version () +{ + # Show the version information. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + COMPREPLY=( $(compgen -W "${words}" -- ${cur}) ) + return 0 +} + +_scw_wait () +{ + # Block until a server stops. + + local cur prev grps words=() #split=false + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + COMPREPLY=() + words="-h + --help" + + _get_servers + + COMPREPLY=( $(compgen -W "${words} ${servers}" -- ${cur}) ) + return 0 +} + +_scw () +{ + local cur prev grps words=() #split=false + + COMPREPLY=() + options="-D + --debug + -V + --verbose + -q + --quiet + --sensitive + -v + --version + --region" + words="attach + commit + cp + create + events + exec + history + images + info + inspect + kill + login + logout + logs + port + products + ps + rename + restart + rm + rmi + run + search + start + stop + tag + top + version + wait" + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # trigger var is used to check if bash completes when there is only options on the line + trigger="no" + + case ${prev} in + scw) + COMPREPLY=( $(compgen -W "${words} ${options}" -- ${cur}) ) + ;; + + @($(echo ${words} | tr ' ' '|')) ) + _scw_${prev} + ;; + + @($(echo ${options} | tr ' ' '|')) ) + COMPREPLY=( $(compgen -W "${words} ${options}" -- ${cur}) ) + ;; + + *) + for word in ${COMP_WORDS[*]} + do + if [[ ${word} =~ ^($(echo ${words} | tr ' ' '|')) ]] + then + trigger="yes" + _scw_${word} + fi + done + if [[ ${trigger} != "yes" ]] + then + COMPREPLY=( $(compgen -W "${words} ${options}" -- ${cur}) ) + fi + ;; + esac + + return 0 +} && +complete -F _scw ${_nospace} -o noquote -o filenames scw