docker-compose 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. #!/bin/bash
  2. #
  3. # bash completion for docker-compose
  4. #
  5. # This work is based on the completion for the docker command.
  6. #
  7. # This script provides completion of:
  8. # - commands and their options
  9. # - service names
  10. # - filepaths
  11. #
  12. # To enable the completions either:
  13. # - place this file in /etc/bash_completion.d
  14. # or
  15. # - copy this file to e.g. ~/.docker-compose-completion.sh and add the line
  16. # below to your .bashrc after bash completion features are loaded
  17. # . ~/.docker-compose-completion.sh
  18. __docker_compose_previous_extglob_setting=$(shopt -p extglob)
  19. shopt -s extglob
  20. __docker_compose_q() {
  21. docker-compose 2>/dev/null "${top_level_options[@]}" "$@"
  22. }
  23. # Transforms a multiline list of strings into a single line string
  24. # with the words separated by "|".
  25. __docker_compose_to_alternatives() {
  26. local parts=( $1 )
  27. local IFS='|'
  28. echo "${parts[*]}"
  29. }
  30. # Transforms a multiline list of options into an extglob pattern
  31. # suitable for use in case statements.
  32. __docker_compose_to_extglob() {
  33. local extglob=$( __docker_compose_to_alternatives "$1" )
  34. echo "@($extglob)"
  35. }
  36. # Determines whether the option passed as the first argument exist on
  37. # the commandline. The option may be a pattern, e.g. `--force|-f`.
  38. __docker_compose_has_option() {
  39. local pattern="$1"
  40. for (( i=2; i < $cword; ++i)); do
  41. if [[ ${words[$i]} =~ ^($pattern)$ ]] ; then
  42. return 0
  43. fi
  44. done
  45. return 1
  46. }
  47. # Returns `key` if we are currently completing the value of a map option (`key=value`)
  48. # which matches the extglob passed in as an argument.
  49. # This function is needed for key-specific completions.
  50. __docker_compose_map_key_of_current_option() {
  51. local glob="$1"
  52. local key glob_pos
  53. if [ "$cur" = "=" ] ; then # key= case
  54. key="$prev"
  55. glob_pos=$((cword - 2))
  56. elif [[ $cur == *=* ]] ; then # key=value case (OSX)
  57. key=${cur%=*}
  58. glob_pos=$((cword - 1))
  59. elif [ "$prev" = "=" ] ; then
  60. key=${words[$cword - 2]} # key=value case
  61. glob_pos=$((cword - 3))
  62. else
  63. return
  64. fi
  65. [ "${words[$glob_pos]}" = "=" ] && ((glob_pos--)) # --option=key=value syntax
  66. [[ ${words[$glob_pos]} == @($glob) ]] && echo "$key"
  67. }
  68. # suppress trailing whitespace
  69. __docker_compose_nospace() {
  70. # compopt is not available in ancient bash versions
  71. type compopt &>/dev/null && compopt -o nospace
  72. }
  73. # Outputs a list of all defined services, regardless of their running state.
  74. # Arguments for `docker-compose ps` may be passed in order to filter the service list,
  75. # e.g. `status=running`.
  76. __docker_compose_services() {
  77. __docker_compose_q ps --services "$@"
  78. }
  79. # Applies completion of services based on the current value of `$cur`.
  80. # Arguments for `docker-compose ps` may be passed in order to filter the service list,
  81. # see `__docker_compose_services`.
  82. __docker_compose_complete_services() {
  83. COMPREPLY=( $(compgen -W "$(__docker_compose_services "$@")" -- "$cur") )
  84. }
  85. # The services for which at least one running container exists
  86. __docker_compose_complete_running_services() {
  87. local names=$(__docker_compose_services --filter status=running)
  88. COMPREPLY=( $(compgen -W "$names" -- "$cur") )
  89. }
  90. _docker_compose_build() {
  91. case "$prev" in
  92. --build-arg)
  93. COMPREPLY=( $( compgen -e -- "$cur" ) )
  94. __docker_compose_nospace
  95. return
  96. ;;
  97. --memory|-m)
  98. return
  99. ;;
  100. esac
  101. case "$cur" in
  102. -*)
  103. COMPREPLY=( $( compgen -W "--build-arg --compress --force-rm --help --memory -m --no-cache --no-rm --pull --parallel -q --quiet" -- "$cur" ) )
  104. ;;
  105. *)
  106. __docker_compose_complete_services --filter source=build
  107. ;;
  108. esac
  109. }
  110. _docker_compose_bundle() {
  111. case "$prev" in
  112. --output|-o)
  113. _filedir
  114. return
  115. ;;
  116. esac
  117. COMPREPLY=( $( compgen -W "--push-images --help --output -o" -- "$cur" ) )
  118. }
  119. _docker_compose_config() {
  120. case "$prev" in
  121. --hash)
  122. if [[ $cur == \\* ]] ; then
  123. COMPREPLY=( '\*' )
  124. else
  125. COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") )
  126. fi
  127. return
  128. ;;
  129. esac
  130. COMPREPLY=( $( compgen -W "--hash --help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) )
  131. }
  132. _docker_compose_create() {
  133. case "$cur" in
  134. -*)
  135. COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) )
  136. ;;
  137. *)
  138. __docker_compose_complete_services
  139. ;;
  140. esac
  141. }
  142. _docker_compose_docker_compose() {
  143. case "$prev" in
  144. --tlscacert|--tlscert|--tlskey)
  145. _filedir
  146. return
  147. ;;
  148. --file|-f)
  149. _filedir "y?(a)ml"
  150. return
  151. ;;
  152. --log-level)
  153. COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) )
  154. return
  155. ;;
  156. --project-directory)
  157. _filedir -d
  158. return
  159. ;;
  160. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  161. return
  162. ;;
  163. esac
  164. case "$cur" in
  165. -*)
  166. COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) )
  167. ;;
  168. *)
  169. COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
  170. ;;
  171. esac
  172. }
  173. _docker_compose_down() {
  174. case "$prev" in
  175. --rmi)
  176. COMPREPLY=( $( compgen -W "all local" -- "$cur" ) )
  177. return
  178. ;;
  179. --timeout|-t)
  180. return
  181. ;;
  182. esac
  183. case "$cur" in
  184. -*)
  185. COMPREPLY=( $( compgen -W "--help --rmi --timeout -t --volumes -v --remove-orphans" -- "$cur" ) )
  186. ;;
  187. esac
  188. }
  189. _docker_compose_events() {
  190. case "$prev" in
  191. --json)
  192. return
  193. ;;
  194. esac
  195. case "$cur" in
  196. -*)
  197. COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) )
  198. ;;
  199. *)
  200. __docker_compose_complete_services
  201. ;;
  202. esac
  203. }
  204. _docker_compose_exec() {
  205. case "$prev" in
  206. --index|--user|-u|--workdir|-w)
  207. return
  208. ;;
  209. esac
  210. case "$cur" in
  211. -*)
  212. COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) )
  213. ;;
  214. *)
  215. __docker_compose_complete_running_services
  216. ;;
  217. esac
  218. }
  219. _docker_compose_help() {
  220. COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
  221. }
  222. _docker_compose_images() {
  223. case "$cur" in
  224. -*)
  225. COMPREPLY=( $( compgen -W "--help --quiet -q" -- "$cur" ) )
  226. ;;
  227. *)
  228. __docker_compose_complete_services
  229. ;;
  230. esac
  231. }
  232. _docker_compose_kill() {
  233. case "$prev" in
  234. -s)
  235. COMPREPLY=( $( compgen -W "SIGHUP SIGINT SIGKILL SIGUSR1 SIGUSR2" -- "$(echo $cur | tr '[:lower:]' '[:upper:]')" ) )
  236. return
  237. ;;
  238. esac
  239. case "$cur" in
  240. -*)
  241. COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) )
  242. ;;
  243. *)
  244. __docker_compose_complete_running_services
  245. ;;
  246. esac
  247. }
  248. _docker_compose_logs() {
  249. case "$prev" in
  250. --tail)
  251. return
  252. ;;
  253. esac
  254. case "$cur" in
  255. -*)
  256. COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) )
  257. ;;
  258. *)
  259. __docker_compose_complete_services
  260. ;;
  261. esac
  262. }
  263. _docker_compose_pause() {
  264. case "$cur" in
  265. -*)
  266. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  267. ;;
  268. *)
  269. __docker_compose_complete_running_services
  270. ;;
  271. esac
  272. }
  273. _docker_compose_port() {
  274. case "$prev" in
  275. --protocol)
  276. COMPREPLY=( $( compgen -W "tcp udp" -- "$cur" ) )
  277. return;
  278. ;;
  279. --index)
  280. return;
  281. ;;
  282. esac
  283. case "$cur" in
  284. -*)
  285. COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) )
  286. ;;
  287. *)
  288. __docker_compose_complete_services
  289. ;;
  290. esac
  291. }
  292. _docker_compose_ps() {
  293. local key=$(__docker_compose_map_key_of_current_option '--filter')
  294. case "$key" in
  295. source)
  296. COMPREPLY=( $( compgen -W "build image" -- "${cur##*=}" ) )
  297. return
  298. ;;
  299. status)
  300. COMPREPLY=( $( compgen -W "paused restarting running stopped" -- "${cur##*=}" ) )
  301. return
  302. ;;
  303. esac
  304. case "$prev" in
  305. --filter)
  306. COMPREPLY=( $( compgen -W "source status" -S "=" -- "$cur" ) )
  307. __docker_compose_nospace
  308. return;
  309. ;;
  310. esac
  311. case "$cur" in
  312. -*)
  313. COMPREPLY=( $( compgen -W "--all -a --filter --help --quiet -q --services" -- "$cur" ) )
  314. ;;
  315. *)
  316. __docker_compose_complete_services
  317. ;;
  318. esac
  319. }
  320. _docker_compose_pull() {
  321. case "$cur" in
  322. -*)
  323. COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) )
  324. ;;
  325. *)
  326. __docker_compose_complete_services --filter source=image
  327. ;;
  328. esac
  329. }
  330. _docker_compose_push() {
  331. case "$cur" in
  332. -*)
  333. COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) )
  334. ;;
  335. *)
  336. __docker_compose_complete_services
  337. ;;
  338. esac
  339. }
  340. _docker_compose_restart() {
  341. case "$prev" in
  342. --timeout|-t)
  343. return
  344. ;;
  345. esac
  346. case "$cur" in
  347. -*)
  348. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  349. ;;
  350. *)
  351. __docker_compose_complete_running_services
  352. ;;
  353. esac
  354. }
  355. _docker_compose_rm() {
  356. case "$cur" in
  357. -*)
  358. COMPREPLY=( $( compgen -W "--force -f --help --stop -s -v" -- "$cur" ) )
  359. ;;
  360. *)
  361. if __docker_compose_has_option "--stop|-s" ; then
  362. __docker_compose_complete_services
  363. else
  364. __docker_compose_complete_services --filter status=stopped
  365. fi
  366. ;;
  367. esac
  368. }
  369. _docker_compose_run() {
  370. case "$prev" in
  371. -e)
  372. COMPREPLY=( $( compgen -e -- "$cur" ) )
  373. __docker_compose_nospace
  374. return
  375. ;;
  376. --entrypoint|--label|-l|--name|--user|-u|--volume|-v|--workdir|-w)
  377. return
  378. ;;
  379. esac
  380. case "$cur" in
  381. -*)
  382. 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" ) )
  383. ;;
  384. *)
  385. __docker_compose_complete_services
  386. ;;
  387. esac
  388. }
  389. _docker_compose_scale() {
  390. case "$prev" in
  391. =)
  392. COMPREPLY=("$cur")
  393. return
  394. ;;
  395. --timeout|-t)
  396. return
  397. ;;
  398. esac
  399. case "$cur" in
  400. -*)
  401. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  402. ;;
  403. *)
  404. COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") )
  405. __docker_compose_nospace
  406. ;;
  407. esac
  408. }
  409. _docker_compose_start() {
  410. case "$cur" in
  411. -*)
  412. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  413. ;;
  414. *)
  415. __docker_compose_complete_services --filter status=stopped
  416. ;;
  417. esac
  418. }
  419. _docker_compose_stop() {
  420. case "$prev" in
  421. --timeout|-t)
  422. return
  423. ;;
  424. esac
  425. case "$cur" in
  426. -*)
  427. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  428. ;;
  429. *)
  430. __docker_compose_complete_running_services
  431. ;;
  432. esac
  433. }
  434. _docker_compose_top() {
  435. case "$cur" in
  436. -*)
  437. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  438. ;;
  439. *)
  440. __docker_compose_complete_running_services
  441. ;;
  442. esac
  443. }
  444. _docker_compose_unpause() {
  445. case "$cur" in
  446. -*)
  447. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  448. ;;
  449. *)
  450. __docker_compose_complete_services --filter status=paused
  451. ;;
  452. esac
  453. }
  454. _docker_compose_up() {
  455. case "$prev" in
  456. =)
  457. COMPREPLY=("$cur")
  458. return
  459. ;;
  460. --exit-code-from)
  461. __docker_compose_complete_services
  462. return
  463. ;;
  464. --scale)
  465. COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") )
  466. __docker_compose_nospace
  467. return
  468. ;;
  469. --timeout|-t)
  470. return
  471. ;;
  472. esac
  473. case "$cur" in
  474. -*)
  475. 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" ) )
  476. ;;
  477. *)
  478. __docker_compose_complete_services
  479. ;;
  480. esac
  481. }
  482. _docker_compose_version() {
  483. case "$cur" in
  484. -*)
  485. COMPREPLY=( $( compgen -W "--short" -- "$cur" ) )
  486. ;;
  487. esac
  488. }
  489. _docker_compose() {
  490. local previous_extglob_setting=$(shopt -p extglob)
  491. shopt -s extglob
  492. local commands=(
  493. build
  494. bundle
  495. config
  496. create
  497. down
  498. events
  499. exec
  500. help
  501. images
  502. kill
  503. logs
  504. pause
  505. port
  506. ps
  507. pull
  508. push
  509. restart
  510. rm
  511. run
  512. scale
  513. start
  514. stop
  515. top
  516. unpause
  517. up
  518. version
  519. )
  520. # Options for the docker daemon that have to be passed to secondary calls to
  521. # docker-compose executed by this script.
  522. local daemon_boolean_options="
  523. --skip-hostname-check
  524. --tls
  525. --tlsverify
  526. "
  527. local daemon_options_with_args="
  528. --file -f
  529. --host -H
  530. --project-directory
  531. --project-name -p
  532. --tlscacert
  533. --tlscert
  534. --tlskey
  535. "
  536. # These options are require special treatment when searching the command.
  537. local top_level_options_with_args="
  538. --log-level
  539. "
  540. COMPREPLY=()
  541. local cur prev words cword
  542. _get_comp_words_by_ref -n : cur prev words cword
  543. # search subcommand and invoke its handler.
  544. # special treatment of some top-level options
  545. local command='docker_compose'
  546. local top_level_options=()
  547. local counter=1
  548. while [ $counter -lt $cword ]; do
  549. case "${words[$counter]}" in
  550. $(__docker_compose_to_extglob "$daemon_boolean_options") )
  551. local opt=${words[counter]}
  552. top_level_options+=($opt)
  553. ;;
  554. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  555. local opt=${words[counter]}
  556. local arg=${words[++counter]}
  557. top_level_options+=($opt $arg)
  558. ;;
  559. $(__docker_compose_to_extglob "$top_level_options_with_args") )
  560. (( counter++ ))
  561. ;;
  562. -*)
  563. ;;
  564. *)
  565. command="${words[$counter]}"
  566. break
  567. ;;
  568. esac
  569. (( counter++ ))
  570. done
  571. local completions_func=_docker_compose_${command//-/_}
  572. declare -F $completions_func >/dev/null && $completions_func
  573. eval "$previous_extglob_setting"
  574. return 0
  575. }
  576. eval "$__docker_compose_previous_extglob_setting"
  577. unset __docker_compose_previous_extglob_setting
  578. complete -F _docker_compose docker-compose docker-compose.exe