docker-compose 11 KB

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