docker-compose 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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. # Extracts all service names from the compose file.
  74. ___docker_compose_all_services_in_compose_file() {
  75. __docker_compose_q config --services
  76. }
  77. # All services, even those without an existing container
  78. __docker_compose_services_all() {
  79. COMPREPLY=( $(compgen -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") )
  80. }
  81. # All services that are defined by a Dockerfile reference
  82. __docker_compose_services_from_build() {
  83. COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "source=build")" -- "$cur") )
  84. }
  85. # All services that are defined by an image
  86. __docker_compose_services_from_image() {
  87. COMPREPLY=( $(compgen -W "$(__docker_compose_q ps --services --filter "source=image")" -- "$cur") )
  88. }
  89. # The services for which at least one paused container exists
  90. __docker_compose_services_paused() {
  91. names=$(__docker_compose_q ps --services --filter "status=paused")
  92. COMPREPLY=( $(compgen -W "$names" -- "$cur") )
  93. }
  94. # The services for which at least one running container exists
  95. __docker_compose_services_running() {
  96. names=$(__docker_compose_q ps --services --filter "status=running")
  97. COMPREPLY=( $(compgen -W "$names" -- "$cur") )
  98. }
  99. # The services for which at least one stopped container exists
  100. __docker_compose_services_stopped() {
  101. names=$(__docker_compose_q ps --services --filter "status=stopped")
  102. COMPREPLY=( $(compgen -W "$names" -- "$cur") )
  103. }
  104. _docker_compose_build() {
  105. case "$prev" in
  106. --build-arg)
  107. COMPREPLY=( $( compgen -e -- "$cur" ) )
  108. __docker_compose_nospace
  109. return
  110. ;;
  111. esac
  112. case "$cur" in
  113. -*)
  114. COMPREPLY=( $( compgen -W "--build-arg --force-rm --help --memory --no-cache --pull" -- "$cur" ) )
  115. ;;
  116. *)
  117. __docker_compose_services_from_build
  118. ;;
  119. esac
  120. }
  121. _docker_compose_bundle() {
  122. case "$prev" in
  123. --output|-o)
  124. _filedir
  125. return
  126. ;;
  127. esac
  128. COMPREPLY=( $( compgen -W "--push-images --help --output -o" -- "$cur" ) )
  129. }
  130. _docker_compose_config() {
  131. COMPREPLY=( $( compgen -W "--help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) )
  132. }
  133. _docker_compose_create() {
  134. case "$cur" in
  135. -*)
  136. COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) )
  137. ;;
  138. *)
  139. __docker_compose_services_all
  140. ;;
  141. esac
  142. }
  143. _docker_compose_docker_compose() {
  144. case "$prev" in
  145. --tlscacert|--tlscert|--tlskey)
  146. _filedir
  147. return
  148. ;;
  149. --file|-f)
  150. _filedir "y?(a)ml"
  151. return
  152. ;;
  153. --project-directory)
  154. _filedir -d
  155. return
  156. ;;
  157. $(__docker_compose_to_extglob "$top_level_options_with_args") )
  158. return
  159. ;;
  160. esac
  161. case "$cur" in
  162. -*)
  163. COMPREPLY=( $( compgen -W "$top_level_boolean_options $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) )
  164. ;;
  165. *)
  166. COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
  167. ;;
  168. esac
  169. }
  170. _docker_compose_down() {
  171. case "$prev" in
  172. --rmi)
  173. COMPREPLY=( $( compgen -W "all local" -- "$cur" ) )
  174. return
  175. ;;
  176. --timeout|-t)
  177. return
  178. ;;
  179. esac
  180. case "$cur" in
  181. -*)
  182. COMPREPLY=( $( compgen -W "--help --rmi --timeout -t --volumes -v --remove-orphans" -- "$cur" ) )
  183. ;;
  184. esac
  185. }
  186. _docker_compose_events() {
  187. case "$prev" in
  188. --json)
  189. return
  190. ;;
  191. esac
  192. case "$cur" in
  193. -*)
  194. COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) )
  195. ;;
  196. *)
  197. __docker_compose_services_all
  198. ;;
  199. esac
  200. }
  201. _docker_compose_exec() {
  202. case "$prev" in
  203. --index|--user|-u)
  204. return
  205. ;;
  206. esac
  207. case "$cur" in
  208. -*)
  209. COMPREPLY=( $( compgen -W "-d --help --index --privileged -T --user -u" -- "$cur" ) )
  210. ;;
  211. *)
  212. __docker_compose_services_running
  213. ;;
  214. esac
  215. }
  216. _docker_compose_help() {
  217. COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
  218. }
  219. _docker_compose_images() {
  220. case "$cur" in
  221. -*)
  222. COMPREPLY=( $( compgen -W "--help --quiet -q" -- "$cur" ) )
  223. ;;
  224. *)
  225. __docker_compose_services_all
  226. ;;
  227. esac
  228. }
  229. _docker_compose_kill() {
  230. case "$prev" in
  231. -s)
  232. COMPREPLY=( $( compgen -W "SIGHUP SIGINT SIGKILL SIGUSR1 SIGUSR2" -- "$(echo $cur | tr '[:lower:]' '[:upper:]')" ) )
  233. return
  234. ;;
  235. esac
  236. case "$cur" in
  237. -*)
  238. COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) )
  239. ;;
  240. *)
  241. __docker_compose_services_running
  242. ;;
  243. esac
  244. }
  245. _docker_compose_logs() {
  246. case "$prev" in
  247. --tail)
  248. return
  249. ;;
  250. esac
  251. case "$cur" in
  252. -*)
  253. COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) )
  254. ;;
  255. *)
  256. __docker_compose_services_all
  257. ;;
  258. esac
  259. }
  260. _docker_compose_pause() {
  261. case "$cur" in
  262. -*)
  263. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  264. ;;
  265. *)
  266. __docker_compose_services_running
  267. ;;
  268. esac
  269. }
  270. _docker_compose_port() {
  271. case "$prev" in
  272. --protocol)
  273. COMPREPLY=( $( compgen -W "tcp udp" -- "$cur" ) )
  274. return;
  275. ;;
  276. --index)
  277. return;
  278. ;;
  279. esac
  280. case "$cur" in
  281. -*)
  282. COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) )
  283. ;;
  284. *)
  285. __docker_compose_services_all
  286. ;;
  287. esac
  288. }
  289. _docker_compose_ps() {
  290. local key=$(__docker_compose_map_key_of_current_option '--filter')
  291. case "$key" in
  292. source)
  293. COMPREPLY=( $( compgen -W "build image" -- "${cur##*=}" ) )
  294. return
  295. ;;
  296. status)
  297. COMPREPLY=( $( compgen -W "paused restarting running stopped" -- "${cur##*=}" ) )
  298. return
  299. ;;
  300. esac
  301. case "$prev" in
  302. --filter)
  303. COMPREPLY=( $( compgen -W "source status" -S "=" -- "$cur" ) )
  304. __docker_compose_nospace
  305. return;
  306. ;;
  307. esac
  308. case "$cur" in
  309. -*)
  310. COMPREPLY=( $( compgen -W "--help --quiet -q --services --filter" -- "$cur" ) )
  311. ;;
  312. *)
  313. __docker_compose_services_all
  314. ;;
  315. esac
  316. }
  317. _docker_compose_pull() {
  318. case "$cur" in
  319. -*)
  320. COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --parallel --quiet -q" -- "$cur" ) )
  321. ;;
  322. *)
  323. __docker_compose_services_from_image
  324. ;;
  325. esac
  326. }
  327. _docker_compose_push() {
  328. case "$cur" in
  329. -*)
  330. COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) )
  331. ;;
  332. *)
  333. __docker_compose_services_all
  334. ;;
  335. esac
  336. }
  337. _docker_compose_restart() {
  338. case "$prev" in
  339. --timeout|-t)
  340. return
  341. ;;
  342. esac
  343. case "$cur" in
  344. -*)
  345. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  346. ;;
  347. *)
  348. __docker_compose_services_running
  349. ;;
  350. esac
  351. }
  352. _docker_compose_rm() {
  353. case "$cur" in
  354. -*)
  355. COMPREPLY=( $( compgen -W "--force -f --help --stop -s -v" -- "$cur" ) )
  356. ;;
  357. *)
  358. if __docker_compose_has_option "--stop|-s" ; then
  359. __docker_compose_services_all
  360. else
  361. __docker_compose_services_stopped
  362. fi
  363. ;;
  364. esac
  365. }
  366. _docker_compose_run() {
  367. case "$prev" in
  368. -e)
  369. COMPREPLY=( $( compgen -e -- "$cur" ) )
  370. __docker_compose_nospace
  371. return
  372. ;;
  373. --entrypoint|--label|-l|--name|--user|-u|--volume|-v|--workdir|-w)
  374. return
  375. ;;
  376. esac
  377. case "$cur" in
  378. -*)
  379. 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" ) )
  380. ;;
  381. *)
  382. __docker_compose_services_all
  383. ;;
  384. esac
  385. }
  386. _docker_compose_scale() {
  387. case "$prev" in
  388. =)
  389. COMPREPLY=("$cur")
  390. return
  391. ;;
  392. --timeout|-t)
  393. return
  394. ;;
  395. esac
  396. case "$cur" in
  397. -*)
  398. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  399. ;;
  400. *)
  401. COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") )
  402. __docker_compose_nospace
  403. ;;
  404. esac
  405. }
  406. _docker_compose_start() {
  407. case "$cur" in
  408. -*)
  409. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  410. ;;
  411. *)
  412. __docker_compose_services_stopped
  413. ;;
  414. esac
  415. }
  416. _docker_compose_stop() {
  417. case "$prev" in
  418. --timeout|-t)
  419. return
  420. ;;
  421. esac
  422. case "$cur" in
  423. -*)
  424. COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) )
  425. ;;
  426. *)
  427. __docker_compose_services_running
  428. ;;
  429. esac
  430. }
  431. _docker_compose_top() {
  432. case "$cur" in
  433. -*)
  434. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  435. ;;
  436. *)
  437. __docker_compose_services_running
  438. ;;
  439. esac
  440. }
  441. _docker_compose_unpause() {
  442. case "$cur" in
  443. -*)
  444. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  445. ;;
  446. *)
  447. __docker_compose_services_paused
  448. ;;
  449. esac
  450. }
  451. _docker_compose_up() {
  452. case "$prev" in
  453. =)
  454. COMPREPLY=("$cur")
  455. return
  456. ;;
  457. --exit-code-from)
  458. __docker_compose_services_all
  459. return
  460. ;;
  461. --scale)
  462. COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") )
  463. __docker_compose_nospace
  464. return
  465. ;;
  466. --timeout|-t)
  467. return
  468. ;;
  469. esac
  470. case "$cur" in
  471. -*)
  472. COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --build -d --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" ) )
  473. ;;
  474. *)
  475. __docker_compose_services_all
  476. ;;
  477. esac
  478. }
  479. _docker_compose_version() {
  480. case "$cur" in
  481. -*)
  482. COMPREPLY=( $( compgen -W "--short" -- "$cur" ) )
  483. ;;
  484. esac
  485. }
  486. _docker_compose() {
  487. local previous_extglob_setting=$(shopt -p extglob)
  488. shopt -s extglob
  489. local commands=(
  490. build
  491. bundle
  492. config
  493. create
  494. down
  495. events
  496. exec
  497. help
  498. images
  499. kill
  500. logs
  501. pause
  502. port
  503. ps
  504. pull
  505. push
  506. restart
  507. rm
  508. run
  509. scale
  510. start
  511. stop
  512. top
  513. unpause
  514. up
  515. version
  516. )
  517. # Options for the docker daemon that have to be passed to secondary calls to
  518. # docker-compose executed by this script.
  519. # Other global otions that are not relevant for secondary calls are defined in
  520. # `_docker_compose_docker_compose`.
  521. local top_level_boolean_options="
  522. --skip-hostname-check
  523. --tls
  524. --tlsverify
  525. "
  526. local top_level_options_with_args="
  527. --file -f
  528. --host -H
  529. --project-directory
  530. --project-name -p
  531. --tlscacert
  532. --tlscert
  533. --tlskey
  534. "
  535. COMPREPLY=()
  536. local cur prev words cword
  537. _get_comp_words_by_ref -n : cur prev words cword
  538. # search subcommand and invoke its handler.
  539. # special treatment of some top-level options
  540. local command='docker_compose'
  541. local top_level_options=()
  542. local counter=1
  543. while [ $counter -lt $cword ]; do
  544. case "${words[$counter]}" in
  545. $(__docker_compose_to_extglob "$top_level_boolean_options") )
  546. local opt=${words[counter]}
  547. top_level_options+=($opt)
  548. ;;
  549. $(__docker_compose_to_extglob "$top_level_options_with_args") )
  550. local opt=${words[counter]}
  551. local arg=${words[++counter]}
  552. top_level_options+=($opt $arg)
  553. ;;
  554. -*)
  555. ;;
  556. *)
  557. command="${words[$counter]}"
  558. break
  559. ;;
  560. esac
  561. (( counter++ ))
  562. done
  563. local completions_func=_docker_compose_${command//-/_}
  564. declare -F $completions_func >/dev/null && $completions_func
  565. eval "$previous_extglob_setting"
  566. return 0
  567. }
  568. eval "$__docker_compose_previous_extglob_setting"
  569. unset __docker_compose_previous_extglob_setting
  570. complete -F _docker_compose docker-compose docker-compose.exe