docker-compose 13 KB

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