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.
 
 

275 lines
7.1 KiB

#!/bin/bash
## Bash wrap script to launch the ``compose`` docker with right options.
##
##
## Launcher
## - should need minimum requirement to run
## - no shell libs
##
get_os() {
local uname_output machine
uname_output="$(uname -s)"
case "${uname_output}" in
Linux*) machine=linux;;
Darwin*) machine=mac;;
CYGWIN*) machine=cygwin;;
MINGW*) machine=mingw;;
*) machine="UNKNOWN:${uname_output}"
esac
echo "${machine}"
}
read-0() {
local eof= IFS=''
while [ "$1" ]; do
read -r -d '' -- "$1" || eof=1
shift
done
[ -z "$eof" ]
}
get_running_compose_containers() {
## XXXvlab: docker bug: there will be a final newline anyway
docker ps --filter label="compose.service" --format='{{.ID}}'
}
get_volumes_for_container() {
local container="$1"
docker inspect \
--format '{{range $mount := .Mounts}}{{$mount.Source}}{{"\x00"}}{{$mount.Destination}}{{"\x00"}}{{end}}' \
"$container"
}
is_volume_used() {
local volume="$1"
while read container_id; do
while read-0 src dst; do
[ "$src" == "$volume" ] && return 0
done < <(get_volumes_for_container "$container_id")
done < <(get_running_compose_containers)
return 1
}
clean_unused_sessions() {
for f in "$COMPOSE_VAR/sessions/"*; do
[ -e "$f" ] || continue
is_volume_used "$f" && continue
rm -f "$f"
done
}
relink_subdirs() {
local dir
for dir in "$@"; do
[ -L "$dir" ] || continue
target=$(realpath "$dir")
[ -d "$target" ] || continue
docker_run_opts+=("-v" "$target:$dir")
[ -e "$dir/metadata.yml" ] && continue
relink_subdirs "$dir"/*
done
}
mk_docker_run_options() {
docker_run_opts=("-v" "/var/run/docker.sock:/var/run/docker.sock")
## CACHE/DATA DIRS
docker_run_opts+=("-v" "$COMPOSE_VAR:/var/lib/compose")
docker_run_opts+=("-v" "$COMPOSE_CACHE:/var/cache/compose")
docker_run_opts+=("-v" "$TZ_PATH:/etc/timezone:ro")
## current dir
if parent=$(while true; do
[ -e "./compose.yml" ] && {
echo "$PWD"
exit 0
}
[ "$PWD" == "/" ] && exit 1
cd ..
done
); then
docker_path=$COMPOSE_VAR/root/$(basename "$parent")
docker_run_opts+=("-v" "$parent:$docker_path:ro" \
"-w" "$docker_path")
fi
##
## Load config files
##
if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then
## XXXvlab: should provide YML config opportunities in possible parent dirs ?
## userdir ? and global /etc/compose.yml ?
for cfgfile in "${compose_config_files[@]}"; do
[ -e "$cfgfile" ] || continue
docker_run_opts+=("-v" "$cfgfile:$cfgfile:ro")
. "$cfgfile"
done
else
docker_run_opts+=("-e" "DISABLE_SYSTEM_CONFIG_FILE=$DISABLE_SYSTEM_CONFIG_FILE")
fi
##
## Checking vars
##
## CHARM_STORE
CHARM_STORE=${CHARM_STORE:-/srv/charm-store}
[ -L "$CHARM_STORE" ] && {
CHARM_STORE=$(readlink "$CHARM_STORE") || exit 1
}
docker_run_opts+=(
"-v" "$CHARM_STORE:/srv/charm-store:ro"
"-e" "CHARM_STORE=/srv/charm-store"
"-e" "HOST_CHARM_STORE=$CHARM_STORE"
)
relink_subdirs /srv/charm-store/*
## DEFAULT_COMPOSE_FILE
if [ "${DEFAULT_COMPOSE_FILE+x}" ]; then
DEFAULT_COMPOSE_FILE=$(realpath "$DEFAULT_COMPOSE_FILE")
dirname=$(dirname "$DEFAULT_COMPOSE_FILE")/
if [ -e "${DEFAULT_COMPOSE_FILE}" ]; then
docker_run_opts+=("-v" "$dirname:$dirname:ro")
fi
fi
## COMPOSE_YML_FILE
if [ "${COMPOSE_YML_FILE+x}" ]; then
if [ -e "${COMPOSE_YML_FILE}" ]; then
docker_run_opts+=(
"-v" "$COMPOSE_YML_FILE:/tmp/compose.yml:ro"
"-e" "COMPOSE_YML_FILE=/tmp/compose.yml"
"-e" "HOST_COMPOSE_YML_FILE=/tmp/compose.yml"
)
fi
fi
## DATASTORE
if [ "${DATASTORE+x}" ]; then
docker_run_opts+=(
"-v" "$DATASTORE:/srv/datastore/data:rw"
"-e" "DATASTORE=/srv/datastore/data"
"-e" "HOST_DATASTORE=$DATASTORE"
)
fi
## CONFIGSTORE
if [ "${CONFIGSTORE+x}" ]; then
docker_run_opts+=(
"-v" "$CONFIGSTORE:/srv/datastore/config:rw"
"-e" "CONFIGSTORE=/srv/datastore/config"
"-e" "HOST_CONFIGSTORE=$CONFIGSTORE"
)
fi
docker_run_opts+=("-v" "$HOME/.docker:/root/.docker")
COMPOSE_DOCKER_IMAGE=${COMPOSE_DOCKER_IMAGE:-docker.0k.io/compose}
docker_run_opts+=("-e" "COMPOSE_DOCKER_IMAGE=$COMPOSE_DOCKER_IMAGE")
COMPOSE_LAUNCHER_BIN=$(readlink -f "${BASH_SOURCE[0]}")
docker_run_opts+=("-v" "$COMPOSE_LAUNCHER_BIN:/usr/local/bin/compose")
filename=$(mktemp -p /tmp/ -t launch_opts-XXXXXXXXXXXXXXXX)
{
printf "%s\0" "${docker_run_opts[@]}"
} > "$filename"
sha=$(sha256sum "$filename")
sha=${sha:0:64}
dest="$COMPOSE_VAR/sessions/$sha"
{
printf "%s\0" "-v" "$dest:$dest"
printf "%s\0" "-e" "COMPOSE_LAUNCHER_OPTS=$dest"
printf "%s\0" "-e" "COMPOSE_LAUNCHER_BIN=$COMPOSE_LAUNCHER_BIN"
} >> "$filename"
mkdir -p "$COMPOSE_VAR"/sessions
mv "$filename" "$dest"
echo "$dest"
}
run() {
local os docker_run_opts
## Order matters, files get to override vars
compose_config_files=(
/etc/default/charm
/etc/default/datastore
/etc/compose.conf
/etc/compose.local.conf
/etc/default/compose
~/.compose/etc/local.conf
/etc/compose/local.conf
)
os=$(get_os)
case "$os" in
linux)
COMPOSE_VAR=/var/lib/compose
COMPOSE_CACHE=/var/cache/compose
;;
mac)
if ! [ -e "$HOME/.compose/etc/timezone" ]; then
TZ=${TZ:-"Europe/Paris"}
echo "$TZ" > "$HOME"/.compose/etc/timezone
fi
TZ_PATH="$HOME"/.compose/etc/timezone
COMPOSE_VAR="$HOME"/.compose/lib
COMPOSE_CACHE="$HOME"/.compose/cache
;;
*)
echo "System '$os' not supported yet." >&2
exit 1
;;
esac
docker_run_opts=()
if [ -z "$COMPOSE_LAUNCHER_OPTS" ]; then
clean_unused_sessions
COMPOSE_LAUNCHER_OPTS="$(mk_docker_run_options)"
fi
while read-0 opt; do
docker_run_opts+=("$opt")
## catch COMPOSE_DOCKER_IMAGE
if [[ "$env" == "true" && "$opt" == "COMPOSE_DOCKER_IMAGE="* ]]; then
COMPOSE_DOCKER_IMAGE=${opt##COMPOSE_DOCKER_IMAGE=}
elif [ "$opt" == "-e" ]; then
env=true
else
env=
fi
done < <(cat "$COMPOSE_LAUNCHER_OPTS")
if [ -t 0 ]; then
docker_run_opts+=("-i")
fi
if [ -t 1 ]; then
docker_run_opts+=("-t")
fi
exec docker run --rm "${docker_run_opts[@]}" "${COMPOSE_DOCKER_IMAGE}" "$@"
}
run "$@"