docker-compose 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  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. esac
  98. case "$cur" in
  99. -*)
  100. COMPREPLY=( $( compgen -W "--build-arg --compress --force-rm --help --memory --no-cache --pull --parallel" -- "$cur" ) )
  101. ;;
  102. *)
  103. __docker_compose_complete_services --filter source=build
  104. ;;
  105. esac
  106. }
  107. _docker_compose_bundle() {
  108. case "$prev" in
  109. --output|-o)
  110. _filedir
  111. return
  112. ;;
  113. esac
  114. COMPREPLY=( $( compgen -W "--push-images --help --output -o" -- "$cur" ) )
  115. }
  116. _docker_compose_config() {
  117. case "$prev" in
  118. --hash)
  119. if [[ $cur == \\* ]] ; then
  120. COMPREPLY=( '\*' )
  121. else
  122. COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") )
  123. fi
  124. return
  125. ;;
  126. esac
  127. COMPREPLY=( $( compgen -W "--hash --help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) )
  128. }
  129. _docker_compose_create() {
  130. case "$cur" in
  131. -*)
  132. COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) )
  133. ;;
  134. *)
  135. __docker_compose_complete_services
  136. ;;
  137. esac
  138. }
  139. _docker_compose_docker_compose() {
  140. case "$prev" in
  141. --tlscacert|--tlscert|--tlskey)
  142. _filedir
  143. return
  144. ;;
  145. --file|-f)
  146. _filedir "y?(a)ml"
  147. return
  148. ;;
  149. --log-level)
  150. COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) )
  151. return
  152. ;;
  153. --project-directory)
  154. _filedir -d
  155. return
  156. ;;
  157. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  158. return
  159. ;;
  160. esac
  161. case "$cur" in
  162. -*)
  163. COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $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_complete_services
  198. ;;
  199. esac
  200. }
  201. _docker_compose_exec() {
  202. case "$prev" in
  203. --index|--user|-u|--workdir|-w)
  204. return
  205. ;;
  206. esac
  207. case "$cur" in
  208. -*)
  209. COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) )
  210. ;;
  211. *)
  212. __docker_compose_complete_running_services
  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_complete_services
  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_complete_running_services
  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_complete_services
  257. ;;
  258. esac
  259. }
  260. _docker_compose_pause() {
  261. case "$cur" in
  262. -*)
  263. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  264. ;;
  265. *)
  266. __docker_compose_complete_running_services
  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_complete_services
  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 "--all -a --filter --help --quiet -q --services" -- "$cur" ) )
  311. ;;
  312. *)
  313. __docker_compose_complete_services
  314. ;;
  315. esac
  316. }
  317. _docker_compose_pull() {
  318. case "$cur" in
  319. -*)
  320. COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) )
  321. ;;
  322. *)
  323. __docker_compose_complete_services --filter source=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_complete_services
  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_complete_running_services
  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_complete_services
  360. else
  361. __docker_compose_complete_services --filter status=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 "--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" ) )
  380. ;;
  381. *)
  382. __docker_compose_complete_services
  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_services)" -- "$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_complete_services --filter status=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_complete_running_services
  428. ;;
  429. esac
  430. }
  431. _docker_compose_top() {
  432. case "$cur" in
  433. -*)
  434. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  435. ;;
  436. *)
  437. __docker_compose_complete_running_services
  438. ;;
  439. esac
  440. }
  441. _docker_compose_unpause() {
  442. case "$cur" in
  443. -*)
  444. COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
  445. ;;
  446. *)
  447. __docker_compose_complete_services --filter status=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_complete_services
  459. return
  460. ;;
  461. --scale)
  462. COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$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 --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" ) )
  473. ;;
  474. *)
  475. __docker_compose_complete_services
  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. local daemon_boolean_options="
  520. --skip-hostname-check
  521. --tls
  522. --tlsverify
  523. "
  524. local daemon_options_with_args="
  525. --file -f
  526. --host -H
  527. --project-directory
  528. --project-name -p
  529. --tlscacert
  530. --tlscert
  531. --tlskey
  532. "
  533. # These options are require special treatment when searching the command.
  534. local top_level_options_with_args="
  535. --log-level
  536. "
  537. COMPREPLY=()
  538. local cur prev words cword
  539. _get_comp_words_by_ref -n : cur prev words cword
  540. # search subcommand and invoke its handler.
  541. # special treatment of some top-level options
  542. local command='docker_compose'
  543. local top_level_options=()
  544. local counter=1
  545. while [ $counter -lt $cword ]; do
  546. case "${words[$counter]}" in
  547. $(__docker_compose_to_extglob "$daemon_boolean_options") )
  548. local opt=${words[counter]}
  549. top_level_options+=($opt)
  550. ;;
  551. $(__docker_compose_to_extglob "$daemon_options_with_args") )
  552. local opt=${words[counter]}
  553. local arg=${words[++counter]}
  554. top_level_options+=($opt $arg)
  555. ;;
  556. $(__docker_compose_to_extglob "$top_level_options_with_args") )
  557. (( counter++ ))
  558. ;;
  559. -*)
  560. ;;
  561. *)
  562. command="${words[$counter]}"
  563. break
  564. ;;
  565. esac
  566. (( counter++ ))
  567. done
  568. local completions_func=_docker_compose_${command//-/_}
  569. declare -F $completions_func >/dev/null && $completions_func
  570. eval "$previous_extglob_setting"
  571. return 0
  572. }
  573. eval "$__docker_compose_previous_extglob_setting"
  574. unset __docker_compose_previous_extglob_setting
  575. complete -F _docker_compose docker-compose docker-compose.exe