You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
7.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. #!/bin/bash
  2. ## Bash wrap script to launch the ``compose`` docker with right options.
  3. ##
  4. ##
  5. ## Launcher
  6. ## - should need minimum requirement to run
  7. ## - no shell libs
  8. ##
  9. get_os() {
  10. local uname_output machine
  11. uname_output="$(uname -s)"
  12. case "${uname_output}" in
  13. Linux*) machine=linux;;
  14. Darwin*) machine=mac;;
  15. CYGWIN*) machine=cygwin;;
  16. MINGW*) machine=mingw;;
  17. *) machine="UNKNOWN:${uname_output}"
  18. esac
  19. echo "${machine}"
  20. }
  21. read-0() {
  22. local eof= IFS=''
  23. while [ "$1" ]; do
  24. read -r -d '' -- "$1" || eof=1
  25. shift
  26. done
  27. [ -z "$eof" ]
  28. }
  29. read-0a() {
  30. local eof= IFS=''
  31. while [ "$1" ]; do
  32. IFS='' read -r -d $'\n' -- "$1" || eof=1
  33. shift
  34. done
  35. [ -z "$eof" ]
  36. }
  37. p0() {
  38. printf "%s\0" "$@"
  39. }
  40. list_compose_vars() {
  41. while read-0a def; do
  42. def="${def##* }"
  43. def="${def%=*}"
  44. p0 "$def"
  45. done < <(declare -p | grep "^declare -x COMPOSE_[A-Z_]\+=\"")
  46. }
  47. get_running_compose_containers() {
  48. ## XXXvlab: docker bug: there will be a final newline anyway
  49. docker ps --filter label="compose.service" --format='{{.ID}}'
  50. }
  51. get_volumes_for_container() {
  52. local container="$1"
  53. docker inspect \
  54. --format '{{range $mount := .Mounts}}{{$mount.Source}}{{"\x00"}}{{$mount.Destination}}{{"\x00"}}{{end}}' \
  55. "$container"
  56. }
  57. is_volume_used() {
  58. local volume="$1"
  59. while read container_id; do
  60. while read-0 src dst; do
  61. [ "$src" == "$volume" ] && return 0
  62. done < <(get_volumes_for_container "$container_id")
  63. done < <(get_running_compose_containers)
  64. return 1
  65. }
  66. clean_unused_sessions() {
  67. for f in "$COMPOSE_VAR/sessions/"*; do
  68. [ -e "$f" ] || continue
  69. is_volume_used "$f" && continue
  70. rm -f "$f"
  71. done
  72. }
  73. relink_subdirs() {
  74. local dir
  75. for dir in "$@"; do
  76. [ -L "$dir" ] || continue
  77. target=$(realpath "$dir")
  78. [ -d "$target" ] || continue
  79. docker_run_opts+=("-v" "$target:$dir")
  80. [ -e "$dir/metadata.yml" ] && continue
  81. relink_subdirs "$dir"/*
  82. done
  83. }
  84. mk_docker_run_options() {
  85. docker_run_opts=("-v" "/var/run/docker.sock:/var/run/docker.sock")
  86. ## CACHE/DATA DIRS
  87. docker_run_opts+=("-v" "$COMPOSE_VAR:/var/lib/compose")
  88. docker_run_opts+=("-v" "$COMPOSE_CACHE:/var/cache/compose")
  89. docker_run_opts+=("-v" "$TZ_PATH:/etc/timezone:ro")
  90. ## current dir
  91. if parent=$(while true; do
  92. [ -e "./compose.yml" ] && {
  93. echo "$PWD"
  94. exit 0
  95. }
  96. [ "$PWD" == "/" ] && exit 1
  97. cd ..
  98. done
  99. ); then
  100. docker_path=$COMPOSE_VAR/root/$(basename "$parent")
  101. docker_run_opts+=("-v" "$parent:$docker_path:ro" \
  102. "-w" "$docker_path")
  103. fi
  104. ##
  105. ## Load config files
  106. ##
  107. if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then
  108. ## XXXvlab: should provide YML config opportunities in possible parent dirs ?
  109. ## userdir ? and global /etc/compose.yml ?
  110. for cfgfile in "${compose_config_files[@]}"; do
  111. [ -e "$cfgfile" ] || continue
  112. docker_run_opts+=("-v" "$cfgfile:$cfgfile:ro")
  113. . "$cfgfile"
  114. done
  115. else
  116. docker_run_opts+=("-e" "DISABLE_SYSTEM_CONFIG_FILE=$DISABLE_SYSTEM_CONFIG_FILE")
  117. fi
  118. ##
  119. ## Checking vars
  120. ##
  121. ## CHARM_STORE
  122. CHARM_STORE=${CHARM_STORE:-/srv/charm-store}
  123. [ -L "$CHARM_STORE" ] && {
  124. CHARM_STORE=$(readlink -f "$CHARM_STORE") || exit 1
  125. }
  126. docker_run_opts+=(
  127. "-v" "$CHARM_STORE:/srv/charm-store:ro"
  128. "-e" "CHARM_STORE=/srv/charm-store"
  129. "-e" "HOST_CHARM_STORE=$CHARM_STORE"
  130. )
  131. relink_subdirs /srv/charm-store/*
  132. ## DEFAULT_COMPOSE_FILE
  133. if [ "${DEFAULT_COMPOSE_FILE+x}" ]; then
  134. DEFAULT_COMPOSE_FILE=$(realpath "$DEFAULT_COMPOSE_FILE")
  135. dirname=$(dirname "$DEFAULT_COMPOSE_FILE")/
  136. if [ -e "${DEFAULT_COMPOSE_FILE}" ]; then
  137. docker_run_opts+=("-v" "$dirname:$dirname:ro")
  138. fi
  139. fi
  140. ## COMPOSE_YML_FILE
  141. if [ "${COMPOSE_YML_FILE+x}" ]; then
  142. if [ -e "${COMPOSE_YML_FILE}" ]; then
  143. docker_run_opts+=(
  144. "-v" "$COMPOSE_YML_FILE:/tmp/compose.yml:ro"
  145. "-e" "COMPOSE_YML_FILE=/tmp/compose.yml"
  146. "-e" "HOST_COMPOSE_YML_FILE=/tmp/compose.yml"
  147. )
  148. fi
  149. fi
  150. ## DATASTORE
  151. DATASTORE=${DATASTORE:-/srv/datastore/data}
  152. docker_run_opts+=(
  153. "-v" "$DATASTORE:/srv/datastore/data:rw"
  154. "-e" "DATASTORE=/srv/datastore/data"
  155. "-e" "HOST_DATASTORE=$DATASTORE"
  156. )
  157. ## CONFIGSTORE
  158. CONFIGSTORE=${CONFIGSTORE:-/srv/datastore/config}
  159. docker_run_opts+=(
  160. "-v" "$CONFIGSTORE:/srv/datastore/config:rw"
  161. "-e" "CONFIGSTORE=/srv/datastore/config"
  162. "-e" "HOST_CONFIGSTORE=$CONFIGSTORE"
  163. )
  164. docker_run_opts+=("-v" "$HOME/.docker:/root/.docker")
  165. COMPOSE_DOCKER_IMAGE=${COMPOSE_DOCKER_IMAGE:-docker.0k.io/compose}
  166. docker_run_opts+=("-e" "COMPOSE_DOCKER_IMAGE=$COMPOSE_DOCKER_IMAGE")
  167. COMPOSE_LAUNCHER_BIN=$(readlink -f "${BASH_SOURCE[0]}")
  168. docker_run_opts+=("-v" "$COMPOSE_LAUNCHER_BIN:/usr/local/bin/compose")
  169. while read-0 var; do
  170. case "$var" in
  171. COMPOSE_YML_FILE|COMPOSE_LAUNCHER_BIN|COMPOSE_DOCKER_IMAGE|\
  172. COMPOSE_LAUNCHER_OPTS|COMPOSE_VAR|COMPOSE_CACHE)
  173. :
  174. ;;
  175. *)
  176. docker_run_opts+=("-e" "$var=${!var}")
  177. ;;
  178. esac
  179. done < <(list_compose_vars)
  180. filename=$(mktemp -p /tmp/ -t launch_opts-XXXXXXXXXXXXXXXX)
  181. {
  182. printf "%s\0" "${docker_run_opts[@]}"
  183. } > "$filename"
  184. sha=$(sha256sum "$filename")
  185. sha=${sha:0:64}
  186. dest="$COMPOSE_VAR/sessions/$sha"
  187. {
  188. printf "%s\0" "-v" "$dest:$dest"
  189. printf "%s\0" "-e" "COMPOSE_LAUNCHER_OPTS=$dest"
  190. printf "%s\0" "-e" "COMPOSE_LAUNCHER_BIN=$COMPOSE_LAUNCHER_BIN"
  191. } >> "$filename"
  192. mkdir -p "$COMPOSE_VAR"/sessions
  193. mv "$filename" "$dest"
  194. echo "$dest"
  195. }
  196. run() {
  197. local os docker_run_opts
  198. ## Order matters, files get to override vars
  199. compose_config_files=(
  200. /etc/default/charm
  201. /etc/default/datastore
  202. /etc/compose.conf
  203. /etc/compose.local.conf
  204. /etc/default/compose
  205. ~/.compose/etc/local.conf
  206. /etc/compose/local.conf
  207. )
  208. os=$(get_os)
  209. case "$os" in
  210. linux)
  211. COMPOSE_VAR=/var/lib/compose
  212. COMPOSE_CACHE=/var/cache/compose
  213. TZ_PATH=/etc/timezone
  214. ;;
  215. mac)
  216. if ! [ -e "$HOME/.compose/etc/timezone" ]; then
  217. TZ=${TZ:-"Europe/Paris"}
  218. echo "$TZ" > "$HOME"/.compose/etc/timezone
  219. fi
  220. TZ_PATH="$HOME"/.compose/etc/timezone
  221. COMPOSE_VAR="$HOME"/.compose/lib
  222. COMPOSE_CACHE="$HOME"/.compose/cache
  223. ;;
  224. *)
  225. echo "System '$os' not supported yet." >&2
  226. exit 1
  227. ;;
  228. esac
  229. docker_run_opts=()
  230. if [ -z "$COMPOSE_LAUNCHER_OPTS" ]; then
  231. clean_unused_sessions
  232. COMPOSE_LAUNCHER_OPTS="$(mk_docker_run_options)"
  233. fi
  234. while read-0 opt; do
  235. docker_run_opts+=("$opt")
  236. ## catch COMPOSE_DOCKER_IMAGE
  237. if [[ "$env" == "true" && "$opt" == "COMPOSE_DOCKER_IMAGE="* ]]; then
  238. COMPOSE_DOCKER_IMAGE=${opt##COMPOSE_DOCKER_IMAGE=}
  239. elif [ "$opt" == "-e" ]; then
  240. env=true
  241. else
  242. env=
  243. fi
  244. done < <(cat "$COMPOSE_LAUNCHER_OPTS")
  245. if [ -t 0 ]; then
  246. docker_run_opts+=("-i")
  247. fi
  248. if [ -t 1 ]; then
  249. docker_run_opts+=("-t")
  250. fi
  251. exec docker run --rm "${docker_run_opts[@]}" "${COMPOSE_DOCKER_IMAGE}" "$@"
  252. }
  253. run "$@"