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. # 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_config() {
  111. case "$prev" in
  112. --hash)
  113. if [[ $cur == \\* ]] ; then
  114. COMPREPLY=( '\*' )
  115. else
  116. COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") )
  117. fi
  118. return
  119. ;;
  120. esac
  121. COMPREPLY=( $( compgen -W "--hash --help --no-interpolate --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) )
  122. }
  123. _docker_compose_create() {
  124. case "$cur" in
  125. -*)
  126. COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) )
  127. ;;
  128. *)
  129. __docker_compose_complete_services
  130. ;;
  131. esac
  132. }
  133. _docker_compose_docker_compose() {
  134. case "$prev" in
  135. --tlscacert|--tlscert|--tlskey)
  136. _filedir
  137. return
  138. ;;
  139. --file|-f)
  140. _filedir "y?(a)ml"
  141. return
  142. ;;
  143. --log-level)
  144. COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) )
  145. return
  146. ;;
  147. --project-directory)
  148. _filedir -d
  149. return
  150. ;;
  151. --env-file)
  152. _filedir
  153. return
  154. ;;
  155. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  156. return
  157. ;;
  158. esac
  159. case "$cur" in
  160. -*)
  161. COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $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_complete_services
  196. ;;
  197. esac
  198. }
  199. _docker_compose_exec() {
  200. case "$prev" in
  201. --index|--user|-u|--workdir|-w)
  202. return
  203. ;;
  204. esac
  205. case "$cur" in
  206. -*)
  207. COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) )
  208. ;;
  209. *)
  210. __docker_compose_complete_running_services
  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_complete_services
  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_complete_running_services
  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_complete_services
  255. ;;
  256. esac
  257. }
  258. _docker_compose_pause() {
  259. case "$cur" in
  260. -*)
  261. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  262. ;;
  263. *)
  264. __docker_compose_complete_running_services
  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_complete_services
  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 "--all -a --filter --help --quiet -q --services" -- "$cur" ) )
  309. ;;
  310. *)
  311. __docker_compose_complete_services
  312. ;;
  313. esac
  314. }
  315. _docker_compose_pull() {
  316. case "$cur" in
  317. -*)
  318. COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) )
  319. ;;
  320. *)
  321. __docker_compose_complete_services --filter source=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_complete_services
  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_complete_running_services
  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_complete_services
  358. else
  359. __docker_compose_complete_services --filter status=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 "--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" ) )
  378. ;;
  379. *)
  380. __docker_compose_complete_services
  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_services)" -- "$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_complete_services --filter status=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_complete_running_services
  426. ;;
  427. esac
  428. }
  429. _docker_compose_top() {
  430. case "$cur" in
  431. -*)
  432. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  433. ;;
  434. *)
  435. __docker_compose_complete_running_services
  436. ;;
  437. esac
  438. }
  439. _docker_compose_unpause() {
  440. case "$cur" in
  441. -*)
  442. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  443. ;;
  444. *)
  445. __docker_compose_complete_services --filter status=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_complete_services
  457. return
  458. ;;
  459. --scale)
  460. COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$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 --attach-dependencies --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" ) )
  471. ;;
  472. *)
  473. __docker_compose_complete_services
  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. config
  490. create
  491. down
  492. events
  493. exec
  494. help
  495. images
  496. kill
  497. logs
  498. pause
  499. port
  500. ps
  501. pull
  502. push
  503. restart
  504. rm
  505. run
  506. scale
  507. start
  508. stop
  509. top
  510. unpause
  511. up
  512. version
  513. )
  514. # Options for the docker daemon that have to be passed to secondary calls to
  515. # docker-compose executed by this script.
  516. local daemon_boolean_options="
  517. --skip-hostname-check
  518. --tls
  519. --tlsverify
  520. "
  521. local daemon_options_with_args="
  522. --context -c
  523. --env-file
  524. --file -f
  525. --host -H
  526. --project-directory
  527. --project-name -p
  528. --tlscacert
  529. --tlscert
  530. --tlskey
  531. "
  532. # These options are require special treatment when searching the command.
  533. local top_level_options_with_args="
  534. --log-level
  535. "
  536. COMPREPLY=()
  537. local cur prev words cword
  538. _get_comp_words_by_ref -n : cur prev words cword
  539. # search subcommand and invoke its handler.
  540. # special treatment of some top-level options
  541. local command='docker_compose'
  542. local top_level_options=()
  543. local counter=1
  544. while [ $counter -lt $cword ]; do
  545. case "${words[$counter]}" in
  546. $(__docker_compose_to_extglob "$daemon_boolean_options") )
  547. local opt=${words[counter]}
  548. top_level_options+=($opt)
  549. ;;
  550. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  551. local opt=${words[counter]}
  552. local arg=${words[++counter]}
  553. top_level_options+=($opt $arg)
  554. ;;
  555. $(__docker_compose_to_extglob "$top_level_options_with_args") )
  556. (( counter++ ))
  557. ;;
  558. -*)
  559. ;;
  560. *)
  561. command="${words[$counter]}"
  562. break
  563. ;;
  564. esac
  565. (( counter++ ))
  566. done
  567. local completions_func=_docker_compose_${command//-/_}
  568. declare -F $completions_func >/dev/null && $completions_func
  569. eval "$previous_extglob_setting"
  570. return 0
  571. }
  572. eval "$__docker_compose_previous_extglob_setting"
  573. unset __docker_compose_previous_extglob_setting
  574. complete -F _docker_compose docker-compose docker-compose.exe