From e521d5fee9265a9d98f7c6d12c47aebe21dee1fc Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Mon, 26 Nov 2018 11:13:09 +0100 Subject: [PATCH] new: store and keep compiled docker-compose and a mean to use-it for services. The ``docker-compose.yml`` is saved along with an executable ``dc`` and ``.env`` in a directory to be shared as a volume in case we'd like to launch a subservice in the same setup from a launched service. For instance, a ``cron`` charm could want to launch ``run-once`` services. The charm only need to access the ``dc`` binary, this can be done by sharing the binary as a volume. This is the recommended way to do this: ``\${DOCKER_COMPOSE_PATH}/bin/dc:/bin/dc:ro``. Notice how we use a docker-compose level variable here as the DOCKER_COMPOSE_PATH will only be computed after all ``init`` hooks are done. This is the purpose of the ``.env`` file that is also generated. These directories are garbage collected if no containers have volumes connected to it. --- bin/compose-core | 108 ++++++++++++++++++++++++++++++++++++++++++++++- test/action | 2 +- test/args | 3 +- test/base | 3 +- test/injection | 3 +- test/wget | 2 +- 6 files changed, 115 insertions(+), 6 deletions(-) diff --git a/bin/compose-core b/bin/compose-core index 008dab5..588a222 100755 --- a/bin/compose-core +++ b/bin/compose-core @@ -2161,6 +2161,98 @@ get_default_project_name() { export -f get_default_project_name +get_running_compose_containers() { + ## XXXvlab: docker bug: there will be a final newline anyway + docker ps --filter label="compose.service" --format='{{.ID}}' +} +export -f get_running_compose_containers + + +get_volumes_for_container() { + local container="$1" + + docker inspect \ + --format '{{range $mount := .Mounts}}{{$mount.Source}}{{"\x00"}}{{$mount.Destination}}{{"\x00"}}{{end}}' \ + "$container" +} +export -f get_volumes_for_container + +is_volume_used() { + local volume="$1" container_id src dst + + 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 +} +export -f is_volume_used + + +clean_unused_docker_compose() { + for f in /var/lib/compose/docker-compose/*; do + [ -e "$f" ] || continue + is_volume_used "$f" && continue + debug "Cleaning unused docker-compose ${f##*/}" + rm -rf "$f" || return 1 + done +} +export -f clean_unused_docker_compose + + +file_get_hash() { + local file="$1" sha + sha=$(sha256sum "$file") + sha=${sha:0:64} + echo "$sha" +} +export -f file_get_hash + + +docker_compose_store() { + local file="$1" sha + + sha=$(file_get_hash "$file") || return 1 + project=$(get_default_project_name) || return 1 + dst="/var/lib/compose/docker-compose/$sha/$project" + mkdir -p "$dst" || return 1 + cat < "$dst/.env" || return 1 +DOCKER_COMPOSE_PATH=$dst +EOF + cp "$file" "$dst/docker-compose.yml" || return 1 + + mkdir -p "$dst/bin" || return 1 + + cat < "$dst/bin/dc" || return 1 +#!/bin/bash + +$(declare -f read-0) + +docker_run_opts=() + +while read-0 opt; do + docker_run_opts+=("\$opt") +done < <(cat "$COMPOSE_LAUNCHER_OPTS") + +docker_run_opts+=( + "-w" "$dst" + "--entrypoint" "/usr/local/bin/docker-compose" +) +[ -t 1 ] && { + docker_run_opts+=("-ti") +} + +exec docker run "\${docker_run_opts[@]}" "${COMPOSE_DOCKER_IMAGE:-docker.0k.io/compose}" "\$@" + +EOF + + chmod +x "$dst/bin/dc" || return 1 + + printf "%s" "$sha" +} + + launch_docker_compose() { local charm docker_compose_tmpdir docker_compose_dir docker_compose_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) @@ -2192,9 +2284,21 @@ launch_docker_compose() { # done mkdir "$docker_compose_dir/.data" + if [ -z "$COMPOSE_DISABLE_DOCKER_COMPOSE_STORE" ]; then + sha=$(docker_compose_store "$docker_compose_dir/docker-compose.yml") || return 1 + fi + { { - cd "$docker_compose_dir" + if [ -z "$COMPOSE_DISABLE_DOCKER_COMPOSE_STORE" ]; then + cd "/var/lib/compose/docker-compose/$sha/$project" + else + cd "$docker_compose_dir" + fi + if [ -f ".env" ]; then + debug "${WHITE}.env$NORMAL for $DARKYELLOW$SERVICE_PACK$NORMAL:" + debug "$(cat ".env" | prefix " $GRAY|$NORMAL ")" + fi debug "${WHITE}docker-compose.yml$NORMAL for $DARKYELLOW$SERVICE_PACK$NORMAL:" debug "$(cat "docker-compose.yml" | prefix " $GRAY|$NORMAL ")" debug "${WHITE}Launching$NORMAL: docker-compose $@" @@ -3086,3 +3190,5 @@ esac || exit 1 if [ "$post_hook" -a "${#services_args[@]}" != 0 ]; then run_service_hook post_deploy "${services_args[@]}" || exit 1 fi + +clean_unused_docker_compose || return 1 diff --git a/test/action b/test/action index 19651e1..123ee7b 100755 --- a/test/action +++ b/test/action @@ -9,7 +9,7 @@ export -f matches export grep tmp=/tmp -tprog="../bin/compose" +tprog="../bin/compose-core" tprog=$(readlink -f $tprog) diff --git a/test/args b/test/args index 00dac70..389adb0 100755 --- a/test/args +++ b/test/args @@ -9,7 +9,7 @@ export -f matches export grep tmp=/tmp -tprog="../bin/compose" +tprog="../bin/compose-core" tprog=$(readlink -f $tprog) @@ -26,6 +26,7 @@ init_test() { cd "$test_tmpdir" export CACHEDIR="$test_tmpdir/.cache" export VARDIR="$test_tmpdir/.var" + export COMPOSE_DISABLE_DOCKER_COMPOSE_STORE="1" mkdir -p "$CACHEDIR" } diff --git a/test/base b/test/base index db21acf..7b54ba4 100755 --- a/test/base +++ b/test/base @@ -9,7 +9,7 @@ export -f matches export grep tmp=/tmp -tprog="../bin/compose" +tprog="../bin/compose-core" tprog=$(readlink -f $tprog) @@ -26,6 +26,7 @@ init_test() { cd "$test_tmpdir" export CACHEDIR="$test_tmpdir/.cache" export VARDIR="$test_tmpdir/.var" + export COMPOSE_DISABLE_DOCKER_COMPOSE_STORE="1" mkdir -p "$CACHEDIR" } diff --git a/test/injection b/test/injection index 36600fe..a469eda 100755 --- a/test/injection +++ b/test/injection @@ -9,7 +9,7 @@ export -f matches export grep tmp=/tmp -tprog="../bin/compose" +tprog="../bin/compose-core" tprog=$(readlink -f $tprog) @@ -26,6 +26,7 @@ init_test() { cd "$test_tmpdir" export CACHEDIR="$test_tmpdir/.cache" export VARDIR="$test_tmpdir/.var" + export COMPOSE_DISABLE_DOCKER_COMPOSE_STORE="1" mkdir -p "$CACHEDIR" } diff --git a/test/wget b/test/wget index 0397509..74dbb9b 100755 --- a/test/wget +++ b/test/wget @@ -9,7 +9,7 @@ export -f matches export grep tmp=/tmp -tprog="../bin/compose" +tprog="../bin/compose-core" tprog=$(readlink -f $tprog)