#!/bin/bash # # bash completion file for core docker commands # # This script provides completion of: # - commands and their options # - container 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. ~/.docker-completion.sh and add the line # below to your .bashrc after bash completion features are loaded # . ~/.docker-completion.sh # # Configuration: # # For several commands, the amount of completions can be configured by # setting environment variables. # # DOCKER_COMPLETION_SHOW_CONTAINER_IDS # DOCKER_COMPLETION_SHOW_NETWORK_IDS # DOCKER_COMPLETION_SHOW_NODE_IDS # DOCKER_COMPLETION_SHOW_SERVICE_IDS # "no" - Show names only (default) # "yes" - Show names and ids # # You can tailor completion for the "events", "history", "inspect", "run", # "rmi" and "save" commands by settings the following environment # variables: # # DOCKER_COMPLETION_SHOW_IMAGE_IDS # "none" - Show names only (default) # "non-intermediate" - Show names and ids, but omit intermediate image IDs # "all" - Show names and ids, including intermediate image IDs # # DOCKER_COMPLETION_SHOW_TAGS # "yes" - include tags in completion options (default) # "no" - don't include tags in completion options # # Note: # Currently, the completions will not work if the docker daemon is not # bound to the default communication port/socket # If the docker daemon is using a unix socket for communication your user # must have access to the socket for the completions to function correctly # # 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. __docker_previous_extglob_setting=$(shopt -p extglob) shopt -s extglob __docker_q() { docker ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@" } # __docker_containers returns a list of containers. Additional options to # `docker ps` may be specified in order to filter the list, e.g. # `__docker_containers --filter status=running` # By default, only names are returned. # Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs. # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. __docker_containers() { local format if [ "$1" = "--id" ] ; then format='{{.ID}}' shift elif [ "$1" = "--name" ] ; then format='{{.Names}}' shift elif [ "${DOCKER_COMPLETION_SHOW_CONTAINER_IDS}" = yes ] ; then format='{{.ID}} {{.Names}}' else format='{{.Names}}' fi __docker_q ps --format "$format" "$@" } # __docker_complete_containers applies completion of containers based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # Additional filters may be appended, see `__docker_containers`. __docker_complete_containers() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_containers "$@")" -- "$current") ) } __docker_complete_containers_all() { __docker_complete_containers "$@" --all } __docker_complete_containers_running() { __docker_complete_containers "$@" --filter status=running } __docker_complete_containers_stopped() { __docker_complete_containers "$@" --filter status=exited } __docker_complete_containers_unpauseable() { __docker_complete_containers "$@" --filter status=paused } __docker_complete_container_names() { local containers=( $(__docker_q ps -aq --no-trunc) ) local names=( $(__docker_q inspect --format '{{.Name}}' "${containers[@]}") ) names=( "${names[@]#/}" ) # trim off the leading "/" from the container names COMPREPLY=( $(compgen -W "${names[*]}" -- "$cur") ) } __docker_complete_container_ids() { local containers=( $(__docker_q ps -aq) ) COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) } __docker_complete_images() { local images_args="" case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in all) images_args="--no-trunc -a" ;; non-intermediate) images_args="--no-trunc" ;; esac local repo_print_command if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then repo_print_command='print $1; print $1":"$2' else repo_print_command='print $1' fi local awk_script case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in all|non-intermediate) awk_script='NR>1 { print $3; if ($1 != "") { '"$repo_print_command"' } }' ;; none|*) awk_script='NR>1 && $1 != "" { '"$repo_print_command"' }' ;; esac local images=$(__docker_q images $images_args | awk "$awk_script") COMPREPLY=( $(compgen -W "$images" -- "$cur") ) __ltrim_colon_completions "$cur" } __docker_complete_image_repos() { local repos="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1 }')" COMPREPLY=( $(compgen -W "$repos" -- "$cur") ) } __docker_complete_image_repos_and_tags() { local reposAndTags="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1; print $1":"$2 }')" COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") ) __ltrim_colon_completions "$cur" } __docker_complete_containers_and_images() { __docker_complete_containers_all local containers=( "${COMPREPLY[@]}" ) __docker_complete_images COMPREPLY+=( "${containers[@]}" ) } # __docker_networks returns a list of all networks. Additional options to # `docker network ls` may be specified in order to filter the list, e.g. # `__docker_networks --filter type=custom` # By default, only names are returned. # Set DOCKER_COMPLETION_SHOW_NETWORK_IDS=yes to also complete IDs. # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. __docker_networks() { local format if [ "$1" = "--id" ] ; then format='{{.ID}}' shift elif [ "$1" = "--name" ] ; then format='{{.Name}}' shift elif [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS}" = yes ] ; then format='{{.ID}} {{.Name}}' else format='{{.Name}}' fi __docker_q network ls --format "$format" "$@" } # __docker_complete_networks applies completion of networks based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # Additional filters may be appended, see `__docker_networks`. __docker_complete_networks() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_networks "$@")" -- "$current") ) } __docker_complete_containers_in_network() { local containers=$(__docker_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1") COMPREPLY=( $(compgen -W "$containers" -- "$cur") ) } # __docker_volumes returns a list of all volumes. Additional options to # `docker volume ls` may be specified in order to filter the list, e.g. # `__docker_volumes --filter dangling=true` # Because volumes do not have IDs, this function does not distinguish between # IDs and names. __docker_volumes() { __docker_q volume ls -q "$@" } # __docker_complete_volumes applies completion of volumes based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # Additional filters may be appended, see `__docker_volumes`. __docker_complete_volumes() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_volumes "$@")" -- "$current") ) } # __docker_plugins returns a list of all plugins of a given type. # The type has to be specified with the mandatory option `--type`. # Valid types are: Network, Volume, Authorization. # Completions may be added or removed with `--add` and `--remove` __docker_plugins() { local type add=() remove=() while true ; do case "$1" in --type) type="$2" shift 2 ;; --add) add+=("$2") shift 2 ;; --remove) remove+=("$2") shift 2 ;; *) break ;; esac done local plugins=($(__docker_q info | sed -n "/^Plugins/,/^[^ ]/s/ $type: //p")) for del in "${remove[@]}" ; do plugins=(${plugins[@]/$del/}) done echo "${plugins[@]} ${add[@]}" } # __docker_complete_plugins applies completion of plugins based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # The plugin type has to be specified with the next option `--type`. __docker_complete_plugins() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_plugins "$@")" -- "$current") ) } __docker_runtimes() { __docker_q info | sed -n 's/^Runtimes: \(.*\)/\1/p' } __docker_complete_runtimes() { COMPREPLY=( $(compgen -W "$(__docker_runtimes)" -- "$cur") ) } # __docker_nodes returns a list of all nodes. Additional options to # `docker node ls` may be specified in order to filter the list, e.g. # `__docker_nodes --filter role=manager` # By default, only node names are returned. # Set DOCKER_COMPLETION_SHOW_NODE_IDS=yes to also complete node IDs. # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. __docker_nodes() { local fields='$2' # default: node name only [ "${DOCKER_COMPLETION_SHOW_NODE_IDS}" = yes ] && fields='$1,$2' # ID and name if [ "$1" = "--id" ] ; then fields='$1' # IDs only shift elif [ "$1" = "--name" ] ; then fields='$2' # names only shift fi __docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}" } # __docker_complete_nodes applies completion of nodes based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # Additional filters may be appended, see `__docker_nodes`. __docker_complete_nodes() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_nodes "$@")" -- "$current") ) } __docker_complete_nodes_plus_self() { __docker_complete_nodes "$@" COMPREPLY+=( self ) } # __docker_services returns a list of all services. Additional options to # `docker service ls` may be specified in order to filter the list, e.g. # `__docker_services --filter name=xxx` # By default, only node names are returned. # Set DOCKER_COMPLETION_SHOW_SERVICE_IDS=yes to also complete IDs. # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. __docker_services() { local fields='$2' # default: service name only [ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name if [ "$1" = "--id" ] ; then fields='$1' # IDs only shift elif [ "$1" = "--name" ] ; then fields='$2' # names only shift fi __docker_q service ls "$@" | awk "NR>1 {print $fields}" } # __docker_complete_services applies completion of services based on the current # value of `$cur` or the value of the optional first option `--cur`, if given. # Additional filters may be appended, see `__docker_services`. __docker_complete_services() { local current="$cur" if [ "$1" = "--cur" ] ; then current="$2" shift 2 fi COMPREPLY=( $(compgen -W "$(__docker_services "$@")" -- "$current") ) } # __docker_append_to_completions appends the word passed as an argument to every # word in `$COMPREPLY`. # Normally you do this with `compgen -S` while generating the completions. # This function allows you to append a suffix later. It allows you to use # the __docker_complete_XXX functions in cases where you need a suffix. __docker_append_to_completions() { COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) } # __docker_pos_first_nonflag finds the position of the first word that is neither # option nor an option's argument. If there are options that require arguments, # you should pass a glob describing those options, e.g. "--option1|-o|--option2" # Use this function to restrict completions to exact positions after the argument list. __docker_pos_first_nonflag() { local argument_flags=$1 local counter=$((${subcommand_pos:-${command_pos}} + 1)) while [ $counter -le $cword ]; do if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then (( counter++ )) # eat "=" in case of --option=arg syntax [ "${words[$counter]}" = "=" ] && (( counter++ )) else case "${words[$counter]}" in -*) ;; *) break ;; esac fi # Bash splits words at "=", retaining "=" as a word, examples: # "--debug=false" => 3 words, "--log-opt syslog-facility=daemon" => 4 words while [ "${words[$counter + 1]}" = "=" ] ; do counter=$(( counter + 2)) done (( counter++ )) done echo $counter } # __docker_map_key_of_current_option returns `key` if we are currently completing the # value of a map option (`key=value`) which matches the extglob given as an argument. # This function is needed for key-specific completions. __docker_map_key_of_current_option() { local glob="$1" local key glob_pos if [ "$cur" = "=" ] ; then # key= case key="$prev" glob_pos=$((cword - 2)) elif [[ $cur == *=* ]] ; then # key=value case (OSX) key=${cur%=*} glob_pos=$((cword - 1)) elif [ "$prev" = "=" ] ; then key=${words[$cword - 2]} # key=value case glob_pos=$((cword - 3)) else return fi [ "${words[$glob_pos]}" = "=" ] && ((glob_pos--)) # --option=key=value syntax [[ ${words[$glob_pos]} == @($glob) ]] && echo "$key" } # __docker_value_of_option returns the value of the first option matching `option_glob`. # Valid values for `option_glob` are option names like `--log-level` and globs like # `--log-level|-l` # Only positions between the command and the current word are considered. __docker_value_of_option() { local option_extglob=$(__docker_to_extglob "$1") local counter=$((command_pos + 1)) while [ $counter -lt $cword ]; do case ${words[$counter]} in $option_extglob ) echo ${words[$counter + 1]} break ;; esac (( counter++ )) done } # __docker_to_alternatives transforms a multiline list of strings into a single line # string with the words separated by `|`. # This is used to prepare arguments to __docker_pos_first_nonflag(). __docker_to_alternatives() { local parts=( $1 ) local IFS='|' echo "${parts[*]}" } # __docker_to_extglob transforms a multiline list of options into an extglob pattern # suitable for use in case statements. __docker_to_extglob() { local extglob=$( __docker_to_alternatives "$1" ) echo "@($extglob)" } # __docker_subcommands processes subcommands # Locates the first occurrence of any of the subcommands contained in the # first argument. In case of a match, calls the corresponding completion # function and returns 0. # If no match is found, 1 is returned. The calling function can then # continue processing its completion. # # TODO if the preceding command has options that accept arguments and an # argument is equal ot one of the subcommands, this is falsely detected as # a match. __docker_subcommands() { local subcommands="$1" local counter=$(($command_pos + 1)) while [ $counter -lt $cword ]; do case "${words[$counter]}" in $(__docker_to_extglob "$subcommands") ) subcommand_pos=$counter local subcommand=${words[$counter]} local completions_func=_docker_${command}_${subcommand} declare -F $completions_func >/dev/null && $completions_func return 0 ;; esac (( counter++ )) done return 1 } # __docker_nospace suppresses trailing whitespace __docker_nospace() { # compopt is not available in ancient bash versions type compopt &>/dev/null && compopt -o nospace } __docker_complete_resolved_hostname() { command -v host >/dev/null 2>&1 || return COMPREPLY=( $(host 2>/dev/null "${cur%:}" | awk '/has address/ {print $4}') ) } __docker_local_interfaces() { command -v ip >/dev/null 2>&1 || return ip addr show scope global 2>/dev/null | sed -n 's| \+inet \([0-9.]\+\).* \([^ ]\+\)|\1 \2|p' } __docker_complete_local_interfaces() { local additional_interface if [ "$1" = "--add" ] ; then additional_interface="$2" fi COMPREPLY=( $( compgen -W "$(__docker_local_interfaces) $additional_interface" -- "$cur" ) ) } __docker_complete_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" ) ) } __docker_complete_detach-keys() { case "$prev" in --detach-keys) case "$cur" in *,) COMPREPLY=( $( compgen -W "${cur}ctrl-" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "ctrl-" -- "$cur" ) ) ;; esac __docker_nospace return ;; esac return 1 } __docker_complete_isolation() { COMPREPLY=( $( compgen -W "default hyperv process" -- "$cur" ) ) } __docker_complete_log_drivers() { COMPREPLY=( $( compgen -W " awslogs etwlogs fluentd gcplogs gelf journald json-file logentries none splunk syslog " -- "$cur" ) ) } __docker_complete_log_options() { # see docs/reference/logging/index.md local awslogs_options="awslogs-region awslogs-group awslogs-stream" local fluentd_options="env fluentd-address fluentd-async-connect fluentd-buffer-limit fluentd-retry-wait fluentd-max-retries labels tag" local gcplogs_options="env gcp-log-cmd gcp-project labels" local gelf_options="env gelf-address gelf-compression-level gelf-compression-type labels tag" local journald_options="env labels tag" local json_file_options="env labels max-file max-size" local logentries_options="logentries-token" local syslog_options="env labels syslog-address syslog-facility syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify tag" local splunk_options="env labels splunk-caname splunk-capath splunk-format splunk-gzip splunk-gzip-level splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url splunk-verify-connection tag" local all_options="$fluentd_options $gcplogs_options $gelf_options $journald_options $logentries_options $json_file_options $syslog_options $splunk_options" case $(__docker_value_of_option --log-driver) in '') COMPREPLY=( $( compgen -W "$all_options" -S = -- "$cur" ) ) ;; awslogs) COMPREPLY=( $( compgen -W "$awslogs_options" -S = -- "$cur" ) ) ;; fluentd) COMPREPLY=( $( compgen -W "$fluentd_options" -S = -- "$cur" ) ) ;; gcplogs) COMPREPLY=( $( compgen -W "$gcplogs_options" -S = -- "$cur" ) ) ;; gelf) COMPREPLY=( $( compgen -W "$gelf_options" -S = -- "$cur" ) ) ;; journald) COMPREPLY=( $( compgen -W "$journald_options" -S = -- "$cur" ) ) ;; json-file) COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) ) ;; logentries) COMPREPLY=( $( compgen -W "$logentries_options" -S = -- "$cur" ) ) ;; syslog) COMPREPLY=( $( compgen -W "$syslog_options" -S = -- "$cur" ) ) ;; splunk) COMPREPLY=( $( compgen -W "$splunk_options" -S = -- "$cur" ) ) ;; *) return ;; esac __docker_nospace } __docker_complete_log_driver_options() { local key=$(__docker_map_key_of_current_option '--log-opt') case "$key" in fluentd-async-connect) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; gelf-address) COMPREPLY=( $( compgen -W "udp" -S "://" -- "${cur##*=}" ) ) __docker_nospace return ;; gelf-compression-level) COMPREPLY=( $( compgen -W "1 2 3 4 5 6 7 8 9" -- "${cur##*=}" ) ) return ;; gelf-compression-type) COMPREPLY=( $( compgen -W "gzip none zlib" -- "${cur##*=}" ) ) return ;; syslog-address) COMPREPLY=( $( compgen -W "tcp:// tcp+tls:// udp:// unix://" -- "${cur##*=}" ) ) __docker_nospace __ltrim_colon_completions "${cur}" return ;; syslog-facility) COMPREPLY=( $( compgen -W " auth authpriv cron daemon ftp kern local0 local1 local2 local3 local4 local5 local6 local7 lpr mail news syslog user uucp " -- "${cur##*=}" ) ) return ;; syslog-format) COMPREPLY=( $( compgen -W "rfc3164 rfc5424 rfc5424micro" -- "${cur##*=}" ) ) return ;; syslog-tls-ca-cert|syslog-tls-cert|syslog-tls-key) _filedir return ;; syslog-tls-skip-verify) COMPREPLY=( $( compgen -W "true" -- "${cur##*=}" ) ) return ;; splunk-url) COMPREPLY=( $( compgen -W "http:// https://" -- "${cur##*=}" ) ) __docker_nospace __ltrim_colon_completions "${cur}" return ;; splunk-gzip|splunk-insecureskipverify|splunk-verify-connection) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; splunk-format) COMPREPLY=( $( compgen -W "inline json raw" -- "${cur##*=}" ) ) return ;; esac return 1 } __docker_complete_log_levels() { COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) ) } __docker_complete_restart() { case "$prev" in --restart) case "$cur" in on-failure:*) ;; *) COMPREPLY=( $( compgen -W "always no on-failure on-failure: unless-stopped" -- "$cur") ) ;; esac return ;; esac return 1 } # __docker_complete_signals returns a subset of the available signals that is most likely # relevant in the context of docker containers __docker_complete_signals() { local signals=( SIGCONT SIGHUP SIGINT SIGKILL SIGQUIT SIGSTOP SIGTERM SIGUSR1 SIGUSR2 ) COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) ) } __docker_complete_user_group() { if [[ $cur == *:* ]] ; then COMPREPLY=( $(compgen -g -- "${cur#*:}") ) else COMPREPLY=( $(compgen -u -S : -- "$cur") ) __docker_nospace fi } _docker_docker() { # global options that may appear after the docker command local boolean_options=" $global_boolean_options --help --version -v " case "$prev" in --config) _filedir -d return ;; --log-level|-l) __docker_complete_log_levels return ;; $(__docker_to_extglob "$global_options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $global_options_with_args" -- "$cur" ) ) ;; *) local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) if [ $cword -eq $counter ]; then COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) fi ;; esac } _docker_attach() { _docker_container_attach } _docker_build() { _docker_image_build } _docker_container() { local subcommands=" attach commit cp create diff exec export inspect kill logs ls pause port prune rename restart rm run start stats stop top unpause update wait " local aliases=" list ps " __docker_subcommands "$subcommands $aliases" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_container_attach() { __docker_complete_detach-keys && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--detach-keys --help --no-stdin --sig-proxy=false" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--detach-keys') if [ $cword -eq $counter ]; then __docker_complete_containers_running fi ;; esac } _docker_container_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=false -p=false" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--author|-a|--change|-c|--message|-m') if [ $cword -eq $counter ]; then __docker_complete_containers_all return fi (( counter++ )) if [ $cword -eq $counter ]; then __docker_complete_image_repos_and_tags return fi ;; esac } _docker_container_cp() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--follow-link -L --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then case "$cur" in *:) return ;; *) # combined container and filename completion _filedir local files=( ${COMPREPLY[@]} ) __docker_complete_containers_all COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) local containers=( ${COMPREPLY[@]} ) COMPREPLY=( $( compgen -W "${files[*]} ${containers[*]}" -- "$cur" ) ) if [[ "$COMPREPLY" == *: ]]; then __docker_nospace fi return ;; esac fi (( counter++ )) if [ $cword -eq $counter ]; then if [ -e "$prev" ]; then __docker_complete_containers_all COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) __docker_nospace else _filedir fi return fi ;; esac } _docker_container_create() { _docker_container_run } _docker_container_diff() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_all fi ;; esac } _docker_container_exec() { __docker_complete_detach-keys && return case "$prev" in --env|-e) # we do not append a "=" here because "-e VARNAME" is legal systax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; --user|-u) __docker_complete_user_group return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--detach -d --detach-keys --env -e --help --interactive -i --privileged -t --tty -u --user" -- "$cur" ) ) ;; *) __docker_complete_containers_running ;; esac } _docker_container_export() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_all fi ;; esac } _docker_container_inspect() { _docker_inspect --type container } _docker_container_kill() { case "$prev" in --signal|-s) __docker_complete_signals return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --signal -s" -- "$cur" ) ) ;; *) __docker_complete_containers_running ;; esac } _docker_container_logs() { case "$prev" in --since|--tail) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--details --follow -f --help --since --tail --timestamps -t" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--since|--tail') if [ $cword -eq $counter ]; then __docker_complete_containers_all fi ;; esac } _docker_container_list() { _docker_container_ls } _docker_container_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in ancestor) cur="${cur##*=}" __docker_complete_images return ;; before) __docker_complete_containers_all --cur "${cur##*=}" return ;; id) __docker_complete_containers_all --cur "${cur##*=}" --id return ;; is-task) COMPREPLY=( $( compgen -W "true false" -- "${cur##*=}" ) ) return ;; name) __docker_complete_containers_all --cur "${cur##*=}" --name return ;; network) __docker_complete_networks --cur "${cur##*=}" return ;; since) __docker_complete_containers_all --cur "${cur##*=}" return ;; status) COMPREPLY=( $( compgen -W "created dead exited paused restarting running removing" -- "${cur##*=}" ) ) return ;; volume) __docker_complete_volumes --cur "${cur##*=}" return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "ancestor before exited id label name network since status volume" -- "$cur" ) ) __docker_nospace return ;; --format|--last|-n) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--all -a --filter -f --format --help --last -n --latest -l --no-trunc --quiet -q --size -s" -- "$cur" ) ) ;; esac } _docker_container_pause() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_running fi ;; esac } _docker_container_port() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_all fi ;; esac } # TODO new command _docker_container_prune() { : } _docker_container_ps() { _docker_container_ls } _docker_container_rename() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_all fi ;; esac } _docker_container_restart() { case "$prev" in --time|-t) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) ;; *) __docker_complete_containers_all ;; esac } _docker_container_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) __docker_complete_containers_all return ;; esac done __docker_complete_containers_stopped ;; esac } _docker_container_run() { local options_with_args=" --add-host --attach -a --blkio-weight --blkio-weight-device --cap-add --cap-drop --cgroup-parent --cidfile --cpu-period --cpu-quota --cpu-rt-period --cpu-rt-runtime --cpuset-cpus --cpuset-mems --cpu-shares -c --device --device-read-bps --device-read-iops --device-write-bps --device-write-iops --dns --dns-opt --dns-search --entrypoint --env -e --env-file --expose --group-add --hostname -h --ip --ip6 --ipc --isolation --kernel-memory --label-file --label -l --link --link-local-ip --log-driver --log-opt --mac-address --memory -m --memory-swap --memory-swappiness --memory-reservation --name --network --network-alias --oom-score-adj --pid --pids-limit --publish -p --restart --runtime --security-opt --shm-size --stop-signal --stop-timeout --storage-opt --tmpfs --sysctl --ulimit --user -u --userns --uts --volume-driver --volumes-from --volume -v --workdir -w " local boolean_options=" --disable-content-trust=false --help --interactive -i --oom-kill-disable --privileged --publish-all -P --read-only --tty -t " if [ "$command" = "run" -o "$subcommand" = "run" ] ; then options_with_args="$options_with_args --detach-keys --health-cmd --health-interval --health-retries --health-timeout " boolean_options="$boolean_options --detach -d --no-healthcheck --rm --sig-proxy=false " __docker_complete_detach-keys && return fi local all_options="$options_with_args $boolean_options" __docker_complete_log_driver_options && return __docker_complete_restart && return local key=$(__docker_map_key_of_current_option '--security-opt') case "$key" in label) [[ $cur == *: ]] && return COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "${cur##*=}") ) if [ "${COMPREPLY[*]}" != "disable" ] ; then __docker_nospace fi return ;; seccomp) local cur=${cur##*=} _filedir COMPREPLY+=( $( compgen -W "unconfined" -- "$cur" ) ) return ;; esac case "$prev" in --add-host) case "$cur" in *:) __docker_complete_resolved_hostname return ;; esac ;; --attach|-a) COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) ) return ;; --cap-add|--cap-drop) __docker_complete_capabilities return ;; --cidfile|--env-file|--label-file) _filedir return ;; --device|--tmpfs|--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" ) ) __docker_nospace ;; /*) _filedir __docker_nospace ;; esac return ;; --env|-e) # we do not append a "=" here because "-e VARNAME" is legal systax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; --ipc) case "$cur" in *:*) cur="${cur#*:}" __docker_complete_containers_running ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) if [ "$COMPREPLY" = "container:" ]; then __docker_nospace fi ;; esac return ;; --isolation) __docker_complete_isolation return ;; --link) case "$cur" in *:*) ;; *) __docker_complete_containers_running COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) __docker_nospace ;; esac return ;; --log-driver) __docker_complete_log_drivers return ;; --log-opt) __docker_complete_log_options return ;; --network) case "$cur" in container:*) __docker_complete_containers_all --cur "${cur#*:}" ;; *) COMPREPLY=( $( compgen -W "$(__docker_plugins --type Network) $(__docker_networks) container:" -- "$cur") ) if [ "${COMPREPLY[*]}" = "container:" ] ; then __docker_nospace fi ;; esac return ;; --pid) case "$cur" in *:*) __docker_complete_containers_running --cur "${cur#*:}" ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) if [ "$COMPREPLY" = "container:" ]; then __docker_nospace fi ;; esac return ;; --runtime) __docker_complete_runtimes return ;; --security-opt) COMPREPLY=( $( compgen -W "apparmor= label= no-new-privileges seccomp=" -- "$cur") ) if [ "${COMPREPLY[*]}" != "no-new-privileges" ] ; then __docker_nospace fi return ;; --storage-opt) COMPREPLY=( $( compgen -W "size" -S = -- "$cur") ) __docker_nospace return ;; --user|-u) __docker_complete_user_group return ;; --userns) COMPREPLY=( $( compgen -W "host" -- "$cur" ) ) return ;; --volume-driver) __docker_complete_plugins --type Volume return ;; --volumes-from) __docker_complete_containers_all return ;; $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __docker_complete_images fi ;; esac } _docker_container_start() { __docker_complete_detach-keys && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--attach -a --detach-keys --help --interactive -i" -- "$cur" ) ) ;; *) __docker_complete_containers_stopped ;; esac } _docker_container_stats() { case "$prev" in --format) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--all -a --format --help --no-stream" -- "$cur" ) ) ;; *) __docker_complete_containers_running ;; esac } _docker_container_stop() { case "$prev" in --time|-t) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) ;; *) __docker_complete_containers_running ;; esac } _docker_container_top() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_running fi ;; esac } _docker_container_unpause() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_containers_unpauseable fi ;; esac } _docker_container_update() { local options_with_args=" --blkio-weight --cpu-period --cpu-quota --cpu-rt-period --cpu-rt-runtime --cpuset-cpus --cpuset-mems --cpu-shares -c --kernel-memory --memory -m --memory-reservation --memory-swap --restart " local boolean_options=" --help " local all_options="$options_with_args $boolean_options" __docker_complete_restart && return case "$prev" in $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) __docker_complete_containers_all ;; esac } _docker_container_wait() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_containers_all ;; esac } _docker_commit() { _docker_container_commit } _docker_cp() { _docker_container_cp } _docker_create() { _docker_container_run } _docker_daemon() { local boolean_options=" $global_boolean_options --disable-legacy-registry --experimental --help --icc=false --ip-forward=false --ip-masq=false --iptables=false --ipv6 --live-restore --raw-logs --selinux-enabled --userland-proxy=false " local options_with_args=" $global_options_with_args --add-runtime --api-cors-header --authorization-plugin --bip --bridge -b --cgroup-parent --cluster-advertise --cluster-store --cluster-store-opt --config-file --containerd --default-gateway --default-gateway-v6 --default-ulimit --dns --dns-search --dns-opt --exec-opt --exec-root --fixed-cidr --fixed-cidr-v6 --graph -g --group -G --init-path --insecure-registry --ip --label --log-driver --log-opt --max-concurrent-downloads --max-concurrent-uploads --mtu --oom-score-adjust --pidfile -p --registry-mirror --shutdown-timeout --storage-driver -s --storage-opt --userns-remap " __docker_complete_log_driver_options && return key=$(__docker_map_key_of_current_option '--cluster-store-opt') case "$key" in kv.*file) cur=${cur##*=} _filedir return ;; esac local key=$(__docker_map_key_of_current_option '--storage-opt') case "$key" in dm.blkdiscard|dm.override_udev_sync_check|dm.use_deferred_removal|dm.use_deferred_deletion) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; dm.fs) COMPREPLY=( $( compgen -W "ext4 xfs" -- "${cur##*=}" ) ) return ;; dm.thinpooldev) cur=${cur##*=} _filedir return ;; esac case "$prev" in --authorization-plugin) __docker_complete_plugins --type Authorization return ;; --cluster-store) COMPREPLY=( $( compgen -W "consul etcd zk" -S "://" -- "$cur" ) ) __docker_nospace return ;; --cluster-store-opt) COMPREPLY=( $( compgen -W "discovery.heartbeat discovery.ttl kv.cacertfile kv.certfile kv.keyfile kv.path" -S = -- "$cur" ) ) __docker_nospace return ;; --config-file|--containerd|--init-path|--pidfile|-p|--tlscacert|--tlscert|--tlskey) _filedir return ;; --exec-root|--graph|-g) _filedir -d return ;; --log-driver) __docker_complete_log_drivers return ;; --storage-driver|-s) COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) ) return ;; --storage-opt) local btrfs_options="btrfs.min_space" local devicemapper_options=" dm.basesize dm.blkdiscard dm.blocksize dm.fs dm.loopdatasize dm.loopmetadatasize dm.min_free_space dm.mkfsarg dm.mountopt dm.override_udev_sync_check dm.thinpooldev dm.use_deferred_deletion dm.use_deferred_removal " local zfs_options="zfs.fsname" case $(__docker_value_of_option '--storage-driver|-s') in '') COMPREPLY=( $( compgen -W "$btrfs_options $devicemapper_options $zfs_options" -S = -- "$cur" ) ) ;; btrfs) COMPREPLY=( $( compgen -W "$btrfs_options" -S = -- "$cur" ) ) ;; devicemapper) COMPREPLY=( $( compgen -W "$devicemapper_options" -S = -- "$cur" ) ) ;; zfs) COMPREPLY=( $( compgen -W "$zfs_options" -S = -- "$cur" ) ) ;; *) return ;; esac __docker_nospace return ;; --log-level|-l) __docker_complete_log_levels return ;; --log-opt) __docker_complete_log_options return ;; --userns-remap) __docker_complete_user_group return ;; $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) ;; esac } _docker_diff() { _docker_container_diff } _docker_events() { _docker_system_events } _docker_exec() { _docker_container_exec } _docker_export() { _docker_container_export } _docker_help() { local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) fi } _docker_history() { _docker_image_history } _docker_image() { local subcommands=" build history import inspect load ls prune pull push rm save tag " local aliases=" images list remove rmi " __docker_subcommands "$subcommands $aliases" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_image_build() { local options_with_args=" --build-arg --cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --isolation --label --memory -m --memory-swap --shm-size --tag -t --ulimit " local boolean_options=" --compress --disable-content-trust=false --force-rm --help --no-cache --pull --quiet -q --rm " local all_options="$options_with_args $boolean_options" case "$prev" in --build-arg) COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; --file|-f) _filedir return ;; --isolation) __docker_complete_isolation return ;; --tag|-t) __docker_complete_image_repos_and_tags return ;; $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then _filedir -d fi ;; esac } _docker_image_history() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_images fi ;; esac } _docker_image_images() { _docker_image_ls } _docker_image_import() { case "$prev" in --change|-c|--message|-m) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m') if [ $cword -eq $counter ]; then return fi (( counter++ )) if [ $cword -eq $counter ]; then __docker_complete_image_repos_and_tags return fi ;; esac } _docker_image_inspect() { _docker_inspect --type image } _docker_image_load() { case "$prev" in --input|-i) _filedir return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --input -i --quiet -q" -- "$cur" ) ) ;; esac } _docker_image_list() { _docker_image_ls } _docker_image_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in before) cur="${cur##*=}" __docker_complete_images return ;; dangling) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; label) return ;; since) cur="${cur##*=}" __docker_complete_images return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "before dangling label since" -- "$cur" ) ) __docker_nospace return ;; --format) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--all -a --digests --filter -f --format --help --no-trunc --quiet -q" -- "$cur" ) ) ;; =) return ;; *) __docker_complete_image_repos ;; esac } # TODO new command _docker_image_prune() { : } _docker_image_pull() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--all-tags -a --disable-content-trust=false --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then for arg in "${COMP_WORDS[@]}"; do case "$arg" in --all-tags|-a) __docker_complete_image_repos return ;; esac done __docker_complete_image_repos_and_tags fi ;; esac } _docker_image_push() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--disable-content-trust=false --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_image_repos_and_tags fi ;; esac } _docker_image_remove() { _docker_image_rm } _docker_image_rm() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) ) ;; *) __docker_complete_images ;; esac } _docker_image_rmi() { _docker_image_rm } _docker_image_save() { case "$prev" in --output|-o) _filedir return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) ) ;; *) __docker_complete_images ;; esac } _docker_image_tag() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_image_repos_and_tags return fi (( counter++ )) if [ $cword -eq $counter ]; then __docker_complete_image_repos_and_tags return fi ;; esac } _docker_images() { _docker_image_ls } _docker_import() { _docker_image_import } _docker_info() { _docker_system_info } _docker_inspect() { local type if [ "$1" = "--type" ] ; then type="$2" else type=$(__docker_value_of_option --type) fi case "$prev" in --format|-f) return ;; --type) if [ -z "$type" ] ; then COMPREPLY=( $( compgen -W "image container" -- "$cur" ) ) fi return ;; esac case "$cur" in -*) local options="--format -f --help --size -s" if [ -z "$type" ] ; then options+=" --type" fi COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) case "$type" in '') __docker_complete_containers_and_images ;; container) __docker_complete_containers_all ;; image) __docker_complete_images ;; esac esac } _docker_kill() { _docker_container_kill } _docker_load() { _docker_image_load } _docker_login() { case "$prev" in --password|-p|--username|-u) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --password -p --username -u" -- "$cur" ) ) ;; esac } _docker_logout() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; esac } _docker_logs() { _docker_container_logs } _docker_network_connect() { local options_with_args=" --alias --ip --ip6 --link --link-local-ip " local boolean_options=" --help " case "$prev" in --link) case "$cur" in *:*) ;; *) __docker_complete_containers_running COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) __docker_nospace ;; esac return ;; $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) ;; *) local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) if [ $cword -eq $counter ]; then __docker_complete_networks elif [ $cword -eq $(($counter + 1)) ]; then __docker_complete_containers_all fi ;; esac } _docker_network_create() { case "$prev" in --aux-address|--gateway|--internal|--ip-range|--ipam-opt|--ipv6|--opt|-o|--subnet) return ;; --ipam-driver) COMPREPLY=( $( compgen -W "default" -- "$cur" ) ) return ;; --driver|-d) # remove drivers that allow one instance only, add drivers missing in `docker info` __docker_complete_plugins --type Network --remove host --remove null --add macvlan return ;; --label) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--aux-address --driver -d --gateway --help --internal --ip-range --ipam-driver --ipam-opt --ipv6 --label --opt -o --subnet" -- "$cur" ) ) ;; esac } _docker_network_disconnect() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) if [ $cword -eq $counter ]; then __docker_complete_networks elif [ $cword -eq $(($counter + 1)) ]; then __docker_complete_containers_in_network "$prev" fi ;; esac } _docker_network_inspect() { case "$prev" in --format|-f) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) ;; *) __docker_complete_networks esac } _docker_network_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in driver) __docker_complete_plugins --cur "${cur##*=}" --type Network --add macvlan return ;; id) __docker_complete_networks --cur "${cur##*=}" --id return ;; name) __docker_complete_networks --cur "${cur##*=}" --name return ;; type) COMPREPLY=( $( compgen -W "builtin custom" -- "${cur##*=}" ) ) return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "driver id label name type" -- "$cur" ) ) __docker_nospace return ;; --format) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter -f --format --help --no-trunc --quiet -q" -- "$cur" ) ) ;; esac } _docker_network_rm() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_networks --filter type=custom esac } _docker_network() { local subcommands=" connect create disconnect inspect ls rm " __docker_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_service() { local subcommands=" create inspect ls list rm remove scale ps update " __docker_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_service_create() { _docker_service_update } _docker_service_inspect() { case "$prev" in --format|-f) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--format -f --help --pretty" -- "$cur" ) ) ;; *) __docker_complete_services esac } _docker_service_list() { _docker_service_ls } _docker_service_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in id) __docker_complete_services --cur "${cur##*=}" --id return ;; name) __docker_complete_services --cur "${cur##*=}" --name return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) __docker_nospace return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) ;; esac } _docker_service_remove() { _docker_service_rm } _docker_service_rm() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_services esac } _docker_service_scale() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_services __docker_append_to_completions "=" __docker_nospace ;; esac } _docker_service_ps() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in desired-state) COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) return ;; name) __docker_complete_services --cur "${cur##*=}" --name return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -W "desired-state id name" -S = -- "$cur" ) ) __docker_nospace return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--filter|-f') if [ $cword -eq $counter ]; then __docker_complete_services fi ;; esac } _docker_service_update() { local $subcommand="${words[$subcommand_pos]}" local options_with_args=" --constraint --endpoint-mode --env -e --force --group-add --label -l --limit-cpu --limit-memory --log-driver --log-opt --mount --name --network --publish -p --replicas --reserve-cpu --reserve-memory --restart-condition --restart-delay --restart-max-attempts --restart-window --rollback --stop-grace-period --update-delay --update-failure-action --update-max-failure-ratio --update-monitor --update-parallelism --user -u --workdir -w " local boolean_options=" --help --with-registry-auth " __docker_complete_log_driver_options && return if [ "$subcommand" = "create" ] ; then options_with_args="$options_with_args --container-label --mode " case "$prev" in --mode) COMPREPLY=( $( compgen -W "global replicated" -- "$cur" ) ) return ;; esac fi if [ "$subcommand" = "update" ] ; then options_with_args="$options_with_args --arg --container-label-add --container-label-rm --group-rm --image " case "$prev" in --group-rm) COMPREPLY=( $(compgen -g -- "$cur") ) return ;; --image) __docker_complete_image_repos_and_tags return ;; esac fi case "$prev" in --endpoint-mode) COMPREPLY=( $( compgen -W "dnsrr vip" -- "$cur" ) ) return ;; --env|-e) # we do not append a "=" here because "-e VARNAME" is legal systax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; --group-add) COMPREPLY=( $(compgen -g -- "$cur") ) return ;; --log-driver) __docker_complete_log_drivers return ;; --log-opt) __docker_complete_log_options return ;; --network) __docker_complete_networks return ;; --restart-condition) COMPREPLY=( $( compgen -W "any none on-failure" -- "$cur" ) ) return ;; --user|-u) __docker_complete_user_group return ;; $(__docker_to_extglob "$options_with_args") ) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) ;; *) if [ "$subcommand" = "update" ] ; then __docker_complete_services fi esac } _docker_swarm() { local subcommands=" init join join-token leave update " __docker_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_swarm_init() { case "$prev" in --advertise-addr) if [[ $cur == *: ]] ; then COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) else __docker_complete_local_interfaces __docker_nospace fi return ;; --listen-addr) if [[ $cur == *: ]] ; then COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) else __docker_complete_local_interfaces --add 0.0.0.0 __docker_nospace fi return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--advertise-addr --force-new-cluster --help --listen-addr" -- "$cur" ) ) ;; esac } _docker_swarm_join() { case "$prev" in --advertise-addr) if [[ $cur == *: ]] ; then COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) else __docker_complete_local_interfaces __docker_nospace fi return ;; --listen-addr) if [[ $cur == *: ]] ; then COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) else __docker_complete_local_interfaces --add 0.0.0.0 __docker_nospace fi return ;; --token) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--advertise-addr --help --listen-addr --token" -- "$cur" ) ) ;; *:) COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) ;; esac } _docker_swarm_join-token() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help --quiet -q --rotate" -- "$cur" ) ) ;; *) local counter=$( __docker_pos_first_nonflag ) if [ $cword -eq $counter ]; then COMPREPLY=( $( compgen -W "manager worker" -- "$cur" ) ) fi ;; esac } _docker_swarm_leave() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--force --help" -- "$cur" ) ) ;; esac } _docker_swarm_update() { case "$prev" in --cert-expiry|--dispatcher-heartbeat|--task-history-limit) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--cert-expiry --dispatcher-heartbeat --help --task-history-limit" -- "$cur" ) ) ;; esac } _docker_node() { local subcommands=" demote inspect ls list promote rm remove ps update " __docker_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_node_demote() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_nodes --filter role=manager esac } _docker_node_inspect() { case "$prev" in --format|-f) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--format -f --help --pretty" -- "$cur" ) ) ;; *) __docker_complete_nodes_plus_self esac } _docker_node_list() { _docker_node_ls } _docker_node_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in id) __docker_complete_nodes --cur "${cur##*=}" --id return ;; name) __docker_complete_nodes --cur "${cur##*=}" --name return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) __docker_nospace return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) ;; esac } _docker_node_promote() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) __docker_complete_nodes --filter role=worker esac } _docker_node_remove() { _docker_node_rm } _docker_node_rm() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--force --help" -- "$cur" ) ) ;; *) __docker_complete_nodes esac } _docker_node_ps() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in desired-state) COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) return ;; name) __docker_complete_services --cur "${cur##*=}" --name return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -W "desired-state id label name" -S = -- "$cur" ) ) __docker_nospace return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc" -- "$cur" ) ) ;; *) __docker_complete_nodes_plus_self ;; esac } _docker_node_update() { case "$prev" in --availability) COMPREPLY=( $( compgen -W "active drain pause" -- "$cur" ) ) return ;; --role) COMPREPLY=( $( compgen -W "manager worker" -- "$cur" ) ) return ;; --label-add|--label-rm) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--availability --help --label-add --label-rm --role" -- "$cur" ) ) ;; *) __docker_complete_nodes esac } _docker_pause() { _docker_container_pause } _docker_port() { _docker_container_port } _docker_ps() { _docker_container_ls } _docker_pull() { _docker_image_pull } _docker_push() { _docker_image_push } _docker_rename() { _docker_container_rename } _docker_restart() { _docker_container_restart } _docker_rm() { _docker_container_rm } _docker_rmi() { _docker_image_rm } _docker_run() { _docker_container_run } _docker_save() { _docker_image_save } _docker_search() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in is-automated) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; is-official) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "is-automated is-official stars" -- "$cur" ) ) __docker_nospace return ;; --limit) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter --help --limit --no-trunc" -- "$cur" ) ) ;; esac } _docker_start() { _docker_container_start } _docker_stats() { _docker_container_stats } _docker_stop() { _docker_container_stop } _docker_system() { local subcommands=" df events info prune " __docker_subcommands "$subcommands $aliases" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } # TODO new command _docker_system_df() { : } _docker_system_events() { local key=$(__docker_map_key_of_current_option '-f|--filter') case "$key" in container) __docker_complete_containers_all --cur "${cur##*=}" return ;; daemon) local name=$(__docker_q info | sed -n 's/^\(ID\|Name\): //p') COMPREPLY=( $( compgen -W "$name" -- "${cur##*=}" ) ) return ;; event) COMPREPLY=( $( compgen -W " attach commit connect copy create delete destroy detach die disconnect exec_create exec_detach exec_start export health_status import kill load mount oom pause pull push reload rename resize restart save start stop tag top unmount unpause untag update " -- "${cur##*=}" ) ) return ;; image) cur="${cur##*=}" __docker_complete_images return ;; network) __docker_complete_networks --cur "${cur##*=}" return ;; type) COMPREPLY=( $( compgen -W "container daemon image network volume" -- "${cur##*=}" ) ) return ;; volume) __docker_complete_volumes --cur "${cur##*=}" return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "container daemon event image label network type volume" -- "$cur" ) ) __docker_nospace return ;; --since|--until) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter -f --help --since --until --format" -- "$cur" ) ) ;; esac } _docker_system_info() { case "$prev" in --format|-f) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) ;; esac } # TODO new command _docker_system_prune() { : } _docker_tag() { _docker_image_tag } _docker_unpause() { _docker_container_unpause } _docker_update() { _docker_container_update } _docker_top() { _docker_container_top } _docker_version() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; esac } _docker_volume_create() { case "$prev" in --driver|-d) __docker_complete_plugins --type Volume return ;; --label|--opt|-o) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--driver -d --help --label --opt -o" -- "$cur" ) ) ;; esac } _docker_volume_inspect() { case "$prev" in --format|-f) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) ;; *) __docker_complete_volumes ;; esac } _docker_volume_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in dangling) COMPREPLY=( $( compgen -W "true false" -- "${cur##*=}" ) ) return ;; driver) __docker_complete_plugins --cur "${cur##*=}" --type Volume return ;; name) __docker_complete_volumes --cur "${cur##*=}" return ;; esac case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "dangling driver label name" -- "$cur" ) ) __docker_nospace return ;; --format) return ;; esac case "$cur" in -*) COMPREPLY=( $( compgen -W "--filter -f --format --help --quiet -q" -- "$cur" ) ) ;; esac } _docker_volume_rm() { case "$cur" in -*) COMPREPLY=( $( compgen -W "--force -f --help" -- "$cur" ) ) ;; *) __docker_complete_volumes ;; esac } _docker_volume() { local subcommands=" create inspect ls rm " __docker_subcommands "$subcommands" && return case "$cur" in -*) COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) ;; esac } _docker_wait() { _docker_container_wait } _docker() { local previous_extglob_setting=$(shopt -p extglob) shopt -s extglob local commands=( attach build commit container cp create daemon diff events exec export history image images import info inspect kill load login logout logs network node pause port ps pull push rename restart rm rmi run save search service start stats stop swarm system tag top unpause update version volume wait ) # These options are valid as global options for all client commands # and valid as command options for `docker daemon` local global_boolean_options=" --debug -D --tls --tlsverify " local global_options_with_args=" --config --host -H --log-level -l --tlscacert --tlscert --tlskey " local host config COMPREPLY=() local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword local command='docker' command_pos=0 subcommand_pos 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]}" ;; # save config so that completion can use custom configuration directories --config) (( counter++ )) config="${words[$counter]}" ;; $(__docker_to_extglob "$global_options_with_args") ) (( counter++ )) ;; -*) ;; =) (( counter++ )) ;; *) command="${words[$counter]}" command_pos=$counter break ;; esac (( counter++ )) done local binary="${words[0]}" if [[ $binary == ?(*/)dockerd ]] ; then # for the dockerd binary, we reuse completion of `docker daemon`. # dockerd does not have subcommands and global options. command=daemon command_pos=0 fi local completions_func=_docker_${command} declare -F $completions_func >/dev/null && $completions_func eval "$previous_extglob_setting" return 0 } eval "$__docker_previous_extglob_setting" unset __docker_previous_extglob_setting complete -F _docker docker dockerd