|
@ -11,8 +11,55 @@ |
|
|
|
|
|
|
|
|
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && SOURCED=true |
|
|
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && SOURCED=true |
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
|
## From kal-shlib |
|
|
|
|
|
## |
|
|
|
|
|
|
|
|
ANSI_ESC=$'\e[' |
|
|
ANSI_ESC=$'\e[' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
md5_compat() { |
|
|
|
|
|
if get_path md5sum >/dev/null; then |
|
|
|
|
|
md5_compat() { md5sum | cut -c -32; } |
|
|
|
|
|
elif get_path md5 >/dev/null; then |
|
|
|
|
|
md5_compat() { md5; } |
|
|
|
|
|
else |
|
|
|
|
|
die "$exname: required GNU or BSD date not found" |
|
|
|
|
|
fi |
|
|
|
|
|
md5_compat |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## output on stdout the next record on stdin separated by a '\0' |
|
|
|
|
|
next-0() { |
|
|
|
|
|
local ans IFS='' |
|
|
|
|
|
read -r -d '' ans && |
|
|
|
|
|
echo -n "$ans" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
array_read-0() { |
|
|
|
|
|
local elt aname |
|
|
|
|
|
while true; do |
|
|
|
|
|
for aname in "$@"; do |
|
|
|
|
|
declare -n cur="$aname" |
|
|
|
|
|
elt="$(next-0)" || return 0 |
|
|
|
|
|
cur+=("$elt") |
|
|
|
|
|
done |
|
|
|
|
|
done |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
str_pattern_matches() { |
|
|
|
|
|
local str="$1" |
|
|
|
|
|
shift |
|
|
|
|
|
for pattern in "$@"; do |
|
|
|
|
|
eval "[[ \"$str\" == $pattern ]]" && return 0 |
|
|
|
|
|
done |
|
|
|
|
|
return 1 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ansi_color() { |
|
|
ansi_color() { |
|
|
local choice="$1" |
|
|
local choice="$1" |
|
|
|
|
|
|
|
@ -123,7 +170,12 @@ debug() { [ -z "$DEBUG" ] || e "$*"$'\n' >&2; } |
|
|
err() { e "${RED}Error:$NORMAL $*"$'\n' >&2 ; } |
|
|
err() { e "${RED}Error:$NORMAL $*"$'\n' >&2 ; } |
|
|
die() { err "$@" ; exit 1; } |
|
|
die() { err "$@" ; exit 1; } |
|
|
|
|
|
|
|
|
ansi_color "${ansi_color:-tty}" |
|
|
|
|
|
|
|
|
## equivalent of 'xargs echo' with builtins |
|
|
|
|
|
nspc() { |
|
|
|
|
|
local content |
|
|
|
|
|
content=$(printf "%s " $(cat -)) |
|
|
|
|
|
printf "%s" "${content::-1}" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_path() { ( |
|
|
get_path() { ( |
|
@ -199,6 +251,59 @@ p0() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cla.normalize() { |
|
|
|
|
|
local letters arg i |
|
|
|
|
|
while [ "$#" != 0 ]; do |
|
|
|
|
|
arg=$1 |
|
|
|
|
|
case "$arg" in |
|
|
|
|
|
--) |
|
|
|
|
|
p0 "$@" |
|
|
|
|
|
return 0 |
|
|
|
|
|
;; |
|
|
|
|
|
--*=*|-*=*) |
|
|
|
|
|
shift |
|
|
|
|
|
set -- "${arg%%=*}" "${arg#*=}" "$@" |
|
|
|
|
|
continue |
|
|
|
|
|
;; |
|
|
|
|
|
--*|-?) :;; |
|
|
|
|
|
-*) |
|
|
|
|
|
letters=${arg:1} |
|
|
|
|
|
shift |
|
|
|
|
|
i=${#letters} |
|
|
|
|
|
while ((i--)); do |
|
|
|
|
|
set -- -${letters:$i:1} "$@" |
|
|
|
|
|
done |
|
|
|
|
|
continue |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
p0 "$arg" |
|
|
|
|
|
shift |
|
|
|
|
|
done |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker_has_image() { |
|
|
|
|
|
local image="$1" |
|
|
|
|
|
images=$(docker images -q "$image" 2>/dev/null) || { |
|
|
|
|
|
err "docker images call has failed unexpectedly." |
|
|
|
|
|
return 1 |
|
|
|
|
|
} |
|
|
|
|
|
[ -n "$images" ] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker_image_id() { |
|
|
|
|
|
local image="$1" |
|
|
|
|
|
image_id=$(docker inspect "$image" --format='{{.Id}}') || return 1 |
|
|
|
|
|
echo "$image_id" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
|
## Compose-core common functions |
|
|
|
|
|
## |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
list_compose_vars() { |
|
|
list_compose_vars() { |
|
|
while read-0a def; do |
|
|
while read-0a def; do |
|
|
def="${def##* }" |
|
|
def="${def##* }" |
|
@ -235,6 +340,15 @@ is_volume_used() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_MULTIOPTION_REGEX='^((-[a-zA-Z]|--[a-zA-Z0-9-]+)(, )?)+' |
|
|
|
|
|
_MULTIOPTION_REGEX_LINE_FILTER=$_MULTIOPTION_REGEX'(\s|=)' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
|
|
## compose launcher functions |
|
|
|
|
|
## |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clean_unused_sessions() { |
|
|
clean_unused_sessions() { |
|
|
for f in "$SESSION_DIR/"*; do |
|
|
for f in "$SESSION_DIR/"*; do |
|
|
[ -e "$f" ] || continue |
|
|
[ -e "$f" ] || continue |
|
@ -257,6 +371,59 @@ relink_subdirs() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_tz() { |
|
|
|
|
|
if [ -n "$TZ" ]; then |
|
|
|
|
|
: |
|
|
|
|
|
elif [ -n "$COMPOSE_LOCAL_ROOT" ] && ## previous compose run |
|
|
|
|
|
[ -e "$COMPOSE_LOCAL_ROOT/etc/timezone" ]; then |
|
|
|
|
|
read -r TZ < "$COMPOSE_LOCAL_ROOT/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" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pretty_print() { |
|
|
|
|
|
while [ "$#" != 0 ]; do |
|
|
|
|
|
case "$1" in |
|
|
|
|
|
"-v"|"-e"|"-w") |
|
|
|
|
|
e "$1" "$2" "\\"$'\n' |
|
|
|
|
|
shift;; |
|
|
|
|
|
*) |
|
|
|
|
|
e "$1 ";; |
|
|
|
|
|
esac |
|
|
|
|
|
shift |
|
|
|
|
|
done |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mk_docker_run_options() { |
|
|
mk_docker_run_options() { |
|
|
|
|
|
|
|
|
## Order matters, files get to override vars |
|
|
## Order matters, files get to override vars |
|
@ -465,59 +632,6 @@ mk_docker_run_options() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_tz() { |
|
|
|
|
|
if [ -n "$TZ" ]; then |
|
|
|
|
|
: |
|
|
|
|
|
elif [ -n "$COMPOSE_LOCAL_ROOT" ] && ## previous compose run |
|
|
|
|
|
[ -e "$COMPOSE_LOCAL_ROOT/etc/timezone" ]; then |
|
|
|
|
|
read -r TZ < "$COMPOSE_LOCAL_ROOT/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" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pretty_print() { |
|
|
|
|
|
while [ "$#" != 0 ]; do |
|
|
|
|
|
case "$1" in |
|
|
|
|
|
"-v"|"-e"|"-w") |
|
|
|
|
|
e "$1" "$2" "\\"$'\n' |
|
|
|
|
|
shift;; |
|
|
|
|
|
*) |
|
|
|
|
|
e "$1 ";; |
|
|
|
|
|
esac |
|
|
|
|
|
shift |
|
|
|
|
|
done |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
run() { |
|
|
run() { |
|
|
local os docker_run_opts |
|
|
local os docker_run_opts |
|
|
|
|
|
|
|
@ -564,6 +678,8 @@ run() { |
|
|
## |
|
|
## |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
depends readlink |
|
|
|
|
|
|
|
|
depends docker cat readlink sed realpath |
|
|
|
|
|
|
|
|
|
|
|
ansi_color "${ansi_color:-tty}" |
|
|
|
|
|
|
|
|
run "$@" |
|
|
run "$@" |