Compare commits

...

7 Commits

Author SHA1 Message Date
Valentin Lab cb7a289ec5 chg: would fail without warning when charm is not found 4 years ago
Valentin Lab 9f38ef9bb9 new: dev: debug messages on launcher 4 years ago
Valentin Lab 90b9545835 fix: non-root user could not launch compose 4 years ago
Valentin Lab 71574d4196 new: default value for ``{CONFIG,DATA}STORE`` are different for non-root user 4 years ago
Valentin Lab ade2d7b1d9 new: timezone is fixed for containers 4 years ago
Valentin Lab 8248f9db1e new: dev: make compose sourcable for eventual tests !minor 4 years ago
Valentin Lab 7677c9e136 chg: dev: include color library and common element !minor 4 years ago
  1. 379
      bin/compose
  2. 11
      bin/compose-core

379
bin/compose

@ -9,19 +9,168 @@
## - no shell libs
##
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && SOURCED=true
ANSI_ESC=$'\e['
ansi_color() {
local choice="$1"
if [ "$choice" == "tty" ]; then
if [ -t 1 ]; then
choice="yes"
else
choice="no"
fi
fi
if [ "$choice" != "no" ]; then
SET_COL_CHAR="${ANSI_ESC}${COL_CHAR}G"
SET_COL_STATUS="${ANSI_ESC}${COL_STATUS}G"
SET_COL_INFO="${ANSI_ESC}${COL_INFO}G"
SET_COL_ELT="${ANSI_ESC}${COL_ELT}G"
SET_BEGINCOL="${ANSI_ESC}0G"
UP="${ANSI_ESC}1A"
DOWN="${ANSI_ESC}1B"
LEFT="${ANSI_ESC}1D"
RIGHT="${ANSI_ESC}1C"
SAVE="${ANSI_ESC}7"
RESTORE="${ANSI_ESC}8"
NORMAL="${ANSI_ESC}0m"
GRAY="${ANSI_ESC}1;30m"
RED="${ANSI_ESC}1;31m"
GREEN="${ANSI_ESC}1;32m"
YELLOW="${ANSI_ESC}1;33m"
BLUE="${ANSI_ESC}1;34m"
PINK="${ANSI_ESC}1;35m"
CYAN="${ANSI_ESC}1;36m"
WHITE="${ANSI_ESC}1;37m"
DARKGRAY="${ANSI_ESC}0;30m"
DARKRED="${ANSI_ESC}0;31m"
DARKGREEN="${ANSI_ESC}0;32m"
DARKYELLOW="${ANSI_ESC}0;33m"
DARKBLUE="${ANSI_ESC}0;34m"
DARKPINK="${ANSI_ESC}0;35m"
DARKCYAN="${ANSI_ESC}0;36m"
DARKWHITE="${ANSI_ESC}0;37m"
SUCCESS=$GREEN
WARNING=$YELLOW
FAILURE=$RED
NOOP=$BLUE
ON=$SUCCESS
OFF=$FAILURE
ERROR=$FAILURE
else
SET_COL_CHAR=
SET_COL_STATUS=
SET_COL_INFO=
SET_COL_ELT=
SET_BEGINCOL=
NORMAL=
RED=
GREEN=
YELLOW=
BLUE=
GRAY=
WHITE=
DARKGRAY=
DARKRED=
DARKGREEN=
DARKYELLOW=
DARKBLUE=
DARKPINK=
DARKCYAN=
SUCCESS=
WARNING=
FAILURE=
NOOP=
ON=
OFF=
ERROR=
fi
ansi_color="$choice"
export SET_COL_CHAR SET_COL_STATUS SET_COL_INFO SET_COL_ELT \
SET_BEGINCOL UP DOWN LEFT RIGHT SAVE RESTORE NORMAL \
GRAY RED GREEN YELLOW BLUE PINK CYAN WHITE DARKGRAY \
DARKRED DARKGREEN DARKYELLOW DARKBLUE DARKPINK DARKCYAN \
SUCCESS WARNING FAILURE NOOP ON OFF ERROR ansi_color
}
e() { printf "%s" "$*"; }
warn() { e "${YELLOW}Warning:$NORMAL" "$*"$'\n' >&2 ; }
info() { e "${BLUE}II$NORMAL" "$*"$'\n' >&2 ; }
verb() { [ -z "$VERBOSE" ] || e "$*"$'\n' >&2; }
debug() { [ -z "$DEBUG" ] || e "$*"$'\n' >&2; }
err() { e "${RED}Error:$NORMAL $*"$'\n' >&2 ; }
die() { err "$@" ; exit 1; }
ansi_color "${ansi_color:-tty}"
get_path() { (
IFS=:
for d in $PATH; do
filename="$d/$1"
[ -f "$filename" -a -x "$filename" ] && {
echo "$d/$1"
return 0
}
done
return 1
) }
depends() {
## Avoid colliding with variables that are created with depends.
local __i __path __new_name
for __i in "$@"; do
if ! __path=$(get_path "$__i"); then
__new_name="$(echo "${__i//-/_}")"
if [ "$__new_name" != "$__i" ]; then
depends "$__new_name"
else
err "dependency check: couldn't find '$__i' required command." >&2
exit 1
fi
else
if ! test -z "$__path" ; then
export "$(echo "${__i//- /__}")"="$__path"
fi
fi
done
}
get_os() {
local uname_output machine
get_os() {
local uname_output
uname_output="$(uname -s)"
case "${uname_output}" in
Linux*) machine=linux;;
Darwin*) machine=mac;;
CYGWIN*) machine=cygwin;;
MINGW*) machine=mingw;;
*) machine="UNKNOWN:${uname_output}"
Linux*) e linux;;
Darwin*) e mac;;
CYGWIN*) e cygwin;;
MINGW*) e mingw;;
*) e "UNKNOWN:${uname_output}";;
esac
echo "${machine}"
}
@ -110,15 +259,26 @@ relink_subdirs() {
mk_docker_run_options() {
docker_run_opts=("-v" "/var/run/docker.sock:/var/run/docker.sock")
## Order matters, files get to override vars
compose_config_files=(
## DEFAULT LINUX VARS
/etc/default/charm
/etc/default/datastore
/etc/default/compose
## CACHE/DATA DIRS
docker_run_opts+=("-v" "$COMPOSE_VAR:/var/lib/compose")
docker_run_opts+=("-v" "$COMPOSE_CACHE:/var/cache/compose")
## COMPOSE SYSTEM-WIDE FILES
/etc/compose.conf
/etc/compose.local.conf
/etc/compose/local.conf
docker_run_opts+=("-v" "$TZ_PATH:/etc/timezone:ro")
## COMPOSE USER FILES
~/.compose/etc/local.conf
~/.compose.conf
)
docker_run_opts=("-v" "/var/run/docker.sock:/var/run/docker.sock")
## current dir
if parent=$(while true; do
[ -e "./compose.yml" ] && {
@ -152,21 +312,62 @@ mk_docker_run_options() {
fi
COMPOSE_LOCAL_ROOT=${COMPOSE_LOCAL_ROOT:-"$HOME/.compose"}
case "$(get_os)" in
linux)
if [ "$UID" == 0 ]; then
COMPOSE_VAR=${COMPOSE_VAR:-/var/lib/compose}
COMPOSE_CACHE=${COMPOSE_CACHE:-/var/cache/compose}
else
COMPOSE_VAR="$COMPOSE_LOCAL_ROOT"/lib
COMPOSE_CACHE="$COMPOSE_LOCAL_ROOT"/cache
fi
;;
mac)
COMPOSE_VAR=${COMPOSE_VAR:-"$COMPOSE_LOCAL_ROOT"/lib}
COMPOSE_CACHE=${COMPOSE_CACHE:-"$COMPOSE_LOCAL_ROOT"/cache}
;;
*)
echo "System '$os' not supported yet." >&2
exit 1
;;
esac
## get TZ value and prepare TZ_PATH
TZ=$(get_tz) || exit 1
mkdir -p "${COMPOSE_VAR}/timezones"
TZ_PATH="${COMPOSE_VAR}/timezones/$(e "$TZ" | sha256sum | cut -c 1-8)" || exit 1
[ -e "$TZ_PATH" ] || e "$TZ" > "$TZ_PATH"
## 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")
##
## Checking vars
##
## CHARM_STORE
CHARM_STORE=${CHARM_STORE:-/srv/charm-store}
if [ "$UID" == 0 ]; then
CHARM_STORE=${CHARM_STORE:-/srv/charm-store}
else
CHARM_STORE=${CHARM_STORE:-$HOME/.charm-store}
fi
[ -e "$CHARM_STORE" ] || mkdir -p "$CHARM_STORE" || exit 1
[ -L "$CHARM_STORE" ] && {
CHARM_STORE=$(readlink -f "$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/*
relink_subdirs "$CHARM_STORE"/*
## DEFAULT_COMPOSE_FILE
if [ "${DEFAULT_COMPOSE_FILE+x}" ]; then
@ -189,7 +390,11 @@ mk_docker_run_options() {
fi
## DATASTORE
DATASTORE=${DATASTORE:-/srv/datastore/data}
if [ "$UID" == 0 ]; then
DATASTORE=${DATASTORE:-/srv/datastore/data}
else
DATASTORE=${DATASTORE:-"$COMPOSE_LOCAL_ROOT"/data}
fi
docker_run_opts+=(
"-v" "$DATASTORE:/srv/datastore/data:rw"
"-e" "DATASTORE=/srv/datastore/data"
@ -197,7 +402,11 @@ mk_docker_run_options() {
)
## CONFIGSTORE
CONFIGSTORE=${CONFIGSTORE:-/srv/datastore/config}
if [ "$UID" == 0 ]; then
CONFIGSTORE=${CONFIGSTORE:-/srv/datastore/config}
else
CONFIGSTORE=${CONFIGSTORE:-"$COMPOSE_LOCAL_ROOT"/data}
fi
docker_run_opts+=(
"-v" "$CONFIGSTORE:/srv/datastore/config:rw"
"-e" "CONFIGSTORE=/srv/datastore/config"
@ -211,8 +420,8 @@ mk_docker_run_options() {
## SSH config
docker_run_opts+=(
"-v" "/root/.ssh:/root/.ssh:ro"
"-v" "/etc/ssh:/etc/ssh"
"-v" "$HOME/.ssh:/root/.ssh:ro"
"-v" "/etc/ssh:/etc/ssh:ro"
)
COMPOSE_LAUNCHER_BIN=$(readlink -f "${BASH_SOURCE[0]}")
@ -232,58 +441,88 @@ mk_docker_run_options() {
filename=$(mktemp -p /tmp/ -t launch_opts-XXXXXXXXXXXXXXXX)
{
printf "%s\0" "${docker_run_opts[@]}"
p0 "${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"
p0 "-v" "$dest:$dest"
p0 "-e" "COMPOSE_LAUNCHER_OPTS=$dest"
p0 "-e" "COMPOSE_LAUNCHER_BIN=$COMPOSE_LAUNCHER_BIN"
} >> "$filename"
mkdir -p "$COMPOSE_VAR"/sessions
mv "$filename" "$dest"
echo "$dest"
if [ "$DEBUG" ]; then
echo "${WHITE}Environment:${NORMAL}"
echo " COMPOSE_DOCKER_IMAGE: $COMPOSE_DOCKER_IMAGE"
echo " CHARM_STORE: $CHARM_STORE"
echo " DATASTORE: $DATASTORE"
echo " CONFIGSTORE: $CONFIGSTORE"
echo " COMPOSE_VAR: $COMPOSE_VAR"
echo " COMPOSE_CACHE: $COMPOSE_CACHE"
fi >&2
}
run() {
local os docker_run_opts
get_tz() {
if [ -n "$TZ" ]; then
:
elif [ -n "$COMPOSE_LOCAL_ROOT" ] && ## previous compose run
[ -e "$COMPOSE_LOCAL_ROOT/etc/timezone" ]; then
read -r TZ < /etc/timezone
elif [ -e "/etc/timezone" ]; then ## debian host system timezone
read -r TZ < /etc/timezone
elif [ -e "/etc/localtime" ]; then ## redhat and macosx sys timezone
local fullpath dirname
fullpath="$(readlink -f /etc/localtime)"
dirname="${fullpath%/*}"
TZ=${TZ:-${fullpath##*/}/${dirname##*/}}
else
err "Timezone not found nor inferable !"
echo " compose relies on '/etc/timezone' or '/etc/localtime' to be present " >&2
echo " so as to ensure same timezone for all containers that need it." >&2
echo >&2
echo " You can set a default value for compose by create issuing:" >&2
echo >&2
if [ -n "$COMPOSE_LOCAL_ROOT" ] && [ "$UID" != 0 ]; then
echo " mkdir -p $COMPOSE_LOCAL_ROOT/etc &&" >&2
echo " echo \"Europe/Paris\" > $COMPOSE_LOCAL_ROOT/etc/timezone" >&2
else
echo " echo \"Europe/Paris\" > /etc/timezone" >&2
fi
echo >&2
echo " Of course, you can change 'Europe/Paris' value by any other valid timezone." >&2
echo " timezone." >&2
echo >&2
echo " Notice you can also use \$TZ environment variable, but the value" >&2
echo " will be necessary each time you launch compose." >&2
echo >&2
return 1
fi
e "$TZ"
}
## 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
TZ_PATH=/etc/timezone
;;
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
pretty_print() {
while [ "$#" != 0 ]; do
case "$1" in
"-v"|"-e"|"-w")
e "$1" "$2" "\\"$'\n'
shift;;
*)
e "$1 ";;
esac
shift
done
}
run() {
local os docker_run_opts
docker_run_opts=()
if [ -z "$COMPOSE_LAUNCHER_OPTS" ]; then
@ -303,14 +542,28 @@ run() {
fi
done < <(cat "$COMPOSE_LAUNCHER_OPTS")
if [ -t 0 ]; then
docker_run_opts+=("-i")
fi
if [ -t 1 ]; then
docker_run_opts+=("-t")
fi
[ -t 0 ] && docker_run_opts+=("-i")
[ -t 1 ] && docker_run_opts+=("-t")
if [ "$DEBUG" ]; then
echo "${WHITE}Launching:${NORMAL}"
echo " docker run --rm \\"
pretty_print "${docker_run_opts[@]}" | sed -r 's/^/ /g' >&2
echo "\\"$'\n' >&2
echo " ${COMPOSE_DOCKER_IMAGE} \\"
echo " " "$@"
fi >&2
exec docker run --rm "${docker_run_opts[@]}" "${COMPOSE_DOCKER_IMAGE}" "$@"
}
run "$@"
[ "$SOURCED" ] && return 0
##
## Code
##
depends readlink
run "$@"

11
bin/compose-core

@ -1266,8 +1266,13 @@ get_compose_service_def () {
docker_compose=$(get_compose_yml_content) || return 1
result=$(_get_compose_service_def_cached "$service" "$docker_compose") || return 1
charm=$(echo "$result" | shyaml get-value charm 2>/dev/null) || return 1
metadata=$(charm.metadata "$charm") || return 1
if default_options=$(printf "%s" "$metadata" | shyaml -y -q get-value default-options); then
if charm.exists "$charm"; then
metadata=$(charm.metadata "$charm") || return 1
else
err "Charm $DARKPINK$charm$NORMAL not found in charm-store."
return 1
fi
if default_options=$(e "$metadata" | shyaml -y -q get-value default-options); then
default_options=$(yaml_key_val_str "options" "$default_options") || return 1
result=$(merge_yaml_str "$default_options" "$result") || return 1
fi
@ -2164,7 +2169,7 @@ _get_services_uses() {
for service in "$@"; do
_get_service_uses "$service" | while read-0 rn rd; do
printf "%s\0" "$service" "$rn" "$rd"
p0 "$service" "$rn" "$rd"
done
[ "${PIPESTATUS[0]}" == 0 ] || {
return 1

Loading…
Cancel
Save