docker-compose 10.0 KB

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