docker-compose 13 KB

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