From 7156011f83ea595f9406bb606ff9f9be68f1b4ed Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:29 +0700 Subject: [PATCH 1/3] Update docker completion --- completion/available/docker.completion.bash | 994 +++++++++++++++----- 1 file changed, 766 insertions(+), 228 deletions(-) diff --git a/completion/available/docker.completion.bash b/completion/available/docker.completion.bash index 3a4fbe3d..2b3e805c 100644 --- a/completion/available/docker.completion.bash +++ b/completion/available/docker.completion.bash @@ -1,12 +1,14 @@ #!/usr/bin/env bash -# shellcheck disable=SC2016,SC2119,SC2155 +# shellcheck disable=SC2016,SC2119,SC2155,SC2206,SC2207 # # Shellcheck ignore list: # - SC2016: Expressions don't expand in single quotes, use double quotes for that. # - SC2119: Use foo "$@" if function's $1 should mean script's $1. # - SC2155: Declare and assign separately to avoid masking return values. -# -# You can find more details for each warning at the following page: +# - SC2206: Quote to prevent word splitting, or split robustly with mapfile or read -a. +# - SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting). +# +# You can find more details for each warning at the following page: # https://github.com/koalaman/shellcheck/wiki/ # # bash completion file for core docker commands @@ -68,7 +70,7 @@ __docker_previous_extglob_setting=$(shopt -p extglob) shopt -s extglob __docker_q() { - docker ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@" + docker ${host:+--host "$host"} ${config:+--config "$config"} ${context:+--context "$context"} 2>/dev/null "$@" } # __docker_configs returns a list of configs. Additional options to @@ -156,6 +158,11 @@ __docker_complete_containers_running() { __docker_complete_containers "$@" --filter status=running } +# shellcheck disable=SC2120 +__docker_complete_containers_stoppable() { + __docker_complete_containers "$@" --filter status=running --filter status=paused +} + # shellcheck disable=SC2120 __docker_complete_containers_stopped() { __docker_complete_containers "$@" --filter status=exited @@ -178,52 +185,103 @@ __docker_complete_container_ids() { COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) } +# __docker_contexts returns a list of contexts without the special "default" context. +# Completions may be added with `--add`, e.g. `--add default`. +__docker_contexts() { + local add=() + while true ; do + case "$1" in + --add) + add+=("$2") + shift 2 + ;; + *) + break + ;; + esac + done + __docker_q context ls -q + echo "${add[@]}" +} + +__docker_complete_contexts() { + local contexts=( $(__docker_contexts "$@") ) + COMPREPLY=( $(compgen -W "${contexts[*]}" -- "$cur") ) +} + + +# __docker_images returns a list of images. For each image, up to three representations +# can be generated: the repository (e.g. busybox), repository:tag (e.g. busybox:latest) +# and the ID (e.g. sha256:ee22cbbd4ea3dff63c86ba60c7691287c321e93adfc1009604eb1dde7ec88645). +# +# The optional arguments `--repo`, `--tag` and `--id` select the representations that +# may be returned. Whether or not a particular representation is actually returned +# depends on the user's customization through several environment variables: +# - image IDs are only shown if DOCKER_COMPLETION_SHOW_IMAGE_IDS=all|non-intermediate. +# - tags can be excluded by setting DOCKER_COMPLETION_SHOW_TAGS=no. +# - repositories are always shown. +# +# In cases where an exact image specification is needed, `--force-tag` can be used. +# It ignores DOCKER_COMPLETION_SHOW_TAGS and only lists valid repository:tag combinations, +# avoiding repository names that would default to a potentially missing default tag. +# +# Additional arguments to `docker image ls` may be specified in order to filter the list, +# e.g. `__docker_images --filter dangling=true`. +# __docker_images() { - local images_args="" + local repo_format='{{.Repository}}' + local tag_format='{{.Repository}}:{{.Tag}}' + local id_format='{{.ID}}' + local all + local format - 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' + if [ "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" = "all" ] ; then + all='--all' 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 + while true ; do + case "$1" in + --repo) + format+="$repo_format\n" + shift + ;; + --tag) + if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then + format+="$tag_format\n" + fi + shift + ;; + --id) + if [[ $DOCKER_COMPLETION_SHOW_IMAGE_IDS =~ ^(all|non-intermediate)$ ]] ; then + format+="$id_format\n" + fi + shift + ;; + --force-tag) + # like `--tag` but ignores environment setting + format+="$tag_format\n" + shift + ;; + *) + break + ;; + esac + done - __docker_q images $images_args | awk "$awk_script" | grep -v '$' + __docker_q image ls --no-trunc --format "${format%\\n}" $all "$@" | grep -v '$' } +# __docker_complete_images applies completion of images based on the current value of `$cur` or +# the value of the optional first option `--cur`, if given. +# See __docker_images for customization of the returned items. __docker_complete_images() { - COMPREPLY=( $(compgen -W "$(__docker_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" + local current="$cur" + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_images "$@")" -- "$current") ) + __ltrim_colon_completions "$current" } # __docker_networks returns a list of all networks. Additional options to @@ -262,10 +320,9 @@ __docker_complete_networks() { COMPREPLY=( $(compgen -W "$(__docker_networks "$@")" -- "$current") ) } -# shellcheck disable=SC2128,SC2178 __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") ) + 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 @@ -321,8 +378,7 @@ __docker_plugins_bundled() { for del in "${remove[@]}" ; do plugins=(${plugins[@]/$del/}) done - # shellcheck disable=SC2145 - echo "${plugins[@]} ${add[@]}" + echo "${plugins[@]}" "${add[@]}" } # __docker_complete_plugins_bundled applies completion of plugins based on the current @@ -539,23 +595,64 @@ __docker_append_to_completions() { COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) } -# __docker_daemon_is_experimental tests whether the currently configured Docker -# daemon runs in experimental mode. If so, the function exits with 0 (true). -# Otherwise, or if the result cannot be determined, the exit value is 1 (false). -__docker_daemon_is_experimental() { - [ "$(__docker_q version -f '{{.Server.Experimental}}')" = "true" ] +# __docker_fetch_info fetches information about the configured Docker server and updates +# several variables with the results. +# The result is cached for the duration of one invocation of bash completion. +__docker_fetch_info() { + if [ -z "$info_fetched" ] ; then + read -r client_experimental server_experimental server_os <<< "$(__docker_q version -f '{{.Client.Experimental}} {{.Server.Experimental}} {{.Server.Os}}')" + info_fetched=true + fi } -# __docker_daemon_os_is tests whether the currently configured Docker daemon runs +# __docker_client_is_experimental tests whether the Docker cli is configured to support +# experimental features. If so, the function exits with 0 (true). +# Otherwise, or if the result cannot be determined, the exit value is 1 (false). +__docker_client_is_experimental() { + __docker_fetch_info + [ "$client_experimental" = "true" ] +} + +# __docker_server_is_experimental tests whether the currently configured Docker +# server runs in experimental mode. If so, the function exits with 0 (true). +# Otherwise, or if the result cannot be determined, the exit value is 1 (false). +__docker_server_is_experimental() { + __docker_fetch_info + [ "$server_experimental" = "true" ] +} + +# __docker_server_os_is tests whether the currently configured Docker server runs # on the operating system passed in as the first argument. -# It does so by querying the daemon for its OS. The result is cached for the duration -# of one invocation of bash completion so that this function can be used to test for -# several different operating systems without additional costs. # Known operating systems: linux, windows. -__docker_daemon_os_is() { +__docker_server_os_is() { local expected_os="$1" - local actual_os=${daemon_os=$(__docker_q version -f '{{.Server.Os}}')} - [ "$actual_os" = "$expected_os" ] + __docker_fetch_info + [ "$server_os" = "$expected_os" ] +} + +# __docker_stack_orchestrator_is tests whether the client is configured to use +# the orchestrator that is passed in as the first argument. +__docker_stack_orchestrator_is() { + case "$1" in + kubernetes) + if [ -z "$stack_orchestrator_is_kubernetes" ] ; then + __docker_q stack ls --help | grep -qe --namespace + stack_orchestrator_is_kubernetes=$? + fi + return $stack_orchestrator_is_kubernetes + ;; + swarm) + if [ -z "$stack_orchestrator_is_swarm" ] ; then + __docker_q stack deploy --help | grep -qe "with-registry-auth" + stack_orchestrator_is_swarm=$? + fi + return $stack_orchestrator_is_swarm + ;; + *) + return 1 + ;; + + esac } # __docker_pos_first_nonflag finds the position of the first word that is neither @@ -816,6 +913,7 @@ __docker_complete_log_drivers() { gelf journald json-file + local logentries none splunk @@ -839,7 +937,8 @@ __docker_complete_log_options() { local gcplogs_options="$common_options1 $common_options2 gcp-log-cmd gcp-meta-id gcp-meta-name gcp-meta-zone gcp-project" local gelf_options="$common_options1 $common_options2 gelf-address gelf-compression-level gelf-compression-type gelf-tcp-max-reconnect gelf-tcp-reconnect-delay tag" local journald_options="$common_options1 $common_options2 tag" - local json_file_options="$common_options1 $common_options2 max-file max-size" + local json_file_options="$common_options1 $common_options2 compress max-file max-size" + local local_options="$common_options1 compress max-file max-size" local logentries_options="$common_options1 $common_options2 line-only logentries-token tag" local splunk_options="$common_options1 $common_options2 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 syslog_options="$common_options1 $common_options2 syslog-address syslog-facility syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify tag" @@ -868,6 +967,9 @@ __docker_complete_log_options() { json-file) COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) ) ;; + local) + COMPREPLY=( $( compgen -W "$local_options" -S = -- "$cur" ) ) + ;; logentries) COMPREPLY=( $( compgen -W "$logentries_options" -S = -- "$cur" ) ) ;; @@ -897,7 +999,7 @@ __docker_complete_log_driver_options() { __docker_nospace return ;; - fluentd-async-connect) + compress|fluentd-async-connect) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; @@ -1024,6 +1126,23 @@ __docker_complete_signals() { COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo "$cur" | tr '[:lower:]' '[:upper:]')" ) ) } +__docker_complete_stack_orchestrator_options() { + case "$prev" in + --kubeconfig) + _filedir + return 0 + ;; + --namespace) + return 0 + ;; + --orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur") ) + return 0 + ;; + esac + return 1 +} + __docker_complete_user_group() { if [[ $cur == *:* ]] ; then COMPREPLY=( $(compgen -g -- "${cur#*:}") ) @@ -1046,6 +1165,10 @@ _docker_docker() { _filedir -d return ;; + --context|-c) + __docker_complete_contexts + return + ;; --log-level|-l) __docker_complete_log_levels return @@ -1062,7 +1185,8 @@ _docker_docker() { *) local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) if [ "$cword" -eq "$counter" ]; then - __docker_daemon_is_experimental && commands+=(${experimental_commands[*]}) + __docker_client_is_experimental && commands+=(${experimental_client_commands[*]}) + __docker_server_is_experimental && commands+=(${experimental_server_commands[*]}) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) fi ;; @@ -1078,6 +1202,41 @@ _docker_build() { } +_docker_builder() { + local subcommands=" + prune + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_builder_prune() { + case "$prev" in + --filter) + COMPREPLY=( $( compgen -S = -W "description id inuse parent private shared type until unused-for" -- "$cur" ) ) + __docker_nospace + return + ;; + --keep-storage) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter --force -f --help --keep-storage" -- "$cur" ) ) + ;; + esac +} + _docker_checkpoint() { local subcommands=" create @@ -1194,14 +1353,18 @@ _docker_config_create() { --label|-l) return ;; + --template-driver) + COMPREPLY=( $( compgen -W "golang" -- "$cur" ) ) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --label -l" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --label -l --template-driver" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--label|-l') + local counter=$(__docker_pos_first_nonflag '--label|-l|--template-driver') if [ "$cword" -eq "$((counter + 1))" ]; then _filedir fi @@ -1354,11 +1517,8 @@ _docker_container_commit() { if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -1368,7 +1528,7 @@ _docker_container_commit() { _docker_container_cp() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--follow-link -L --help" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--archive -a --follow-link -L --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) @@ -1387,8 +1547,7 @@ _docker_container_cp() { local containers=( ${COMPREPLY[@]} ) COMPREPLY=( $( compgen -W "${files[*]} ${containers[*]}" -- "$cur" ) ) - # shellcheck disable=SC2128 - if [[ "$COMPREPLY" == *: ]]; then + if [[ "${COMPREPLY[*]}" = *: ]]; then __docker_nospace fi return @@ -1529,8 +1688,7 @@ _docker_container_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in ancestor) - cur="${cur##*=}" - __docker_complete_images + __docker_complete_images --cur "${cur##*=}" --repo --tag --id return ;; before) @@ -1720,6 +1878,7 @@ _docker_container_run_and_create() { --dns --dns-option --dns-search + --domainname --entrypoint --env -e --env-file @@ -1772,14 +1931,14 @@ _docker_container_run_and_create() { --volume -v --workdir -w " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --cpu-count --cpu-percent --io-maxbandwidth --io-maxiops --isolation " - __docker_daemon_is_experimental && options_with_args+=" + __docker_server_is_experimental && options_with_args+=" --platform " @@ -1887,8 +2046,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'none host private shareable container:' -- "$cur" ) ) - # shellcheck disable=SC2128 - if [ "$COMPREPLY" = "container:" ]; then + if [ "${COMPREPLY[*]}" = "container:" ]; then __docker_nospace fi ;; @@ -1896,7 +2054,7 @@ _docker_container_run_and_create() { return ;; --isolation) - if __docker_daemon_os_is windows ; then + if __docker_server_os_is windows ; then __docker_complete_isolation return fi @@ -1942,8 +2100,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) - # shellcheck disable=SC2128 - if [ "$COMPREPLY" = "container:" ]; then + if [ "${COMPREPLY[*]}" = "container:" ]; then __docker_nospace fi ;; @@ -1998,7 +2155,7 @@ _docker_container_run_and_create() { *) local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag --id fi ;; esac @@ -2006,15 +2163,14 @@ _docker_container_run_and_create() { _docker_container_start() { __docker_complete_detach_keys && return - # shellcheck disable=SC2078 case "$prev" in --checkpoint) - if [ __docker_daemon_is_experimental ] ; then + if __docker_server_is_experimental ; then return fi ;; --checkpoint-dir) - if [ __docker_daemon_is_experimental ] ; then + if __docker_server_is_experimental ; then _filedir -d return fi @@ -2024,7 +2180,7 @@ _docker_container_start() { case "$cur" in -*) local options="--attach -a --detach-keys --help --interactive -i" - __docker_daemon_is_experimental && options+=" --checkpoint --checkpoint-dir" + __docker_server_is_experimental && options+=" --checkpoint --checkpoint-dir" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) @@ -2062,7 +2218,7 @@ _docker_container_stop() { COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) ;; *) - __docker_complete_containers_running + __docker_complete_containers_stoppable ;; esac } @@ -2110,6 +2266,7 @@ _docker_container_update() { --memory -m --memory-reservation --memory-swap + --pids-limit --restart " @@ -2149,6 +2306,172 @@ _docker_container_wait() { } +_docker_context() { + local subcommands=" + create + export + import + inspect + ls + rm + update + use + " + local aliases=" + list + remove + " + __docker_subcommands "$subcommands $aliases" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_context_create() { + case "$prev" in + --default-stack-orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur" ) ) + return + ;; + --description|--docker|--kubernetes) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--default-stack-orchestrator --description --docker --help --kubernetes" -- "$cur" ) ) + ;; + esac +} + +_docker_context_export() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --kubeconfig" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts + elif [ "$cword" -eq "$((counter + 1))" ]; then + _filedir + fi + ;; + esac +} + +_docker_context_import() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + : + elif [ "$cword" -eq "$((counter + 1))" ]; then + _filedir + fi + ;; + esac +} + +_docker_context_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_contexts + ;; + esac +} + +_docker_context_list() { + _docker_context_ls +} + +_docker_context_ls() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_context_remove() { + _docker_context_rm +} + +_docker_context_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_contexts + ;; + esac +} + +_docker_context_update() { + case "$prev" in + --default-stack-orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur" ) ) + return + ;; + --description|--docker|--kubernetes) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--default-stack-orchestrator --description --docker --help --kubernetes" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts + fi + ;; + esac +} + +_docker_context_use() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts --add default + fi + ;; + esac +} + + _docker_commit() { _docker_container_commit } @@ -2196,6 +2519,7 @@ _docker_daemon() { --cpu-rt-period --cpu-rt-runtime --data-root + --default-address-pool --default-gateway --default-gateway-v6 --default-runtime @@ -2386,13 +2710,75 @@ _docker_daemon() { } _docker_deploy() { - __docker_daemon_is_experimental && _docker_stack_deploy + __docker_server_is_experimental && _docker_stack_deploy } _docker_diff() { _docker_container_diff } + +_docker_engine() { + local subcommands=" + activate + check + update + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_activate() { + case "$prev" in + --containerd|--engine-image|--format|--license|--registry-prefix|--version) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --display-only --engine-image --format --help --license --quiet --registry-prefix --version" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_check() { + case "$prev" in + --containerd|--engine-image|--format|--registry-prefix) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --downgrades --engine-image --format --help --pre-releases --quiet -q --registry-prefix --upgrades" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_update() { + case "$prev" in + --containerd|--engine-image|--registry-prefix|--version) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --engine-image --help --registry-prefix --version" -- "$cur" ) ) + ;; + esac +} + + _docker_events() { _docker_system_events } @@ -2472,7 +2858,7 @@ _docker_image_build() { --target --ulimit " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --isolation " @@ -2486,7 +2872,7 @@ _docker_image_build() { --quiet -q --rm " - if __docker_daemon_is_experimental ; then + if __docker_server_is_experimental ; then options_with_args+=" --platform " @@ -2513,7 +2899,7 @@ _docker_image_build() { return ;; --cache-from) - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag --id return ;; --file|-f|--iidfile) @@ -2521,7 +2907,7 @@ _docker_image_build() { return ;; --isolation) - if __docker_daemon_os_is windows ; then + if __docker_server_os_is windows ; then __docker_complete_isolation return fi @@ -2541,7 +2927,7 @@ _docker_image_build() { return ;; --tag|-t) - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag return ;; --target) @@ -2587,9 +2973,9 @@ _docker_image_history() { COMPREPLY=( $( compgen -W "--format --help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag) + local counter=$(__docker_pos_first_nonflag '--format') if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --force-tag --id fi ;; esac @@ -2601,24 +2987,24 @@ _docker_image_images() { _docker_image_import() { case "$prev" in - --change|-c|--message|-m) + --change|-c|--message|-m|--platform) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) ) + local options="--change -c --help --message -m" + __docker_server_is_experimental && options+=" --platform" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m') if [ "$cword" -eq "$counter" ]; then + _filedir return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -2651,9 +3037,8 @@ _docker_image_list() { _docker_image_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in - before|since|reference) - cur="${cur##*=}" - __docker_complete_images + before|since) + __docker_complete_images --cur "${cur##*=}" --force-tag --id return ;; dangling) @@ -2663,6 +3048,10 @@ _docker_image_ls() { label) return ;; + reference) + __docker_complete_images --cur "${cur##*=}" --repo --tag + return + ;; esac case "$prev" in @@ -2684,7 +3073,7 @@ _docker_image_ls() { return ;; *) - __docker_complete_image_repos + __docker_complete_images --repo --tag ;; esac } @@ -2714,8 +3103,8 @@ _docker_image_pull() { case "$cur" in -*) - local options="--all-tags -a --disable-content-trust=false --help" - __docker_daemon_is_experimental && options+=" --platform" + local options="--all-tags -a --disable-content-trust=false --help --quiet -q" + __docker_server_is_experimental && options+=" --platform" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; @@ -2725,12 +3114,12 @@ _docker_image_pull() { for arg in "${COMP_WORDS[@]}"; do case "$arg" in --all-tags|-a) - __docker_complete_image_repos + __docker_complete_images --repo return ;; esac done - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag fi ;; esac @@ -2744,7 +3133,7 @@ _docker_image_push() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag fi ;; esac @@ -2760,7 +3149,7 @@ _docker_image_rm() { COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) ) ;; *) - __docker_complete_images + __docker_complete_images --force-tag --id ;; esac } @@ -2782,7 +3171,7 @@ _docker_image_save() { COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) ) ;; *) - __docker_complete_images + __docker_complete_images --repo --tag --id ;; esac } @@ -2796,13 +3185,10 @@ _docker_image_tag() { local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + __docker_complete_images --force-tag --id return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -2858,7 +3244,7 @@ _docker_inspect() { '') COMPREPLY=( $( compgen -W " $(__docker_containers --all) - $(__docker_images) + $(__docker_images --force-tag --id) $(__docker_networks) $(__docker_nodes) $(__docker_plugins_installed) @@ -2872,7 +3258,7 @@ _docker_inspect() { __docker_complete_containers_all ;; image) - __docker_complete_images + __docker_complete_images --force-tag --id ;; network) __docker_complete_networks @@ -3045,6 +3431,10 @@ _docker_network_inspect() { _docker_network_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in + dangling) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; driver) __docker_complete_plugins_bundled --cur "${cur##*=}" --type Network --add macvlan return @@ -3069,7 +3459,7 @@ _docker_network_ls() { case "$prev" in --filter|-f) - COMPREPLY=( $( compgen -S = -W "driver id label name scope type" -- "$cur" ) ) + COMPREPLY=( $( compgen -S = -W "dangling driver id label name scope type" -- "$cur" ) ) __docker_nospace return ;; @@ -3195,7 +3585,7 @@ _docker_service_logs() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--follow -f --help --no-resolve --no-task-ids --no-trunc --since --tail --timestamps -t" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--details --follow -f --help --no-resolve --no-task-ids --no-trunc --raw --since --tail --timestamps -t" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--since|--tail') @@ -3334,8 +3724,6 @@ _docker_service_update_and_create() { local options_with_args=" --endpoint-mode --entrypoint - --env -e - --force --health-cmd --health-interval --health-retries @@ -3343,13 +3731,12 @@ _docker_service_update_and_create() { --health-timeout --hostname --isolation - --label -l --limit-cpu --limit-memory --log-driver --log-opt - --mount --replicas + --replicas-max-per-node --reserve-cpu --reserve-memory --restart-condition @@ -3373,14 +3760,16 @@ _docker_service_update_and_create() { --user -u --workdir -w " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --credential-spec " local boolean_options=" --detach -d --help + --init --no-healthcheck + --no-resolve-image --read-only --tty -t --with-registry-auth @@ -3396,52 +3785,31 @@ _docker_service_update_and_create() { --dns --dns-option --dns-search + --env -e --env-file --generic-resource --group --host + --label -l --mode + --mount --name --network --placement-pref --publish -p --secret + --sysctl " case "$prev" in - --config) - __docker_complete_configs - return - ;; --env-file) _filedir return ;; - --group) - COMPREPLY=( $(compgen -g -- "$cur") ) - return - ;; - --host) - case "$cur" in - *:) - __docker_complete_resolved_hostname - return - ;; - esac - ;; --mode) COMPREPLY=( $( compgen -W "global replicated" -- "$cur" ) ) return ;; - --placement-pref) - COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) - __docker_nospace - return - ;; - --secret) - __docker_complete_secrets - return - ;; esac fi if [ "$subcommand" = "update" ] ; then @@ -3459,6 +3827,8 @@ _docker_service_update_and_create() { --dns-rm --dns-search-add --dns-search-rm + --env-add + --env-rm --generic-resource-add --generic-resource-rm --group-add @@ -3466,6 +3836,10 @@ _docker_service_update_and_create() { --host-add --host-rm --image + --label-add + --label-rm + --mount-add + --mount-rm --network-add --network-rm --placement-pref-add @@ -3475,40 +3849,21 @@ _docker_service_update_and_create() { --rollback --secret-add --secret-rm + --sysctl-add + --sysctl-rm + " + + boolean_options="$boolean_options + --force " case "$prev" in - --config-add|--config-rm) - __docker_complete_configs + --env-rm) + COMPREPLY=( $( compgen -e -- "$cur" ) ) return ;; - --group-add|--group-rm) - COMPREPLY=( $(compgen -g -- "$cur") ) - return - ;; - --host-add|--host-rm) - case "$cur" in - *:) - __docker_complete_resolved_hostname - return - ;; - esac - ;; --image) - __docker_complete_image_repos_and_tags - return - ;; - --network-add|--network-rm) - __docker_complete_networks - return - ;; - --placement-pref-add|--placement-pref-rm) - COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) - __docker_nospace - return - ;; - --secret-add|--secret-rm) - __docker_complete_secrets + __docker_complete_images --repo --tag --id return ;; esac @@ -3524,16 +3879,32 @@ _docker_service_update_and_create() { esac case "$prev" in + --config|--config-add|--config-rm) + __docker_complete_configs + return + ;; --endpoint-mode) COMPREPLY=( $( compgen -W "dnsrr vip" -- "$cur" ) ) return ;; - --env|-e) + --env|-e|--env-add) # we do not append a "=" here because "-e VARNAME" is legal systax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; + --group|--group-add|--group-rm) + COMPREPLY=( $(compgen -g -- "$cur") ) + return + ;; + --host|--host-add|--host-rm) + case "$cur" in + *:) + __docker_complete_resolved_hostname + return + ;; + esac + ;; --isolation) __docker_complete_isolation return @@ -3546,10 +3917,15 @@ _docker_service_update_and_create() { __docker_complete_log_options return ;; - --network) + --network|--network-add|--network-rm) __docker_complete_networks return ;; + --placement-pref|--placement-pref-add|--placement-pref-rm) + COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) + __docker_nospace + return + ;; --restart-condition) COMPREPLY=( $( compgen -W "any none on-failure" -- "$cur" ) ) return @@ -3558,6 +3934,10 @@ _docker_service_update_and_create() { COMPREPLY=( $( compgen -W "continue pause" -- "$cur" ) ) return ;; + --secret|--secret-add|--secret-rm) + __docker_complete_secrets + return + ;; --stop-signal) __docker_complete_signals return @@ -3591,7 +3971,7 @@ _docker_service_update_and_create() { fi else if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag --id fi fi ;; @@ -3654,7 +4034,7 @@ _docker_swarm_init() { COMPREPLY=( $( compgen -W "active drain pause" -- "$cur" ) ) return ;; - --cert-expiry|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit) + --cert-expiry|--data-path-port|--default-addr-pool|--default-addr-pool-mask-length|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit ) return ;; --data-path-addr) @@ -3674,7 +4054,7 @@ _docker_swarm_init() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --data-path-port --default-addr-pool --default-addr-pool-mask-length --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit " -- "$cur" ) ) ;; esac } @@ -3774,6 +4154,109 @@ _docker_swarm_update() { esac } +_docker_manifest() { + local subcommands=" + annotate + create + inspect + push + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_manifest_annotate() { + case "$prev" in + --arch) + COMPREPLY=( $( compgen -W " + 386 + amd64 + arm + arm64 + mips64 + mips64le + ppc64le + s390x" -- "$cur" ) ) + return + ;; + --os) + COMPREPLY=( $( compgen -W " + darwin + dragonfly + freebsd + linux + netbsd + openbsd + plan9 + solaris + windows" -- "$cur" ) ) + return + ;; + --os-features|--variant) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--arch --help --os --os-features --variant" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag "--arch|--os|--os-features|--variant" ) + if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + +_docker_manifest_create() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--amend -a --help --insecure" -- "$cur" ) ) + ;; + *) + __docker_complete_images --force-tag --id + ;; + esac +} + +_docker_manifest_inspect() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --insecure --verbose -v" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag ) + if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + +_docker_manifest_push() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --insecure --purge -p" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag ) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + _docker_node() { local subcommands=" demote @@ -4237,14 +4720,18 @@ _docker_secret_create() { --driver|-d|--label|-l) return ;; + --template-driver) + COMPREPLY=( $( compgen -W "golang" -- "$cur" ) ) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--driver -d --help --label -l" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--driver -d --help --label -l --template-driver" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--driver|-d|--label|-l') + local counter=$(__docker_pos_first_nonflag '--driver|-d|--label|-l|--template-driver') if [ "$cword" -eq "$((counter + 1))" ]; then _filedir fi @@ -4367,11 +4854,15 @@ _docker_stack() { remove up " + + __docker_complete_stack_orchestrator_options && return __docker_subcommands "$subcommands $aliases" && return case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + local options="--help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) @@ -4380,12 +4871,12 @@ _docker_stack() { } _docker_stack_deploy() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --bundle-file) - if __docker_daemon_is_experimental ; then - _filedir dab - return - fi + _filedir dab + return ;; --compose-file|-c) _filedir yml @@ -4399,12 +4890,14 @@ _docker_stack_deploy() { case "$cur" in -*) - local options="--compose-file -c --help --prune --resolve-image --with-registry-auth" - __docker_daemon_is_experimental && options+=" --bundle-file" + local options="--compose-file -c --help --orchestrator" + __docker_server_is_experimental && __docker_stack_orchestrator_is swarm && options+=" --bundle-file" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + __docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--bundle-file|--compose-file|-c|--resolve-image') + local counter=$(__docker_pos_first_nonflag '--bundle-file|--compose-file|-c|--kubeconfig|--namespace|--orchestrator|--resolve-image') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4421,6 +4914,8 @@ _docker_stack_list() { } _docker_stack_ls() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --format) return @@ -4429,7 +4924,9 @@ _docker_stack_ls() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--format --help" -- "$cur" ) ) + local options="--format --help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --all-namespaces --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; esac } @@ -4451,6 +4948,8 @@ _docker_stack_ps() { ;; esac + __docker_complete_stack_orchestrator_options && return + case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "id name desired-state" -- "$cur" ) ) @@ -4464,10 +4963,12 @@ _docker_stack_ps() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--filter -f --format --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) ) + local options="--filter -f --format --help --no-resolve --no-trunc --orchestrator --quiet -q" + __docker_stack_orchestrator_is kubernetes && options+=" --all-namespaces --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--filter|-f') + local counter=$(__docker_pos_first_nonflag '--all-namespaces|--filter|-f|--format|--kubeconfig|--namespace') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4480,9 +4981,13 @@ _docker_stack_remove() { } _docker_stack_rm() { + __docker_complete_stack_orchestrator_options && return + case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + local options="--help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) __docker_complete_stacks @@ -4506,6 +5011,8 @@ _docker_stack_services() { ;; esac + __docker_complete_stack_orchestrator_options && return + case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "id label name" -- "$cur" ) ) @@ -4519,10 +5026,12 @@ _docker_stack_services() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--filter -f --format --help --quiet -q" -- "$cur" ) ) + local options="--filter -f --format --help --orchestrator --quiet -q" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--filter|-f|--format') + local counter=$(__docker_pos_first_nonflag '--filter|-f|--format|--kubeconfig|--namespace|--orchestrator') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4609,6 +5118,7 @@ _docker_system_events() { enable exec_create exec_detach + exec_die exec_start export health_status @@ -4639,16 +5149,19 @@ _docker_system_events() { return ;; image) - cur="${cur##*=}" - __docker_complete_images + __docker_complete_images --cur "${cur##*=}" --repo --tag return ;; network) __docker_complete_networks --cur "${cur##*=}" return ;; + scope) + COMPREPLY=( $( compgen -W "local swarm" -- "${cur##*=}" ) ) + return + ;; type) - COMPREPLY=( $( compgen -W "container daemon image network plugin volume" -- "${cur##*=}" ) ) + COMPREPLY=( $( compgen -W "config container daemon image network plugin secret service volume" -- "${cur##*=}" ) ) return ;; volume) @@ -4659,7 +5172,7 @@ _docker_system_events() { case "$prev" in --filter|-f) - COMPREPLY=( $( compgen -S = -W "container daemon event image label network type volume" -- "$cur" ) ) + COMPREPLY=( $( compgen -S = -W "container daemon event image label network scope type volume" -- "$cur" ) ) __docker_nospace return ;; @@ -4713,9 +5226,9 @@ _docker_tag() { _docker_trust() { local subcommands=" + inspect revoke sign - view " __docker_subcommands "$subcommands" && return @@ -4729,6 +5242,20 @@ _docker_trust() { esac } +_docker_trust_inspect() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --pretty" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_images --repo --tag + fi + ;; + esac +} + _docker_trust_revoke() { case "$cur" in -*) @@ -4737,7 +5264,7 @@ _docker_trust_revoke() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag fi ;; esac @@ -4751,21 +5278,7 @@ _docker_trust_sign() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images - fi - ;; - esac -} - -_docker_trust_view() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__docker_pos_first_nonflag) - if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --force-tag --id fi ;; esac @@ -4785,6 +5298,8 @@ _docker_top() { } _docker_version() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --format|-f) return @@ -4793,7 +5308,9 @@ _docker_version() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + local options="--format -f --help" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; esac } @@ -4936,8 +5453,11 @@ _docker() { shopt -s extglob local management_commands=( + builder config container + context + engine image network node @@ -4947,6 +5467,7 @@ _docker() { stack swarm system + trust volume ) @@ -4996,10 +5517,13 @@ _docker() { wait ) - local experimental_commands=( + local experimental_client_commands=( + manifest + ) + + local experimental_server_commands=( checkpoint deploy - trust ) local commands=(${management_commands[*]} ${top_level_commands[*]}) @@ -5014,6 +5538,7 @@ _docker() { " local global_options_with_args=" --config + --context -c --host -H --log-level -l --tlscacert @@ -5021,7 +5546,12 @@ _docker() { --tlskey " - local host config daemon_os + # variables to cache server info, populated on demand for performance reasons + local info_fetched server_experimental server_os + # variables to cache client info, populated on demand for performance reasons + local client_experimental stack_orchestrator_is_kubernetes stack_orchestrator_is_swarm + + local host config context COMPREPLY=() local cur prev words cword @@ -5031,6 +5561,9 @@ _docker() { local counter=1 while [ "$counter" -lt "$cword" ]; do case "${words[$counter]}" in + docker) + return 0 + ;; # save host so that completion can use custom daemon --host|-H) (( counter++ )) @@ -5041,6 +5574,11 @@ _docker() { (( counter++ )) config="${words[$counter]}" ;; + # save context so that completion can use custom daemon + --context|-c) + (( counter++ )) + context="${words[$counter]}" + ;; $(__docker_to_extglob "$global_options_with_args") ) (( counter++ )) ;; @@ -5076,4 +5614,4 @@ _docker() { eval "$__docker_previous_extglob_setting" unset __docker_previous_extglob_setting -complete -F _docker docker docker.exe dockerd dockerd.exe +complete -F _docker docker docker.exe dockerd dockerd.exe \ No newline at end of file From 4329da109ecf43f5672617309a081a51d4f9061e Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:45 +0700 Subject: [PATCH 2/3] Update docker compose collection --- .../available/docker-compose.completion.bash | 224 +++++++++++------- 1 file changed, 134 insertions(+), 90 deletions(-) diff --git a/completion/available/docker-compose.completion.bash b/completion/available/docker-compose.completion.bash index 87161d0a..dedd8e31 100644 --- a/completion/available/docker-compose.completion.bash +++ b/completion/available/docker-compose.completion.bash @@ -16,6 +16,8 @@ # below to your .bashrc after bash completion features are loaded # . ~/.docker-compose-completion.sh +__docker_compose_previous_extglob_setting=$(shopt -p extglob) +shopt -s extglob __docker_compose_q() { docker-compose 2>/dev/null "${top_level_options[@]}" "$@" @@ -48,64 +50,56 @@ __docker_compose_has_option() { return 1 } +# Returns `key` if we are currently completing the value of a map option (`key=value`) +# which matches the extglob passed in as an argument. +# This function is needed for key-specific completions. +__docker_compose_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" +} + # suppress trailing whitespace __docker_compose_nospace() { # compopt is not available in ancient bash versions type compopt &>/dev/null && compopt -o nospace } -# Extracts all service names from the compose file. -___docker_compose_all_services_in_compose_file() { - __docker_compose_q config --services + +# Outputs a list of all defined services, regardless of their running state. +# Arguments for `docker-compose ps` may be passed in order to filter the service list, +# e.g. `status=running`. +__docker_compose_services() { + __docker_compose_q ps --services "$@" } -# All services, even those without an existing container -__docker_compose_services_all() { - COMPREPLY=( $(compgen -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) -} - -# All services that have an entry with the given key in their compose_file section -___docker_compose_services_with_key() { - # flatten sections under "services" to one line, then filter lines containing the key and return section name - __docker_compose_q config \ - | sed -n -e '/^services:/,/^[^ ]/p' \ - | sed -n 's/^ //p' \ - | awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' \ - | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' -} - -# All services that are defined by a Dockerfile reference -__docker_compose_services_from_build() { - COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key build)" -- "$cur") ) -} - -# All services that are defined by an image -__docker_compose_services_from_image() { - COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key image)" -- "$cur") ) -} - -# The services for which containers have been created, optionally filtered -# by a boolean expression passed in as argument. -__docker_compose_services_with() { - local containers names - containers="$(__docker_compose_q ps -q)" - names=$(docker 2>/dev/null inspect -f "{{if ${1:-true}}}{{range \$k, \$v := .Config.Labels}}{{if eq \$k \"com.docker.compose.service\"}}{{\$v}}{{end}}{{end}}{{end}}" $containers) - COMPREPLY=( $(compgen -W "$names" -- "$cur") ) -} - -# The services for which at least one paused container exists -__docker_compose_services_paused() { - __docker_compose_services_with '.State.Paused' +# Applies completion of services based on the current value of `$cur`. +# Arguments for `docker-compose ps` may be passed in order to filter the service list, +# see `__docker_compose_services`. +__docker_compose_complete_services() { + COMPREPLY=( $(compgen -W "$(__docker_compose_services "$@")" -- "$cur") ) } # The services for which at least one running container exists -__docker_compose_services_running() { - __docker_compose_services_with '.State.Running' -} - -# The services for which at least one stopped container exists -__docker_compose_services_stopped() { - __docker_compose_services_with 'not .State.Running' +__docker_compose_complete_running_services() { + local names=$(__docker_compose_services --filter status=running) + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } @@ -116,14 +110,17 @@ _docker_compose_build() { __docker_compose_nospace return ;; + --memory|-m) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--build-arg --force-rm --help --memory --no-cache --pull" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--build-arg --compress --force-rm --help --memory -m --no-cache --no-rm --pull --parallel -q --quiet" -- "$cur" ) ) ;; *) - __docker_compose_services_from_build + __docker_compose_complete_services --filter source=build ;; esac } @@ -142,7 +139,18 @@ _docker_compose_bundle() { _docker_compose_config() { - COMPREPLY=( $( compgen -W "--help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) + case "$prev" in + --hash) + if [[ $cur == \\* ]] ; then + COMPREPLY=( '\*' ) + else + COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") ) + fi + return + ;; + esac + + COMPREPLY=( $( compgen -W "--hash --help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) } @@ -152,7 +160,7 @@ _docker_compose_create() { COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -168,18 +176,22 @@ _docker_compose_docker_compose() { _filedir "y?(a)ml" return ;; + --log-level) + COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) ) + return + ;; --project-directory) _filedir -d return ;; - $(__docker_compose_to_extglob "$top_level_options_with_args") ) + $(__docker_compose_to_extglob "$daemon_options_with_args") ) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "$top_level_boolean_options $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) @@ -194,11 +206,14 @@ _docker_compose_down() { COMPREPLY=( $( compgen -W "all local" -- "$cur" ) ) return ;; + --timeout|-t) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --rmi --volumes -v --remove-orphans" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --rmi --timeout -t --volumes -v --remove-orphans" -- "$cur" ) ) ;; esac } @@ -216,7 +231,7 @@ _docker_compose_events() { COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -224,17 +239,17 @@ _docker_compose_events() { _docker_compose_exec() { case "$prev" in - --index|--user|-u) + --index|--user|-u|--workdir|-w) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "-d --help --index --privileged -T --user -u" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -247,10 +262,10 @@ _docker_compose_help() { _docker_compose_images() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --quiet -q" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -268,7 +283,7 @@ _docker_compose_kill() { COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -286,7 +301,7 @@ _docker_compose_logs() { COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -298,7 +313,7 @@ _docker_compose_pause() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -320,19 +335,39 @@ _docker_compose_port() { COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } _docker_compose_ps() { + local key=$(__docker_compose_map_key_of_current_option '--filter') + case "$key" in + source) + COMPREPLY=( $( compgen -W "build image" -- "${cur##*=}" ) ) + return + ;; + status) + COMPREPLY=( $( compgen -W "paused restarting running stopped" -- "${cur##*=}" ) ) + return + ;; + esac + + case "$prev" in + --filter) + COMPREPLY=( $( compgen -W "source status" -S "=" -- "$cur" ) ) + __docker_compose_nospace + return; + ;; + esac + case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--all -a --filter --help --quiet -q --services" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -341,10 +376,10 @@ _docker_compose_ps() { _docker_compose_pull() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --parallel --quiet" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) ) ;; *) - __docker_compose_services_from_image + __docker_compose_complete_services --filter source=image ;; esac } @@ -356,7 +391,7 @@ _docker_compose_push() { COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -374,7 +409,7 @@ _docker_compose_restart() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -387,9 +422,9 @@ _docker_compose_rm() { ;; *) if __docker_compose_has_option "--stop|-s" ; then - __docker_compose_services_all + __docker_compose_complete_services else - __docker_compose_services_stopped + __docker_compose_complete_services --filter status=stopped fi ;; esac @@ -410,10 +445,10 @@ _docker_compose_run() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --label -l --name --no-deps --publish -p --rm --service-ports -T --user -u --volume -v --workdir -w" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--detach -d --entrypoint -e --help --label -l --name --no-deps --publish -p --rm --service-ports -T --use-aliases --user -u --volume -v --workdir -w" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -435,7 +470,7 @@ _docker_compose_scale() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) + COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") ) __docker_compose_nospace ;; esac @@ -448,7 +483,7 @@ _docker_compose_start() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_stopped + __docker_compose_complete_services --filter status=stopped ;; esac } @@ -466,7 +501,7 @@ _docker_compose_stop() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -478,7 +513,7 @@ _docker_compose_top() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -490,7 +525,7 @@ _docker_compose_unpause() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_paused + __docker_compose_complete_services --filter status=paused ;; esac } @@ -503,11 +538,11 @@ _docker_compose_up() { return ;; --exit-code-from) - __docker_compose_services_all + __docker_compose_complete_services return ;; --scale) - COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) + COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") ) __docker_compose_nospace return ;; @@ -518,10 +553,10 @@ _docker_compose_up() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --remove-orphans --scale --timeout -t" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --build -d --detach --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --renew-anon-volumes -V --remove-orphans --scale --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -571,14 +606,12 @@ _docker_compose() { # Options for the docker daemon that have to be passed to secondary calls to # docker-compose executed by this script. - # Other global otions that are not relevant for secondary calls are defined in - # `_docker_compose_docker_compose`. - local top_level_boolean_options=" + local daemon_boolean_options=" --skip-hostname-check --tls --tlsverify " - local top_level_options_with_args=" + local daemon_options_with_args=" --file -f --host -H --project-directory @@ -588,6 +621,11 @@ _docker_compose() { --tlskey " + # These options are require special treatment when searching the command. + local top_level_options_with_args=" + --log-level + " + COMPREPLY=() local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword @@ -600,15 +638,18 @@ _docker_compose() { while [ $counter -lt $cword ]; do case "${words[$counter]}" in - $(__docker_compose_to_extglob "$top_level_boolean_options") ) + $(__docker_compose_to_extglob "$daemon_boolean_options") ) local opt=${words[counter]} top_level_options+=($opt) ;; - $(__docker_compose_to_extglob "$top_level_options_with_args") ) + $(__docker_compose_to_extglob "$daemon_options_with_args") ) local opt=${words[counter]} local arg=${words[++counter]} top_level_options+=($opt $arg) ;; + $(__docker_compose_to_extglob "$top_level_options_with_args") ) + (( counter++ )) + ;; -*) ;; *) @@ -626,4 +667,7 @@ _docker_compose() { return 0 } -complete -F _docker_compose docker-compose docker-compose.exe +eval "$__docker_compose_previous_extglob_setting" +unset __docker_compose_previous_extglob_setting + +complete -F _docker_compose docker-compose docker-compose.exe \ No newline at end of file From df011d7ab636239145354b24839d49a5ba0cc84d Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:55 +0700 Subject: [PATCH 3/3] Update docker machine completion --- .../available/docker-machine.completion.bash | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/completion/available/docker-machine.completion.bash b/completion/available/docker-machine.completion.bash index e92bd4cf..8c692ff6 100644 --- a/completion/available/docker-machine.completion.bash +++ b/completion/available/docker-machine.completion.bash @@ -86,6 +86,40 @@ _docker_machine_map_key_of_current_option() { [[ ${words[$glob_pos]} == $glob ]] && echo "$key" } +# Finds the position of the first word that is neither option nor an option's argument. +# If there are options that require arguments, you need to pass a glob describing +# those options, e.g. "--option1|-o|--option2". +# Use this function to restrict completions to exact positions after the options. +_docker_machine_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 +} # --- completion functions --------------------------------------------------- _docker_machine_active() { @@ -128,7 +162,7 @@ _docker_machine_create() { _docker_machine_env() { case "${prev}" in --shell) - COMPREPLY=($(compgen -W "cmd fish powershell tcsh" -- "${cur}")) + COMPREPLY=($(compgen -W "cmd emacs fish powershell tcsh" -- "${cur}")) return ;; esac @@ -208,6 +242,21 @@ _docker_machine_ls() { fi } +_docker_machine_mount() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help --unmount -u" -- "${cur}")) + else + local pos=$(_docker_machine_pos_first_nonflag) + if [ "$cword" -eq "$pos" ]; then + # We can't complete remote filesystems. All we can do here is to complete the machine. + COMPREPLY=($(compgen -W "$(_docker_machine_machines --filter state=Running)" -S: -- "${cur}")) + _docker_machine_nospace + elif [ "$cword" -eq "$((pos + 1))" ]; then + _filedir -d + fi + fi +} + _docker_machine_provision() { if [[ "${cur}" == -* ]]; then COMPREPLY=($(compgen -W "--help" -- "${cur}")) @@ -218,7 +267,7 @@ _docker_machine_provision() { _docker_machine_regenerate_certs() { if [[ "${cur}" == -* ]]; then - COMPREPLY=($(compgen -W "--force -f --help" -- "${cur}")) + COMPREPLY=($(compgen -W "--client-certs --force -f --help" -- "${cur}")) else COMPREPLY=($(compgen -W "$(_docker_machine_machines --filter state=Running)" -- "${cur}")) fi @@ -250,7 +299,7 @@ _docker_machine_ssh() { _docker_machine_scp() { if [[ "${cur}" == -* ]]; then - COMPREPLY=($(compgen -W "--delta -d --help --recursive -r" -- "${cur}")) + COMPREPLY=($(compgen -W "--delta -d --help --quiet -q --recursive -r" -- "${cur}")) else _filedir # It would be really nice to ssh to the machine and ls to complete @@ -329,7 +378,7 @@ _docker_machine_docker_machine() { _docker_machine() { COMPREPLY=() - local commands=(active config create env inspect ip kill ls provision regenerate-certs restart rm ssh scp start status stop upgrade url version help) + local commands=(active config create env inspect ip kill ls mount provision regenerate-certs restart rm ssh scp start status stop upgrade url version help) local flags=(--debug --native-ssh --github-api-token --bugsnag-api-token --help --version) local wants_dir=(--storage-path) @@ -343,7 +392,7 @@ _docker_machine() { local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword local i - local command=docker-machine + local command=docker-machine command_pos=0 for (( i=1; i < ${cword}; ++i)); do local word=${words[i]} @@ -352,6 +401,7 @@ _docker_machine() { (( ++i )) elif [[ " ${commands[*]} " =~ " ${word} " ]]; then command=${word} + command_pos=$i fi done @@ -363,4 +413,4 @@ _docker_machine() { return 0 } -complete -F _docker_machine docker-machine docker-machine.exe +complete -F _docker_machine docker-machine docker-machine.exe \ No newline at end of file