Parent directory

_docker-compose

18168 bytes
  1#compdef docker-compose
  2
  3# Description
  4# -----------
  5#  zsh completion for docker-compose
  6# -------------------------------------------------------------------------
  7# Authors
  8# -------
  9#  * Steve Durrheimer <s.durrheimer@gmail.com>
 10# -------------------------------------------------------------------------
 11# Inspiration
 12# -----------
 13#  * @albers docker-compose bash completion script
 14#  * @felixr docker zsh completion script : https://github.com/felixr/docker-zsh-completion
 15# -------------------------------------------------------------------------
 16
 17__docker-compose_q() {
 18    docker-compose 2>/dev/null $compose_options "$@"
 19}
 20
 21# All services defined in docker-compose.yml
 22__docker-compose_all_services_in_compose_file() {
 23    local already_selected
 24    local -a services
 25    already_selected=$(echo $words | tr " " "|")
 26    __docker-compose_q ps --services "$@" \
 27        | grep -Ev "^(${already_selected})$"
 28}
 29
 30# All services, even those without an existing container
 31__docker-compose_services_all() {
 32    [[ $PREFIX = -* ]] && return 1
 33    integer ret=1
 34    services=$(__docker-compose_all_services_in_compose_file "$@")
 35    _alternative "args:services:($services)" && ret=0
 36
 37    return ret
 38}
 39
 40# All services that are defined by a Dockerfile reference
 41__docker-compose_services_from_build() {
 42    [[ $PREFIX = -* ]] && return 1
 43    __docker-compose_services_all --filter source=build
 44}
 45
 46# All services that are defined by an image
 47__docker-compose_services_from_image() {
 48    [[ $PREFIX = -* ]] && return 1
 49    __docker-compose_services_all --filter source=image
 50}
 51
 52__docker-compose_pausedservices() {
 53    [[ $PREFIX = -* ]] && return 1
 54    __docker-compose_services_all --filter status=paused
 55}
 56
 57__docker-compose_stoppedservices() {
 58    [[ $PREFIX = -* ]] && return 1
 59    __docker-compose_services_all --filter status=stopped
 60}
 61
 62__docker-compose_runningservices() {
 63    [[ $PREFIX = -* ]] && return 1
 64    __docker-compose_services_all --filter status=running
 65}
 66
 67__docker-compose_services() {
 68    [[ $PREFIX = -* ]] && return 1
 69    __docker-compose_services_all
 70}
 71
 72__docker-compose_caching_policy() {
 73    oldp=( "$1"(Nmh+1) )            # 1 hour
 74    (( $#oldp ))
 75}
 76
 77__docker-compose_commands() {
 78    local cache_policy
 79
 80    zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
 81    if [[ -z "$cache_policy" ]]; then
 82        zstyle ":completion:${curcontext}:" cache-policy __docker-compose_caching_policy
 83    fi
 84
 85    if ( [[ ${+_docker_compose_subcommands} -eq 0 ]] || _cache_invalid docker_compose_subcommands) \
 86        && ! _retrieve_cache docker_compose_subcommands;
 87    then
 88        local -a lines
 89        lines=(${(f)"$(_call_program commands docker-compose 2>&1)"})
 90        _docker_compose_subcommands=(${${${lines[$((${lines[(i)Commands:]} + 1)),${lines[(I)  *]}]}## #}/ ##/:})
 91        (( $#_docker_compose_subcommands > 0 )) && _store_cache docker_compose_subcommands _docker_compose_subcommands
 92    fi
 93    _describe -t docker-compose-commands "docker-compose command" _docker_compose_subcommands
 94}
 95
 96__docker-compose_subcommand() {
 97    local opts_help opts_force_recreate opts_no_recreate opts_no_build opts_remove_orphans opts_timeout opts_no_color opts_no_deps
 98
 99    opts_help='(: -)--help[Print usage]'
100    opts_force_recreate="(--no-recreate)--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]"
101    opts_no_recreate="(--force-recreate)--no-recreate[If containers already exist, don't recreate them. Incompatible with --force-recreate.]"
102    opts_no_build="(--build)--no-build[Don't build an image, even if it's missing.]"
103    opts_remove_orphans="--remove-orphans[Remove containers for services not defined in the Compose file]"
104    opts_timeout=('(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: ")
105    opts_no_color='--no-color[Produce monochrome output.]'
106    opts_no_deps="--no-deps[Don't start linked services.]"
107
108    integer ret=1
109
110    case "$words[1]" in
111        (build)
112            _arguments \
113                $opts_help \
114                "*--build-arg=[Set build-time variables for one service.]:<varname>=<value>: " \
115                '--force-rm[Always remove intermediate containers.]' \
116                '(--quiet -q)'{--quiet,-q}'[Curb build output]' \
117                '(--memory -m)'{--memory,-m}'[Memory limit for the build container.]' \
118                '--no-cache[Do not use cache when building the image.]' \
119                '--pull[Always attempt to pull a newer version of the image.]' \
120                '--compress[Compress the build context using gzip.]' \
121                '--parallel[Build images in parallel.]' \
122                '*:services:__docker-compose_services_from_build' && ret=0
123            ;;
124        (config)
125            _arguments \
126                $opts_help \
127                '(--quiet -q)'{--quiet,-q}"[Only validate the configuration, don't print anything.]" \
128                '--resolve-image-digests[Pin image tags to digests.]' \
129                '--services[Print the service names, one per line.]' \
130                '--volumes[Print the volume names, one per line.]' \
131                '--hash[Print the service config hash, one per line. Set "service1,service2" for a list of specified services.]' && ret=0
132            ;;
133        (create)
134            _arguments \
135                $opts_help \
136                $opts_force_recreate \
137                $opts_no_recreate \
138                $opts_no_build \
139                "(--no-build)--build[Build images before creating containers.]" \
140                '*:services:__docker-compose_services' && ret=0
141            ;;
142        (down)
143            _arguments \
144                $opts_help \
145                $opts_timeout \
146                "--rmi[Remove images. Type must be one of: 'all': Remove all images used by any service. 'local': Remove only images that don't have a custom tag set by the \`image\` field.]:type:(all local)" \
147                '(-v --volumes)'{-v,--volumes}"[Remove named volumes declared in the \`volumes\` section of the Compose file and anonymous volumes attached to containers.]" \
148                $opts_remove_orphans && ret=0
149            ;;
150        (events)
151            _arguments \
152                $opts_help \
153                '--json[Output events as a stream of json objects]' \
154                '*:services:__docker-compose_services' && ret=0
155            ;;
156        (exec)
157            _arguments \
158                $opts_help \
159                '-d[Detached mode: Run command in the background.]' \
160                '--privileged[Give extended privileges to the process.]' \
161                '(-u --user)'{-u,--user=}'[Run the command as this user.]:username:_users' \
162                '-T[Disable pseudo-tty allocation. By default `docker-compose exec` allocates a TTY.]' \
163                '--index=[Index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \
164                '*'{-e,--env}'[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \
165                '(-w --workdir)'{-w,--workdir=}'[Working directory inside the container]:workdir: ' \
166                '(-):running services:__docker-compose_runningservices' \
167                '(-):command: _command_names -e' \
168                '*::arguments: _normal' && ret=0
169            ;;
170        (help)
171            _arguments ':subcommand:__docker-compose_commands' && ret=0
172            ;;
173    (images)
174        _arguments \
175        $opts_help \
176        '-q[Only display IDs]' \
177        '*:services:__docker-compose_services' && ret=0
178        ;;
179        (kill)
180            _arguments \
181                $opts_help \
182                '-s[SIGNAL to send to the container. Default signal is SIGKILL.]:signal:_signals' \
183                '*:running services:__docker-compose_runningservices' && ret=0
184            ;;
185        (logs)
186            _arguments \
187                $opts_help \
188                '(-f --follow)'{-f,--follow}'[Follow log output]' \
189                $opts_no_color \
190                '--tail=[Number of lines to show from the end of the logs for each container.]:number of lines: ' \
191                '(-t --timestamps)'{-t,--timestamps}'[Show timestamps]' \
192                '*:services:__docker-compose_services' && ret=0
193            ;;
194        (pause)
195            _arguments \
196                $opts_help \
197                '*:running services:__docker-compose_runningservices' && ret=0
198            ;;
199        (port)
200            _arguments \
201                $opts_help \
202                '--protocol=[tcp or udp \[default: tcp\]]:protocol:(tcp udp)' \
203                '--index=[index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \
204                '1:running services:__docker-compose_runningservices' \
205                '2:port:_ports' && ret=0
206            ;;
207        (ps)
208            _arguments \
209                $opts_help \
210                '-q[Only display IDs]' \
211                '--filter KEY=VAL[Filter services by a property]:<filtername>=<value>:' \
212                '*:services:__docker-compose_services' && ret=0
213            ;;
214        (pull)
215            _arguments \
216                $opts_help \
217                '--ignore-pull-failures[Pull what it can and ignores images with pull failures.]' \
218                '--no-parallel[Disable parallel pulling]' \
219                '(-q --quiet)'{-q,--quiet}'[Pull without printing progress information]' \
220                '--include-deps[Also pull services declared as dependencies]' \
221                '*:services:__docker-compose_services_from_image' && ret=0
222            ;;
223        (push)
224            _arguments \
225                $opts_help \
226                '--ignore-push-failures[Push what it can and ignores images with push failures.]' \
227                '*:services:__docker-compose_services' && ret=0
228            ;;
229        (rm)
230            _arguments \
231                $opts_help \
232                '(-f --force)'{-f,--force}"[Don't ask to confirm removal]" \
233                '-v[Remove any anonymous volumes attached to containers]' \
234                '*:stopped services:__docker-compose_stoppedservices' && ret=0
235            ;;
236        (run)
237            _arguments \
238                $opts_help \
239                $opts_no_deps \
240                '-d[Detached mode: Run container in the background, print new container name.]' \
241                '*-e[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \
242                '*'{-l,--label}'[KEY=VAL Add or override a label (can be used multiple times)]:label KEY=VAL: ' \
243                '--entrypoint[Overwrite the entrypoint of the image.]:entry point: ' \
244                '--name=[Assign a name to the container]:name: ' \
245                '(-p --publish)'{-p,--publish=}"[Publish a container's port(s) to the host]" \
246                '--rm[Remove container after run. Ignored in detached mode.]' \
247                "--service-ports[Run command with the service's ports enabled and mapped to the host.]" \
248                '-T[Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.]' \
249                '(-u --user)'{-u,--user=}'[Run as specified username or uid]:username or uid:_users' \
250                '(-v --volume)*'{-v,--volume=}'[Bind mount a volume]:volume: ' \
251                '(-w --workdir)'{-w,--workdir=}'[Working directory inside the container]:workdir: ' \
252                "--use-aliases[Use the services network aliases in the network(s) the container connects to]" \
253                '(-):services:__docker-compose_services' \
254                '(-):command: _command_names -e' \
255                '*::arguments: _normal' && ret=0
256            ;;
257        (scale)
258            _arguments \
259                $opts_help \
260                $opts_timeout \
261                '*:running services:__docker-compose_runningservices' && ret=0
262            ;;
263        (start)
264            _arguments \
265                $opts_help \
266                '*:stopped services:__docker-compose_stoppedservices' && ret=0
267            ;;
268        (stop|restart)
269            _arguments \
270                $opts_help \
271                $opts_timeout \
272                '*:running services:__docker-compose_runningservices' && ret=0
273            ;;
274        (top)
275            _arguments \
276                $opts_help \
277                '*:running services:__docker-compose_runningservices' && ret=0
278            ;;
279        (unpause)
280            _arguments \
281                $opts_help \
282                '*:paused services:__docker-compose_pausedservices' && ret=0
283            ;;
284        (up)
285            _arguments \
286                $opts_help \
287                '(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit and --attach-dependencies.]' \
288                $opts_no_color \
289                $opts_no_deps \
290                $opts_force_recreate \
291                $opts_no_recreate \
292                $opts_no_build \
293                "(--no-build)--build[Build images before starting containers.]" \
294                "(-d)--abort-on-container-exit[Stops all containers if any container was stopped. Incompatible with -d.]" \
295                "(-d)--attach-dependencies[Attach to dependent containers. Incompatible with -d.]" \
296                '(-t --timeout)'{-t,--timeout}"[Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10)]:seconds: " \
297                '--scale[SERVICE=NUM Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.]:service scale SERVICE=NUM: ' \
298                '--exit-code-from=[Return the exit code of the selected service container. Implies --abort-on-container-exit]:service:__docker-compose_services' \
299                $opts_remove_orphans \
300                '*:services:__docker-compose_services' && ret=0
301            ;;
302        (version)
303            _arguments \
304                $opts_help \
305                "--short[Shows only Compose's version number.]" && ret=0
306            ;;
307        (*)
308            _message 'Unknown sub command' && ret=1
309            ;;
310    esac
311
312    return ret
313}
314
315_docker-compose() {
316    # Support for subservices, which allows for `compdef _docker docker-shell=_docker_containers`.
317    # Based on /usr/share/zsh/functions/Completion/Unix/_git without support for `ret`.
318    if [[ $service != docker-compose ]]; then
319        _call_function - _$service
320        return
321    fi
322
323    local curcontext="$curcontext" state line
324    integer ret=1
325    typeset -A opt_args
326
327    local file_description
328
329    if [[ -n ${words[(r)-f]} || -n ${words[(r)--file]} ]] ; then
330        file_description="Specify an override docker-compose file (default: docker-compose.override.yml)"
331    else
332        file_description="Specify an alternate docker-compose file (default: docker-compose.yml)"
333    fi
334
335    _arguments -C \
336        '(- :)'{-h,--help}'[Get help]' \
337        '*'{-f,--file}"[${file_description}]:file:_files -g '*.yml'" \
338        '(-p --project-name)'{-p,--project-name}'[Specify an alternate project name (default: directory name)]:project name:' \
339        '--env-file[Specify an alternate environment file (default: .env)]:env-file:_files' \
340        "--compatibility[If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent]" \
341        '(- :)'{-v,--version}'[Print version and exit]' \
342        '--verbose[Show more output]' \
343        '--log-level=[Set log level]:level:(DEBUG INFO WARNING ERROR CRITICAL)' \
344        '--no-ansi[Do not print ANSI control characters]' \
345        '--ansi=[Control when to print ANSI control characters]:when:(never always auto)' \
346        '(-H --host)'{-H,--host}'[Daemon socket to connect to]:host:' \
347        '--tls[Use TLS; implied by --tlsverify]' \
348        '--tlscacert=[Trust certs signed only by this CA]:ca path:' \
349        '--tlscert=[Path to TLS certificate file]:client cert path:' \
350        '--tlskey=[Path to TLS key file]:tls key path:' \
351        '--tlsverify[Use TLS and verify the remote]' \
352        "--skip-hostname-check[Don't check the daemon's hostname against the name specified in the client certificate (for example if your docker host is an IP address)]" \
353        '(-): :->command' \
354        '(-)*:: :->option-or-argument' && ret=0
355
356    local -a relevant_compose_flags relevant_compose_repeatable_flags relevant_docker_flags compose_options docker_options
357
358    relevant_compose_flags=(
359        "--env-file"
360        "--file" "-f"
361        "--host" "-H"
362        "--project-name" "-p"
363        "--tls"
364        "--tlscacert"
365        "--tlscert"
366        "--tlskey"
367        "--tlsverify"
368        "--skip-hostname-check"
369    )
370
371    relevant_compose_repeatable_flags=(
372        "--file" "-f"
373    )
374
375    relevant_docker_flags=(
376        "--host" "-H"
377        "--tls"
378        "--tlscacert"
379        "--tlscert"
380        "--tlskey"
381        "--tlsverify"
382    )
383
384    for k in "${(@k)opt_args}"; do
385        if [[ -n "${relevant_docker_flags[(r)$k]}" ]]; then
386            docker_options+=$k
387            if [[ -n "$opt_args[$k]" ]]; then
388                docker_options+=$opt_args[$k]
389            fi
390        fi
391        if [[ -n "${relevant_compose_flags[(r)$k]}" ]]; then
392            if [[ -n "${relevant_compose_repeatable_flags[(r)$k]}"  ]]; then
393                values=("${(@s/:/)opt_args[$k]}")
394                for value in $values
395                do
396                    compose_options+=$k
397                    compose_options+=$value
398                done
399            else
400                compose_options+=$k
401                if [[ -n "$opt_args[$k]" ]]; then
402                    compose_options+=$opt_args[$k]
403                fi
404            fi
405        fi
406    done
407
408    case $state in
409        (command)
410            __docker-compose_commands && ret=0
411            ;;
412        (option-or-argument)
413            curcontext=${curcontext%:*:*}:docker-compose-$words[1]:
414            __docker-compose_subcommand && ret=0
415            ;;
416    esac
417
418    return ret
419}
420
421_docker-compose "$@"