docker-compose 13 KB

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