|
@ -23,6 +23,14 @@ |
|
|
## This will allow to cache completely without issues function in time. |
|
|
## This will allow to cache completely without issues function in time. |
|
|
## - would probably need instrospection in charm custom action to know if these need |
|
|
## - would probably need instrospection in charm custom action to know if these need |
|
|
## init or relations to be set up. |
|
|
## init or relations to be set up. |
|
|
|
|
|
## - Be clear about when the SERVICE name is used and the CHARM name is used. |
|
|
|
|
|
## - in case of service contained in another container |
|
|
|
|
|
## - in normal case |
|
|
|
|
|
## - in docker-compose, can't use charm name: if we want 2 instances of the same charm |
|
|
|
|
|
## we are stuck. What will be unique is the name of the service. |
|
|
|
|
|
## - some relations are configured in compose.yml but should not trigger the loading |
|
|
|
|
|
## of necessary component (for instance, apache --> log-rotate), if log-rotate is |
|
|
|
|
|
## not there, this link should considered optional. |
|
|
|
|
|
|
|
|
#:- |
|
|
#:- |
|
|
[ -e /etc/shlib ] && . /etc/shlib || { |
|
|
[ -e /etc/shlib ] && . /etc/shlib || { |
|
@ -75,17 +83,30 @@ ${WHITE}$exname Options${NORMAL}: |
|
|
" |
|
|
" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && SOURCED=true |
|
|
|
|
|
|
|
|
## XXXvlab: this doesn't seem to work when 'compose' is called in |
|
|
|
|
|
## a hook of a charm. |
|
|
|
|
|
#[[ "${BASH_SOURCE[0]}" == "" ]] && SOURCED=true |
|
|
|
|
|
$(return >/dev/null 2>&1) && SOURCED=true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export CACHEDIR=/var/cache/compose |
|
|
|
|
|
export VARDIR=/var/lib/compose |
|
|
|
|
|
|
|
|
if [ "$UID" == 0 ]; then |
|
|
|
|
|
CACHEDIR=${CACHEDIR:-/var/cache/compose} |
|
|
|
|
|
VARDIR=${VARDIR:-/var/lib/compose} |
|
|
|
|
|
else |
|
|
|
|
|
[ "$XDG_CONFIG_HOME" ] && CACHEDIR=${CACHEDIR:-$XDG_CONFIG_HOME/compose} |
|
|
|
|
|
[ "$XDG_DATA_HOME" ] && VARDIR=${VARDIR:-$XDG_DATA_HOME/compose} |
|
|
|
|
|
CACHEDIR=${CACHEDIR:-$HOME/.cache/compose} |
|
|
|
|
|
VARDIR=${VARDIR:-$HOME/.local/share/compose} |
|
|
|
|
|
fi |
|
|
|
|
|
export VARDIR CACHEDIR |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
md5_compat() { md5sum | cut -c -32; } |
|
|
md5_compat() { md5sum | cut -c -32; } |
|
|
quick_cat_file() { quick_cat_stdin < "$1"; } |
|
|
quick_cat_file() { quick_cat_stdin < "$1"; } |
|
|
quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; } |
|
|
quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; } |
|
|
export -f quick_cat_file quick_cat_stdin md5_compat |
|
|
export -f quick_cat_file quick_cat_stdin md5_compat |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clean_cache() { |
|
|
clean_cache() { |
|
|
local i=0 |
|
|
local i=0 |
|
|
for f in $(ls -t "$CACHEDIR/"*.cache.* 2>/dev/null | tail -n +500); do |
|
|
for f in $(ls -t "$CACHEDIR/"*.cache.* 2>/dev/null | tail -n +500); do |
|
@ -294,6 +315,7 @@ cached_cmd_on_base_image() { |
|
|
} |
|
|
} |
|
|
export -f cached_cmd_on_base_image |
|
|
export -f cached_cmd_on_base_image |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
image_exposed_ports_0() { |
|
|
image_exposed_ports_0() { |
|
|
local image="$1" |
|
|
local image="$1" |
|
|
docker inspect --format='{{range $p, $conf := .Config.ExposedPorts}}{{$p}}{{"\x00"}}{{end}}' "$image" |
|
|
docker inspect --format='{{range $p, $conf := .Config.ExposedPorts}}{{$p}}{{"\x00"}}{{end}}' "$image" |
|
@ -542,10 +564,11 @@ ensure_db_docker_running () { |
|
|
_set_db_params "$DOCKER_IP" "$DOCKER_NETWORK" |
|
|
_set_db_params "$DOCKER_IP" "$DOCKER_NETWORK" |
|
|
return 0 |
|
|
return 0 |
|
|
else |
|
|
else |
|
|
err "Db not found. Docker logs follows:" |
|
|
|
|
|
|
|
|
errlvl="$?" |
|
|
|
|
|
err "Db not found (errlvl: $errlvl). Tail of docker logs follows:" |
|
|
docker logs --tail=5 "$container_id" 2>&1 | prefix " | " >&2 |
|
|
docker logs --tail=5 "$container_id" 2>&1 | prefix " | " >&2 |
|
|
rm "/tmp/${_DB_NAME}.working" |
|
|
rm "/tmp/${_DB_NAME}.working" |
|
|
return 1 |
|
|
|
|
|
|
|
|
return "$errlvl" |
|
|
fi |
|
|
fi |
|
|
} |
|
|
} |
|
|
export -f ensure_db_docker_running |
|
|
export -f ensure_db_docker_running |
|
@ -575,16 +598,16 @@ export -f _dcmd |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Executes code through db |
|
|
## Executes code through db |
|
|
dcmd () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dcmd() { |
|
|
|
|
|
local fun |
|
|
[ "$DB_NAME" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_NAME." |
|
|
[ "$DB_NAME" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_NAME." |
|
|
[ "$DB_DATADIR" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_DATADIR." |
|
|
[ "$DB_DATADIR" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_DATADIR." |
|
|
[ "$DB_PASSFILE" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_PASSFILE." |
|
|
|
|
|
|
|
|
# [ "$DB_PASSFILE" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_PASSFILE." |
|
|
[ "$_PID" ] || print_syntax_error "$FUNCNAME: You must provide \$_PID." |
|
|
[ "$_PID" ] || print_syntax_error "$FUNCNAME: You must provide \$_PID." |
|
|
[ "$(type -t is_db_locked)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function 'is_db_locked'." |
|
|
|
|
|
[ "$(type -t _set_db_params)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function '_set_db_params'." |
|
|
|
|
|
[ "$(type -t ddb)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function 'ddb'." |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for fun in is_db_locked _set_db_params ddb; do |
|
|
|
|
|
[ "$(type -t "$fun")" == "function" ] || |
|
|
|
|
|
print_syntax_error "$FUNCNAME: You must provide function '$fun'." |
|
|
|
|
|
done |
|
|
ensure_db_docker_running </dev/null || return 1 |
|
|
ensure_db_docker_running </dev/null || return 1 |
|
|
|
|
|
|
|
|
_dcmd "$@" |
|
|
_dcmd "$@" |
|
@ -634,31 +657,47 @@ wait_docker_ip() { |
|
|
export -f wait_docker_ip |
|
|
export -f wait_docker_ip |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wait_for_tcp_port() { |
|
|
|
|
|
local host_port=$1 timeout=30 start=$SECONDS |
|
|
|
|
|
verb "Trying to connect to $host_port" |
|
|
|
|
|
while true; do |
|
|
|
|
|
timeout 1 bash -c "</dev/tcp/${host_port/://}" >/dev/null 2>&1 && break |
|
|
|
|
|
sleep 0.2 |
|
|
|
|
|
if [ "$((SECONDS - start))" -gt "$timeout" ]; then |
|
|
|
|
|
err "${RED}timeout error${NORMAL}(${timeout}s):"\ |
|
|
|
|
|
"Could not connect to $host_port." |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
done |
|
|
|
|
|
return 0 |
|
|
|
|
|
} |
|
|
|
|
|
export -f wait_for_tcp_port |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Warning: requires a ``ddb`` matching current database to be checked |
|
|
## Warning: requires a ``ddb`` matching current database to be checked |
|
|
wait_for_docker_ip() { |
|
|
wait_for_docker_ip() { |
|
|
local name=$1 timeout=15 timeout_count=0 DOCKER_IP= DOCKER_NETWORK= docker_ips= docker_ip= DB_OK= |
|
|
|
|
|
|
|
|
local name=$1 DOCKER_IP= DOCKER_NETWORK= docker_ips= docker_ip= |
|
|
docker_ip=$(wait_docker_ip "$name" 5) || return 1 |
|
|
docker_ip=$(wait_docker_ip "$name" 5) || return 1 |
|
|
IFS=: read DOCKER_NETWORK DOCKER_IP <<<"$docker_ip" |
|
|
IFS=: read DOCKER_NETWORK DOCKER_IP <<<"$docker_ip" |
|
|
if ! str_is_ipv4 "$DOCKER_IP"; then |
|
|
if ! str_is_ipv4 "$DOCKER_IP"; then |
|
|
err "internal 'wait_docker_ip' did not return a valid IP. Returned IP is '$DOCKER_IP'." |
|
|
err "internal 'wait_docker_ip' did not return a valid IP. Returned IP is '$DOCKER_IP'." |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
timeout_count=0 |
|
|
|
|
|
DB_OK= |
|
|
|
|
|
_set_db_params "$DOCKER_IP" "$DOCKER_NETWORK" |
|
|
_set_db_params "$DOCKER_IP" "$DOCKER_NETWORK" |
|
|
while [ -z "$DB_OK" ]; do |
|
|
|
|
|
sleep 1 |
|
|
|
|
|
echo "SELECT 1;" | ddb >/dev/null && DB_OK=1 |
|
|
|
|
|
verb "[2/2] Waiting for db service from docker $name... ($[timeout_count + 1]/$timeout)" |
|
|
|
|
|
((timeout_count++)) || true |
|
|
|
|
|
if [ "$timeout_count" == "$timeout" ]; then |
|
|
|
|
|
err "${RED}timeout error${NORMAL}(${timeout}s):"\ |
|
|
|
|
|
"Could not connect to db on $DOCKER_IP" \ |
|
|
|
|
|
"container's IP." |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
done |
|
|
|
|
|
verb "[2/2] Db is ready !" |
|
|
|
|
|
|
|
|
while read-0 port; do |
|
|
|
|
|
IFS="/" read port type <<<"$port" |
|
|
|
|
|
[ "$type" == "tcp" ] || continue |
|
|
|
|
|
wait_for_tcp_port "$DOCKER_IP:${port}" || return 17 |
|
|
|
|
|
verb "Port $DOCKER_IP:${port} checked open." |
|
|
|
|
|
done < <(image_exposed_ports_0 "$container_id") |
|
|
|
|
|
|
|
|
|
|
|
## Checking direct connection |
|
|
|
|
|
if ! echo "SELECT 1;" | ddb >/dev/null; then |
|
|
|
|
|
err "${RED}db connection error${NORMAL}:"\ |
|
|
|
|
|
"Could not connect to db on $DOCKER_IP" \ |
|
|
|
|
|
"container's IP. (IP up, TCP ports is(are) open)" |
|
|
|
|
|
return 18 |
|
|
|
|
|
fi |
|
|
echo "${DOCKER_NETWORK}:${DOCKER_IP}" |
|
|
echo "${DOCKER_NETWORK}:${DOCKER_IP}" |
|
|
return 0 |
|
|
return 0 |
|
|
} |
|
|
} |
|
@ -711,19 +750,25 @@ get_docker_compose_links() { |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
master_service=$(get_top_master_service_for_service "$service") || return 1 |
|
|
master_service=$(get_top_master_service_for_service "$service") || return 1 |
|
|
|
|
|
|
|
|
|
|
|
## XXXvlab: yuck, this make the assumption that next function is cached, |
|
|
|
|
|
## and leverage the fact that the result is stored in a file. All this only |
|
|
|
|
|
## to catch a failure of ``get_compose_relations``, that would go out silently. |
|
|
|
|
|
get_compose_relations "$service" >/dev/null || return 1 ## fetch cache and fail if necessary |
|
|
deps=() |
|
|
deps=() |
|
|
while read-0 _relation_name target_service _relation_config tech_dep; do |
|
|
while read-0 _relation_name target_service _relation_config tech_dep; do |
|
|
master_target_service="$(get_top_master_service_for_service "$target_service")" |
|
|
|
|
|
|
|
|
master_target_service="$(get_top_master_service_for_service "$target_service")" || return 1 |
|
|
[ "$master_service" == "$master_target_service" ] && continue |
|
|
[ "$master_service" == "$master_target_service" ] && continue |
|
|
if [ "$tech_dep" == "reversed" ]; then |
|
|
if [ "$tech_dep" == "reversed" ]; then |
|
|
deps+=("$(echo -en "$master_target_service:\n links:\n - $master_service")") |
|
|
deps+=("$(echo -en "$master_target_service:\n links:\n - $master_service")") |
|
|
elif [ "$tech_dep" == "True" ]; then |
|
|
elif [ "$tech_dep" == "True" ]; then |
|
|
deps+=("$(echo -en "$master_service:\n links:\n - $master_target_service")") |
|
|
deps+=("$(echo -en "$master_service:\n links:\n - $master_target_service")") |
|
|
fi |
|
|
fi |
|
|
done < <(get_compose_relations "$service") || return 1 |
|
|
|
|
|
|
|
|
|
|
|
merge_yaml_str "${deps[@]}" | tee "$cache_file" |
|
|
|
|
|
|
|
|
## XXXvlab: an attempt to add depends_on, but this doesn't work well actually |
|
|
|
|
|
## as there's a circular dependency issue. We don't really want the full feature |
|
|
|
|
|
## of depends_on, but just to add it as targets when doing an 'up' |
|
|
|
|
|
# deps+=("$(echo -en "$master_service:\n depends_on:\n - $master_target_service")") |
|
|
|
|
|
done < <(get_compose_relations "$service") |
|
|
|
|
|
merge_yaml_str "${deps[@]}" | tee "$cache_file" || return 1 |
|
|
if [ "${PIPESTATUS[0]}" != 0 ]; then |
|
|
if [ "${PIPESTATUS[0]}" != 0 ]; then |
|
|
rm "$cache_file" |
|
|
rm "$cache_file" |
|
|
return 1 |
|
|
return 1 |
|
@ -777,7 +822,6 @@ _get_docker_compose_service_mixin() { |
|
|
cat "$cache_file" |
|
|
cat "$cache_file" |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
master_service=$(get_top_master_service_for_service "$service") || { |
|
|
master_service=$(get_top_master_service_for_service "$service") || { |
|
|
err "Failed to get top master service for service $DARKYELLOW$service$NORMAL" |
|
|
err "Failed to get top master service for service $DARKYELLOW$service$NORMAL" |
|
|
return 1 |
|
|
return 1 |
|
@ -787,17 +831,15 @@ _get_docker_compose_service_mixin() { |
|
|
|
|
|
|
|
|
base_mixin="$master_service: |
|
|
base_mixin="$master_service: |
|
|
labels: |
|
|
labels: |
|
|
- \"compose.service=$service\" |
|
|
|
|
|
- \"compose.master-service=${master_service}\" |
|
|
|
|
|
- \"compose.project=$(get_default_project_name)\"" |
|
|
|
|
|
|
|
|
- compose.service=$service |
|
|
|
|
|
- compose.master-service=${master_service} |
|
|
|
|
|
- compose.project=$(get_default_project_name)" |
|
|
links_yaml=$(get_docker_compose_links "$service") || return 1 |
|
|
links_yaml=$(get_docker_compose_links "$service") || return 1 |
|
|
docker_compose_options=$(_get_docker_compose_opts "$service") || return 1 |
|
|
docker_compose_options=$(_get_docker_compose_opts "$service") || return 1 |
|
|
|
|
|
|
|
|
## the charm part |
|
|
## the charm part |
|
|
|
|
|
|
|
|
#debug "Get charm name from service name $DARKYELLOW$service$NORMAL." |
|
|
|
|
|
charm=$(get_service_charm "$service") || return 1 |
|
|
|
|
|
charm_part=$(get_docker_compose_mixin_from_metadata "$service" "$charm") || return 1 |
|
|
|
|
|
|
|
|
charm_part=$(get_docker_compose_mixin_from_metadata "$service") || return 1 |
|
|
|
|
|
|
|
|
## Merge results |
|
|
## Merge results |
|
|
if [ "$charm_part" ]; then |
|
|
if [ "$charm_part" ]; then |
|
@ -822,7 +864,8 @@ export -f _get_docker_compose_service_mixin |
|
|
## @export |
|
|
## @export |
|
|
## @cache: !system !nofail +stdout |
|
|
## @cache: !system !nofail +stdout |
|
|
get_docker_compose () { |
|
|
get_docker_compose () { |
|
|
local cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)" entries services service start |
|
|
|
|
|
|
|
|
local cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \ |
|
|
|
|
|
entries services service start docker_compose_services |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
# debug "$FUNCNAME: cache hit ($*)" |
|
|
# debug "$FUNCNAME: cache hit ($*)" |
|
|
cat "$cache_file" |
|
|
cat "$cache_file" |
|
@ -892,19 +935,31 @@ _get_compose_service_def_cached () { |
|
|
local service="$1" docker_compose="$2" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
local service="$1" docker_compose="$2" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
#debug "$FUNCNAME: STATIC cache hit" |
|
|
#debug "$FUNCNAME: STATIC cache hit" |
|
|
cat "$cache_file" |
|
|
|
|
|
touch "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
service_def_base="charm: $service" |
|
|
|
|
|
value=$(echo "$docker_compose" | shyaml get-value "$service" 2>/dev/null) |
|
|
value=$(echo "$docker_compose" | shyaml get-value "$service" 2>/dev/null) |
|
|
merge_yaml <(echo "$service_def_base") <(echo "$value") | tee "$cache_file" |
|
|
|
|
|
if [ "${PIPESTATUS[0]}" != 0 ]; then |
|
|
|
|
|
rm "$cache_file" |
|
|
|
|
|
return 1 |
|
|
|
|
|
|
|
|
if ! echo "$value" | shyaml get-value "charm" >/dev/null 2>&1; then |
|
|
|
|
|
if charm.exists "$service"; then |
|
|
|
|
|
value=$(merge_yaml <(echo "charm: $service") <(echo "$value")) || return 1 |
|
|
|
|
|
else |
|
|
|
|
|
err "No ${WHITE}charm${NORMAL} value for service $DARKYELLOW$service$NORMAL" \ |
|
|
|
|
|
"in compose, nor same name charm found." |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
echo "$value" | tee "$cache_file" || return 1 |
|
|
|
|
|
# if [ "${PIPESTATUS[0]}" != 0 ]; then |
|
|
|
|
|
# rm "$cache_file" |
|
|
|
|
|
# return 1 |
|
|
|
|
|
# fi |
|
|
|
|
|
return 0 |
|
|
|
|
|
# if [ "${PIPESTATUS[0]}" != 0 -o \! -s "$cache_file" ]; then |
|
|
|
|
|
# rm "$cache_file" |
|
|
|
|
|
# err "PAS OK $service: $value" |
|
|
|
|
|
# return 1 |
|
|
|
|
|
# fi |
|
|
} |
|
|
} |
|
|
export -f _get_compose_service_def_cached |
|
|
export -f _get_compose_service_def_cached |
|
|
|
|
|
|
|
@ -914,15 +969,15 @@ get_compose_service_def () { |
|
|
result |
|
|
result |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
#debug "$FUNCNAME: SESSION cache hit" |
|
|
#debug "$FUNCNAME: SESSION cache hit" |
|
|
cat "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
[ -z "$service" ] && print_syntax_error "Missing service as first argument." |
|
|
[ -z "$service" ] && print_syntax_error "Missing service as first argument." |
|
|
|
|
|
|
|
|
docker_compose=$(cat "$COMPOSE_YML_FILE") || return 1 |
|
|
|
|
|
|
|
|
docker_compose=$([ "$COMPOSE_YML_FILE" -a -e "$COMPOSE_YML_FILE" ] && cat "$COMPOSE_YML_FILE") |
|
|
result=$(_get_compose_service_def_cached "$service" "$docker_compose") || return 1 |
|
|
result=$(_get_compose_service_def_cached "$service" "$docker_compose") || return 1 |
|
|
echo "$result" | tee "$cache_file" |
|
|
|
|
|
|
|
|
echo "$result" | tee "$cache_file" || return 1 |
|
|
} |
|
|
} |
|
|
export -f get_compose_service_def |
|
|
export -f get_compose_service_def |
|
|
|
|
|
|
|
@ -931,8 +986,8 @@ _get_service_charm_cached () { |
|
|
local service="$1" service_def="$2" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
local service="$1" service_def="$2" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
# debug "$FUNCNAME: cache hit $1" |
|
|
# debug "$FUNCNAME: cache hit $1" |
|
|
cat "$cache_file" |
|
|
|
|
|
touch "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
charm=$(echo "$service_def" | shyaml get-value charm 2>/dev/null) |
|
|
charm=$(echo "$service_def" | shyaml get-value charm 2>/dev/null) |
|
@ -940,13 +995,14 @@ _get_service_charm_cached () { |
|
|
err "Missing ${WHITE}charm${NORMAL} value in service $DARKYELLOW$service$NORMAL definition." |
|
|
err "Missing ${WHITE}charm${NORMAL} value in service $DARKYELLOW$service$NORMAL definition." |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
echo "$charm" | tee "$cache_file" |
|
|
|
|
|
|
|
|
echo "$charm" | tee "$cache_file" || return 1 |
|
|
} |
|
|
} |
|
|
export -f _get_service_charm_cached |
|
|
export -f _get_service_charm_cached |
|
|
|
|
|
|
|
|
get_service_charm () { |
|
|
get_service_charm () { |
|
|
local service="$1" |
|
|
local service="$1" |
|
|
if [ -z "$service" ]; then |
|
|
if [ -z "$service" ]; then |
|
|
|
|
|
echo ${FUNCNAME[@]} >&2 |
|
|
print_syntax_error "$FUNCNAME: Please specify a service as first argument." |
|
|
print_syntax_error "$FUNCNAME: Please specify a service as first argument." |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
@ -1111,8 +1167,9 @@ get_ordered_service_dependencies() { |
|
|
|
|
|
|
|
|
#debug "Figuring ordered deps of $DARKYELLOW$services$NORMAL" |
|
|
#debug "Figuring ordered deps of $DARKYELLOW$services$NORMAL" |
|
|
if [ -z "${services[*]}" ]; then |
|
|
if [ -z "${services[*]}" ]; then |
|
|
print_syntax_error "$FUNCNAME: no arguments" |
|
|
|
|
|
return 1 |
|
|
|
|
|
|
|
|
return 0 |
|
|
|
|
|
# print_syntax_error "$FUNCNAME: no arguments" |
|
|
|
|
|
# return 1 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
declare -A depths |
|
|
declare -A depths |
|
@ -1138,11 +1195,12 @@ get_ordered_service_dependencies() { |
|
|
export -f get_ordered_service_dependencies |
|
|
export -f get_ordered_service_dependencies |
|
|
|
|
|
|
|
|
run_service_hook () { |
|
|
run_service_hook () { |
|
|
local services="$1" action="$2" loaded |
|
|
|
|
|
|
|
|
local services="$1" action="$2" subservices loaded |
|
|
|
|
|
|
|
|
declare -A loaded |
|
|
declare -A loaded |
|
|
for service in $services; do |
|
|
for service in $services; do |
|
|
for subservice in $(get_ordered_service_dependencies "$service"); do |
|
|
|
|
|
|
|
|
subservices=$(get_ordered_service_dependencies "$service") || return 1 |
|
|
|
|
|
for subservice in $subservices; do |
|
|
if [ "${loaded[$subservice]}" ]; then |
|
|
if [ "${loaded[$subservice]}" ]; then |
|
|
## Prevent double inclusion of same service if this |
|
|
## Prevent double inclusion of same service if this |
|
|
## service is deps of two or more of your |
|
|
## service is deps of two or more of your |
|
@ -1254,11 +1312,12 @@ export -f setup_host_resource |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setup_host_resources () { |
|
|
setup_host_resources () { |
|
|
local services="$1" loaded |
|
|
|
|
|
|
|
|
local services="$1" subservices loaded |
|
|
|
|
|
|
|
|
declare -A loaded |
|
|
declare -A loaded |
|
|
for service in $services; do |
|
|
for service in $services; do |
|
|
for subservice in $(get_ordered_service_dependencies "$service"); do |
|
|
|
|
|
|
|
|
subservices=$(get_ordered_service_dependencies "$service") || return 1 |
|
|
|
|
|
for subservice in $subservices; do |
|
|
if [ "${loaded[$subservice]}" ]; then |
|
|
if [ "${loaded[$subservice]}" ]; then |
|
|
## Prevent double inclusion of same service if this |
|
|
## Prevent double inclusion of same service if this |
|
|
## service is deps of two or more of your |
|
|
## service is deps of two or more of your |
|
@ -1469,8 +1528,8 @@ _get_compose_relations_cached () { |
|
|
relation_name relation_def target_service |
|
|
relation_name relation_def target_service |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
#debug "$FUNCNAME: STATIC cache hit $1" |
|
|
#debug "$FUNCNAME: STATIC cache hit $1" |
|
|
cat "$cache_file" |
|
|
|
|
|
touch "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
@ -1478,30 +1537,31 @@ _get_compose_relations_cached () { |
|
|
set -o pipefail |
|
|
set -o pipefail |
|
|
if [ "$compose_service_def" ]; then |
|
|
if [ "$compose_service_def" ]; then |
|
|
while read-0 relation_name relation_def; do |
|
|
while read-0 relation_name relation_def; do |
|
|
|
|
|
## XXXvlab: could we use braces here instead of parenthesis ? |
|
|
( |
|
|
( |
|
|
case "$(echo "$relation_def" | shyaml get-type 2>/dev/null)" in |
|
|
case "$(echo "$relation_def" | shyaml get-type 2>/dev/null)" in |
|
|
"str") |
|
|
"str") |
|
|
target_service="$(echo "$relation_def" | shyaml get-value 2>/dev/null)" |
|
|
target_service="$(echo "$relation_def" | shyaml get-value 2>/dev/null)" |
|
|
target_charm=$(get_service_charm "$target_service") |
|
|
|
|
|
|
|
|
target_charm=$(get_service_charm "$target_service") || return 1 |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
echo -en "$relation_name\0$target_service\0\0$tech_dep\0" |
|
|
echo -en "$relation_name\0$target_service\0\0$tech_dep\0" |
|
|
;; |
|
|
;; |
|
|
"sequence") |
|
|
"sequence") |
|
|
while read-0 target_service; do |
|
|
while read-0 target_service; do |
|
|
target_charm=$(get_service_charm "$target_service") |
|
|
|
|
|
|
|
|
target_charm=$(get_service_charm "$target_service") || return 1 |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
echo -en "$relation_name\0$target_service\0\0$tech_dep\0" |
|
|
echo -en "$relation_name\0$target_service\0\0$tech_dep\0" |
|
|
done < <(echo "$relation_def" | shyaml get-values-0 2>/dev/null) |
|
|
done < <(echo "$relation_def" | shyaml get-values-0 2>/dev/null) |
|
|
;; |
|
|
;; |
|
|
"struct") |
|
|
"struct") |
|
|
while read-0 target_service relation_config; do |
|
|
while read-0 target_service relation_config; do |
|
|
target_charm=$(get_service_charm "$target_service") |
|
|
|
|
|
|
|
|
target_charm=$(get_service_charm "$target_service") || return 1 |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_charm" "$relation_name")" |
|
|
echo -en "$relation_name\0$target_service\0$relation_config\0$tech_dep\0" |
|
|
echo -en "$relation_name\0$target_service\0$relation_config\0$tech_dep\0" |
|
|
done < <(echo "$relation_def" | shyaml key-values-0 2>/dev/null) |
|
|
done < <(echo "$relation_def" | shyaml key-values-0 2>/dev/null) |
|
|
;; |
|
|
;; |
|
|
esac |
|
|
esac |
|
|
) </dev/null >> "$cache_file" |
|
|
|
|
|
|
|
|
) </dev/null >> "$cache_file" || return 1 |
|
|
done < <(echo "$compose_service_def" | shyaml key-values-0 relations 2>/dev/null) |
|
|
done < <(echo "$compose_service_def" | shyaml key-values-0 relations 2>/dev/null) |
|
|
fi |
|
|
fi |
|
|
) |
|
|
) |
|
@ -1528,7 +1588,6 @@ get_compose_relations () { |
|
|
compose_def="$(get_compose_service_def "$service")" || return 1 |
|
|
compose_def="$(get_compose_service_def "$service")" || return 1 |
|
|
_get_compose_relations_cached "$compose_def" > "$cache_file" |
|
|
_get_compose_relations_cached "$compose_def" > "$cache_file" |
|
|
if [ "$?" != 0 ]; then |
|
|
if [ "$?" != 0 ]; then |
|
|
err "Error while looking for compose relations." |
|
|
|
|
|
rm -f "$cache_file" ## no cache |
|
|
rm -f "$cache_file" ## no cache |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
@ -1536,15 +1595,27 @@ get_compose_relations () { |
|
|
} |
|
|
} |
|
|
export -f get_compose_relations |
|
|
export -f get_compose_relations |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_compose_relation_def() { |
|
|
|
|
|
local service="$1" relation="$2" relation_name target_service relation_config tech_dep |
|
|
|
|
|
while read-0 relation_name target_service relation_config tech_dep; do |
|
|
|
|
|
[ "$relation_name" == "$relation" ] || continue |
|
|
|
|
|
printf "%s\0%s\0%s\0" "$target_service" "$relation_config" "$tech_dep" |
|
|
|
|
|
done < <(get_compose_relations "$service") || return 1 |
|
|
|
|
|
} |
|
|
|
|
|
export -f get_compose_relation_def |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
run_service_relations () { |
|
|
run_service_relations () { |
|
|
local services="$1" loaded |
|
|
|
|
|
|
|
|
local services="$1" loaded subservices |
|
|
|
|
|
|
|
|
PROJECT_NAME=$(get_default_project_name) || return 1 |
|
|
PROJECT_NAME=$(get_default_project_name) || return 1 |
|
|
|
|
|
|
|
|
export PROJECT_NAME |
|
|
export PROJECT_NAME |
|
|
|
|
|
|
|
|
declare -A loaded |
|
|
declare -A loaded |
|
|
for service in $(get_ordered_service_dependencies $services); do |
|
|
|
|
|
|
|
|
subservices=$(get_ordered_service_dependencies $services) || return 1 |
|
|
|
|
|
for service in $subservices; do |
|
|
|
|
|
|
|
|
# debug "Upping dep's relations of ${DARKYELLOW}$service${NORMAL}:" |
|
|
# debug "Upping dep's relations of ${DARKYELLOW}$service${NORMAL}:" |
|
|
for subservice in $(get_service_deps "$service") "$service"; do |
|
|
for subservice in $(get_service_deps "$service") "$service"; do |
|
@ -1805,8 +1876,8 @@ _get_master_service_for_service_cached () { |
|
|
charm requires master_charm target_charm target_service service_def found |
|
|
charm requires master_charm target_charm target_service service_def found |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
# debug "$FUNCNAME: STATIC cache hit ($1)" |
|
|
# debug "$FUNCNAME: STATIC cache hit ($1)" |
|
|
cat "$cache_file" |
|
|
|
|
|
touch "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
@ -1864,17 +1935,16 @@ get_master_service_for_service() { |
|
|
|
|
|
|
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
# debug "$FUNCNAME: SESSION cache hit ($*)" |
|
|
# debug "$FUNCNAME: SESSION cache hit ($*)" |
|
|
cat "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
charm=$(get_service_charm "$service") || return 1 |
|
|
charm=$(get_service_charm "$service") || return 1 |
|
|
metadata=$(charm.metadata "$charm" 2>/dev/null) || { |
|
|
metadata=$(charm.metadata "$charm" 2>/dev/null) || { |
|
|
metadata="" |
|
|
metadata="" |
|
|
warn "No charm $DARKPINK$charm$NORMAL found." |
|
|
warn "No charm $DARKPINK$charm$NORMAL found." |
|
|
} |
|
|
} |
|
|
result=$(_get_master_service_for_service_cached "$service" "$charm" "$metadata") || return 1 |
|
|
result=$(_get_master_service_for_service_cached "$service" "$charm" "$metadata") || return 1 |
|
|
echo "$result" | tee "$cache_file" |
|
|
|
|
|
|
|
|
echo "$result" | tee "$cache_file" || return 1 |
|
|
} |
|
|
} |
|
|
export -f get_master_service_for_service |
|
|
export -f get_master_service_for_service |
|
|
|
|
|
|
|
@ -1906,16 +1976,16 @@ export -f get_top_master_service_for_service |
|
|
## docker-compose entry (thinking of subordinates). The result |
|
|
## docker-compose entry (thinking of subordinates). The result |
|
|
## will be merge with master charms. |
|
|
## will be merge with master charms. |
|
|
_get_docker_compose_mixin_from_metadata_cached() { |
|
|
_get_docker_compose_mixin_from_metadata_cached() { |
|
|
local service="$1" charm="$2" metadata="$3" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \ |
|
|
|
|
|
|
|
|
local service="$1" charm="$2" metadata="$3" has_build_dir="$4" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \ |
|
|
metadata_file metadata volumes docker_compose subordinate image |
|
|
metadata_file metadata volumes docker_compose subordinate image |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
#debug "$FUNCNAME: STATIC cache hit $1" |
|
|
#debug "$FUNCNAME: STATIC cache hit $1" |
|
|
cat "$cache_file" |
|
|
|
|
|
touch "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
mixin=$(echo -en "labels:\n - \"compose.charm=$charm\"") |
|
|
|
|
|
|
|
|
mixin=$(echo -en "labels:\n- compose.charm=$charm") |
|
|
if [ "$metadata" ]; then |
|
|
if [ "$metadata" ]; then |
|
|
## resources to volumes |
|
|
## resources to volumes |
|
|
volumes=$( |
|
|
volumes=$( |
|
@ -1925,10 +1995,16 @@ _get_docker_compose_mixin_from_metadata_cached() { |
|
|
done < <(echo "$metadata" | shyaml get-values-0 "${resource_type}-resources" 2>/dev/null) |
|
|
done < <(echo "$metadata" | shyaml get-values-0 "${resource_type}-resources" 2>/dev/null) |
|
|
done |
|
|
done |
|
|
while read-0 resource; do |
|
|
while read-0 resource; do |
|
|
if [[ "$resource" == *:* ]]; then |
|
|
|
|
|
|
|
|
if [[ "$resource" == /*:/*:* ]]; then |
|
|
|
|
|
echo " - $resource" |
|
|
|
|
|
elif [[ "$resource" == /*:/* ]]; then |
|
|
echo " - $resource:rw" |
|
|
echo " - $resource:rw" |
|
|
else |
|
|
|
|
|
|
|
|
elif [[ "$resource" == /*:* ]]; then |
|
|
|
|
|
echo " - ${resource%%:*}:$resource" |
|
|
|
|
|
elif [[ "$resource" =~ ^/[^:]+$ ]]; then |
|
|
echo " - $resource:$resource:rw" |
|
|
echo " - $resource:$resource:rw" |
|
|
|
|
|
else |
|
|
|
|
|
die "Invalid host-resource specified in 'metadata.yml'." |
|
|
fi |
|
|
fi |
|
|
done < <(echo "$metadata" | shyaml get-values-0 "host-resources" 2>/dev/null) |
|
|
done < <(echo "$metadata" | shyaml get-values-0 "host-resources" 2>/dev/null) |
|
|
while read-0 resource; do |
|
|
while read-0 resource; do |
|
@ -1969,7 +2045,7 @@ _get_docker_compose_mixin_from_metadata_cached() { |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
image_or_build_statement="image: $image" |
|
|
image_or_build_statement="image: $image" |
|
|
elif [ -d "$(charm.get_dir "$charm")/build" ]; then |
|
|
|
|
|
|
|
|
elif [ "$has_build_dir" ]; then |
|
|
if [ "$subordinate" ]; then |
|
|
if [ "$subordinate" ]; then |
|
|
err "Subordinate charm can not have a 'build' sub directory." |
|
|
err "Subordinate charm can not have a 'build' sub directory." |
|
|
return 1 |
|
|
return 1 |
|
@ -1985,15 +2061,17 @@ export -f _get_docker_compose_mixin_from_metadata_cached |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_mixin_from_metadata() { |
|
|
get_docker_compose_mixin_from_metadata() { |
|
|
local service="$1" charm="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" |
|
|
|
|
|
|
|
|
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
#debug "$FUNCNAME: SESSION cache hit ($*)" |
|
|
#debug "$FUNCNAME: SESSION cache hit ($*)" |
|
|
cat "$cache_file" |
|
|
cat "$cache_file" |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
metadata="$(charm.metadata "$charm" 2>/dev/null)" |
|
|
|
|
|
mixin=$(_get_docker_compose_mixin_from_metadata_cached "$service" "$charm" "$metadata") || return 1 |
|
|
|
|
|
|
|
|
charm=$(get_service_charm "$service") || return 1 |
|
|
|
|
|
metadata="$(charm.metadata "$charm" 2>/dev/null)" || return 1 |
|
|
|
|
|
has_build_dir= |
|
|
|
|
|
[ -d "$(charm.get_dir "$charm")/build" ] && has_build_dir=true |
|
|
|
|
|
mixin=$(_get_docker_compose_mixin_from_metadata_cached "$service" "$charm" "$metadata" "$has_build_dir") || return 1 |
|
|
echo "$mixin" | tee "$cache_file" |
|
|
echo "$mixin" | tee "$cache_file" |
|
|
} |
|
|
} |
|
|
export -f get_docker_compose_mixin_from_metadata |
|
|
export -f get_docker_compose_mixin_from_metadata |
|
@ -2024,7 +2102,7 @@ export -f get_default_project_name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
launch_docker_compose() { |
|
|
launch_docker_compose() { |
|
|
local charm |
|
|
|
|
|
|
|
|
local charm docker_compose_tmpdir docker_compose_dir |
|
|
docker_compose_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) |
|
|
docker_compose_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) |
|
|
#debug "Creating temporary docker-compose directory in '$docker_compose_tmpdir'." |
|
|
#debug "Creating temporary docker-compose directory in '$docker_compose_tmpdir'." |
|
|
# trap_add EXIT "debug \"Removing temporary docker-compose directory in $docker_compose_tmpdir.\";\ |
|
|
# trap_add EXIT "debug \"Removing temporary docker-compose directory in $docker_compose_tmpdir.\";\ |
|
@ -2034,9 +2112,9 @@ launch_docker_compose() { |
|
|
mkdir -p "$docker_compose_tmpdir/$project" |
|
|
mkdir -p "$docker_compose_tmpdir/$project" |
|
|
docker_compose_dir="$docker_compose_tmpdir/$project" |
|
|
docker_compose_dir="$docker_compose_tmpdir/$project" |
|
|
|
|
|
|
|
|
if [ -z "$SERVICE_PACK" ]; then |
|
|
|
|
|
export SERVICE_PACK=$(get_default_target_services $SERVICE_PACK) |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
# if [ -z "$SERVICE_PACK" ]; then |
|
|
|
|
|
# export SERVICE_PACK=$(get_default_target_services $SERVICE_PACK) |
|
|
|
|
|
# fi |
|
|
get_docker_compose $SERVICE_PACK > "$docker_compose_dir/docker-compose.yml" || return 1 |
|
|
get_docker_compose $SERVICE_PACK > "$docker_compose_dir/docker-compose.yml" || return 1 |
|
|
if [ -e "$state_tmpdir/to-merge-in-docker-compose.yml" ]; then |
|
|
if [ -e "$state_tmpdir/to-merge-in-docker-compose.yml" ]; then |
|
|
# debug "Merging some config data in docker-compose.yml:" |
|
|
# debug "Merging some config data in docker-compose.yml:" |
|
@ -2063,7 +2141,11 @@ launch_docker_compose() { |
|
|
debug "${WHITE}docker-compose.yml$NORMAL for $DARKYELLOW$SERVICE_PACK$NORMAL:" |
|
|
debug "${WHITE}docker-compose.yml$NORMAL for $DARKYELLOW$SERVICE_PACK$NORMAL:" |
|
|
debug "$(cat "$docker_compose_dir/docker-compose.yml" | prefix " $GRAY|$NORMAL ")" |
|
|
debug "$(cat "$docker_compose_dir/docker-compose.yml" | prefix " $GRAY|$NORMAL ")" |
|
|
debug "${WHITE}Launching$NORMAL: docker-compose $@" |
|
|
debug "${WHITE}Launching$NORMAL: docker-compose $@" |
|
|
docker-compose "$@" |
|
|
|
|
|
|
|
|
if [ "$DRY_COMPOSE_RUN" ]; then |
|
|
|
|
|
echo docker-compose "$@" |
|
|
|
|
|
else |
|
|
|
|
|
docker-compose "$@" |
|
|
|
|
|
fi |
|
|
echo "$?" > "$docker_compose_dir/.data/errlvl" |
|
|
echo "$?" > "$docker_compose_dir/.data/errlvl" |
|
|
} | _save stdout |
|
|
} | _save stdout |
|
|
} 3>&1 1>&2 2>&3 | _save stderr 3>&1 1>&2 2>&3 |
|
|
} 3>&1 1>&2 2>&3 | _save stderr 3>&1 1>&2 2>&3 |
|
@ -2094,7 +2176,8 @@ get_compose_yml_location() { |
|
|
if [ "$DEFAULT_COMPOSE_FILE" ]; then |
|
|
if [ "$DEFAULT_COMPOSE_FILE" ]; then |
|
|
if ! [ -e "$DEFAULT_COMPOSE_FILE" ]; then |
|
|
if ! [ -e "$DEFAULT_COMPOSE_FILE" ]; then |
|
|
err "No 'compose.yml' was found in current or parent dirs," \ |
|
|
err "No 'compose.yml' was found in current or parent dirs," \ |
|
|
"and \$DEFAULT_COMPOSE_FILE points to an unexistent file." |
|
|
|
|
|
|
|
|
"and \$DEFAULT_COMPOSE_FILE points to an unexistent file." \ |
|
|
|
|
|
"(${DEFAULT_COMPOSE_FILE})" |
|
|
die "Please provide a 'compose.yml' file." |
|
|
die "Please provide a 'compose.yml' file." |
|
|
fi |
|
|
fi |
|
|
echo "$DEFAULT_COMPOSE_FILE" |
|
|
echo "$DEFAULT_COMPOSE_FILE" |
|
@ -2135,6 +2218,7 @@ get_master_services() { |
|
|
echo "$master_service" |
|
|
echo "$master_service" |
|
|
loaded["$master_service"]=1 |
|
|
loaded["$master_service"]=1 |
|
|
done | xargs echo |
|
|
done | xargs echo |
|
|
|
|
|
return "${PIPESTATUS[0]}" |
|
|
} |
|
|
} |
|
|
export -f get_master_services |
|
|
export -f get_master_services |
|
|
|
|
|
|
|
@ -2148,18 +2232,50 @@ _setup_state_dir() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_opts_list() { |
|
|
|
|
|
local action="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$action"; cat "$(which docker-compose)" | md5_compat)" |
|
|
|
|
|
|
|
|
get_docker_compose_action_help_msg() { |
|
|
|
|
|
local action="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$action"; cat "$(which docker-compose)" | md5_compat)" \ |
|
|
|
|
|
docker_compose_help_msg |
|
|
if [ -e "$cache_file" ]; then |
|
|
if [ -e "$cache_file" ]; then |
|
|
cat "$cache_file" |
|
|
|
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
return 0 |
|
|
return 0 |
|
|
fi |
|
|
fi |
|
|
docker_compose_help_msg=$(docker-compose "$action" --help 2>/dev/null) || return 1 |
|
|
docker_compose_help_msg=$(docker-compose "$action" --help 2>/dev/null) || return 1 |
|
|
|
|
|
echo "$docker_compose_help_msg" | |
|
|
|
|
|
tee "$cache_file" || return 1 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_action_usage() { |
|
|
|
|
|
local action="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$action"; cat "$(which docker-compose)" | md5_compat)" \ |
|
|
|
|
|
docker_compose_help_msg |
|
|
|
|
|
if [ -e "$cache_file" ]; then |
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
|
|
|
return 0 |
|
|
|
|
|
fi |
|
|
|
|
|
docker_compose_help_msg=$(get_docker_compose_action_help_msg "$action") || return 1 |
|
|
|
|
|
echo "$docker_compose_help_msg" | |
|
|
|
|
|
grep -m 1 "^Usage:" -A 10000 | |
|
|
|
|
|
egrep -m 1 "^\$" -B 10000 | |
|
|
|
|
|
xargs echo | |
|
|
|
|
|
sed -r 's/^Usage: //g' | |
|
|
|
|
|
tee "$cache_file" || return 1 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_opts_list() { |
|
|
|
|
|
local action="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$action"; cat "$(which docker-compose)" | md5_compat)" \ |
|
|
|
|
|
docker_compose_help_msg |
|
|
|
|
|
if [ -e "$cache_file" ]; then |
|
|
|
|
|
cat "$cache_file" && |
|
|
|
|
|
touch "$cache_file" || return 1 |
|
|
|
|
|
return 0 |
|
|
|
|
|
fi |
|
|
|
|
|
docker_compose_help_msg=$(get_docker_compose_action_help_msg "$action") || return 1 |
|
|
echo "$docker_compose_help_msg" | grep '^Options:' -A 20000 | |
|
|
echo "$docker_compose_help_msg" | grep '^Options:' -A 20000 | |
|
|
tail -n +2 | |
|
|
tail -n +2 | |
|
|
egrep "^\s+-" | |
|
|
egrep "^\s+-" | |
|
|
sed -r 's/\s+((((-[a-zA-Z]|--[a-zA-Z0-9-]+)( [A-Z=]+|=[^ ]+)?)(, )?)+)\s+.*$/\1/g' | |
|
|
sed -r 's/\s+((((-[a-zA-Z]|--[a-zA-Z0-9-]+)( [A-Z=]+|=[^ ]+)?)(, )?)+)\s+.*$/\1/g' | |
|
|
tee "$cache_file" |
|
|
|
|
|
|
|
|
tee "$cache_file" || return 1 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_MULTIOPTION_REGEX='^((-[a-zA-Z]|--[a-zA-Z0-9-]+)(, )?)+' |
|
|
_MULTIOPTION_REGEX='^((-[a-zA-Z]|--[a-zA-Z0-9-]+)(, )?)+' |
|
@ -2312,7 +2428,7 @@ digraph g { |
|
|
ratio = auto; |
|
|
ratio = auto; |
|
|
EOF |
|
|
EOF |
|
|
for target_service in "$@"; do |
|
|
for target_service in "$@"; do |
|
|
services=$(get_ordered_service_dependencies "$target_service") |
|
|
|
|
|
|
|
|
services=$(get_ordered_service_dependencies "$target_service") || return 1 |
|
|
for service in $services; do |
|
|
for service in $services; do |
|
|
[ "${entries[$service]}" ] && continue || entries[$service]=1 |
|
|
[ "${entries[$service]}" ] && continue || entries[$service]=1 |
|
|
if cla_contains "$service" "${services[@]}"; then |
|
|
if cla_contains "$service" "${services[@]}"; then |
|
@ -2329,6 +2445,11 @@ EOF |
|
|
|
|
|
|
|
|
[ "$SOURCED" ] && return 0 |
|
|
[ "$SOURCED" ] && return 0 |
|
|
|
|
|
|
|
|
|
|
|
# if [[ "$UID" != 0 ]]; then |
|
|
|
|
|
# die "'$exname' requires root permissions (for now). Please run as root." |
|
|
|
|
|
# fi |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then |
|
|
if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then |
|
|
if [ -r /etc/default/charm ]; then |
|
|
if [ -r /etc/default/charm ]; then |
|
|
. /etc/default/charm |
|
|
. /etc/default/charm |
|
@ -2362,9 +2483,12 @@ export DOCKER_HOST_NET DOCKER_HOST_IP |
|
|
## Argument parsing |
|
|
## Argument parsing |
|
|
## |
|
|
## |
|
|
|
|
|
|
|
|
|
|
|
services=() |
|
|
remainder_args=() |
|
|
remainder_args=() |
|
|
compose_opts=() |
|
|
compose_opts=() |
|
|
action_opts=() |
|
|
action_opts=() |
|
|
|
|
|
services_args=() |
|
|
|
|
|
pos_arg_ct=0 |
|
|
no_hooks= |
|
|
no_hooks= |
|
|
no_init= |
|
|
no_init= |
|
|
action= |
|
|
action= |
|
@ -2410,22 +2534,41 @@ while [ "$#" != 0 ]; do |
|
|
export DEBUG=true |
|
|
export DEBUG=true |
|
|
export VERBOSE=true |
|
|
export VERBOSE=true |
|
|
;; |
|
|
;; |
|
|
|
|
|
--dirs) |
|
|
|
|
|
echo "CACHEDIR: $CACHEDIR" |
|
|
|
|
|
echo "VARDIR: $VARDIR" |
|
|
|
|
|
exit 0 |
|
|
|
|
|
;; |
|
|
|
|
|
--dry-compose-run) |
|
|
|
|
|
export DRY_COMPOSE_RUN=true |
|
|
|
|
|
;; |
|
|
--*|-*) |
|
|
--*|-*) |
|
|
compose_opts+=("$1") |
|
|
compose_opts+=("$1") |
|
|
;; |
|
|
;; |
|
|
*) |
|
|
*) |
|
|
action="$1" |
|
|
action="$1" |
|
|
stage="action" |
|
|
stage="action" |
|
|
DC_MATCH_MULTI=$(get_docker_compose_multi_opts_list "$action") && |
|
|
|
|
|
DC_MATCH_SINGLE="$(get_docker_compose_single_opts_list "$action")" |
|
|
|
|
|
if [ "$DC_MATCH_MULTI" ]; then |
|
|
|
|
|
DC_MATCH_SINGLE="$DC_MATCH_SINGLE $(echo "$DC_MATCH_MULTI" | sed -r 's/( |$)/=\* /g')" |
|
|
|
|
|
|
|
|
if DC_USAGE=$(get_docker_compose_action_usage "$action"); then |
|
|
|
|
|
is_docker_compose_action=true |
|
|
|
|
|
DC_MATCH_MULTI=$(get_docker_compose_multi_opts_list "$action") && |
|
|
|
|
|
DC_MATCH_SINGLE="$(get_docker_compose_single_opts_list "$action")" |
|
|
|
|
|
if [ "$DC_MATCH_MULTI" ]; then |
|
|
|
|
|
DC_MATCH_SINGLE="$DC_MATCH_SINGLE $(echo "$DC_MATCH_MULTI" | sed -r 's/( |$)/=\* /g')" |
|
|
|
|
|
fi |
|
|
|
|
|
pos_args=($(echo "$DC_USAGE" | sed -r 's/\[-[^]]+\] ?//g;s/\[options\] ?//g')) |
|
|
|
|
|
pos_args=("${pos_args[@]:1}") |
|
|
|
|
|
# echo "USAGE: $DC_USAGE" |
|
|
|
|
|
# echo "pos_args: ${pos_args[@]}" |
|
|
|
|
|
# echo "MULTI: $DC_MATCH_MULTI" |
|
|
|
|
|
# echo "SINGLE: $DC_MATCH_SINGLE" |
|
|
|
|
|
# exit 1 |
|
|
|
|
|
else |
|
|
|
|
|
stage="remainder" |
|
|
fi |
|
|
fi |
|
|
is_docker_compose_action=true |
|
|
|
|
|
;; |
|
|
;; |
|
|
esac |
|
|
esac |
|
|
;; |
|
|
;; |
|
|
"action") |
|
|
|
|
|
|
|
|
"action") ## Only for docker-compose actions |
|
|
case "$1" in |
|
|
case "$1" in |
|
|
--help|-h) |
|
|
--help|-h) |
|
|
no_init=true ; no_hooks=true ; no_relations=true |
|
|
no_init=true ; no_hooks=true ; no_relations=true |
|
@ -2434,10 +2577,10 @@ while [ "$#" != 0 ]; do |
|
|
--*|-*) |
|
|
--*|-*) |
|
|
if [ "$is_docker_compose_action" ]; then |
|
|
if [ "$is_docker_compose_action" ]; then |
|
|
if str_matches "$1" $DC_MATCH_MULTI; then |
|
|
if str_matches "$1" $DC_MATCH_MULTI; then |
|
|
action_opts=("$1" "$2") |
|
|
|
|
|
|
|
|
action_opts+=("$1" "$2") |
|
|
shift; |
|
|
shift; |
|
|
elif str_matches "$1" $DC_MATCH_SINGLE; then |
|
|
elif str_matches "$1" $DC_MATCH_SINGLE; then |
|
|
action_opts=("$1") |
|
|
|
|
|
|
|
|
action_opts+=("$1") |
|
|
else |
|
|
else |
|
|
err "Unknown option '$1'. Please check help." |
|
|
err "Unknown option '$1'. Please check help." |
|
|
docker-compose "$action" --help >&2 |
|
|
docker-compose "$action" --help >&2 |
|
@ -2446,21 +2589,33 @@ while [ "$#" != 0 ]; do |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
;; |
|
|
*) |
|
|
*) |
|
|
action_posargs+=("$1") |
|
|
|
|
|
stage="remainder" |
|
|
|
|
|
|
|
|
# echo "LOOP $1 : pos_arg: $pos_arg_ct // ${pos_args[$pos_arg_ct]}" |
|
|
|
|
|
if [[ "${pos_args[$pos_arg_ct]}" == "[SERVICE...]" ]]; then |
|
|
|
|
|
services_args+=("$1") |
|
|
|
|
|
elif [[ "${pos_args[$pos_arg_ct]}" == "SERVICE" ]]; then |
|
|
|
|
|
services_args=("$1") || exit 1 |
|
|
|
|
|
stage="remainder" |
|
|
|
|
|
else |
|
|
|
|
|
action_posargs+=("$1") |
|
|
|
|
|
((pos_arg_ct++)) |
|
|
|
|
|
fi |
|
|
;; |
|
|
;; |
|
|
esac |
|
|
esac |
|
|
;; |
|
|
;; |
|
|
"remainder") |
|
|
"remainder") |
|
|
remainder_args+=("$@") |
|
|
remainder_args+=("$@") |
|
|
break 3;; |
|
|
|
|
|
|
|
|
break 3 |
|
|
|
|
|
;; |
|
|
esac |
|
|
esac |
|
|
shift |
|
|
shift |
|
|
done |
|
|
done |
|
|
|
|
|
|
|
|
[ "${compose_opts[*]}" ] && debug "Main docker-compose opts: ${compose_opts[*]}" |
|
|
|
|
|
[ "${action_opts[*]}" ] && debug "Action $DARKCYAN$action$NORMAL with opts: ${action_opts[*]}" |
|
|
|
|
|
[ "${remainder_args[*]}" ] && debug "Remainder args: ${remainder_args[*]}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ "${services[*]}" ] && debug " ${DARKWHITE}Services:$NORMAL ${services[*]}" |
|
|
|
|
|
[ "${compose_opts[*]}" ] && debug " ${DARKWHITE}Main docker-compose opts:$NORMAL ${compose_opts[*]}" |
|
|
|
|
|
[ "${action_posargs[*]}" ] && debug " ${DARKWHITE}Main docker-compose pos args:$NORMAL ${action_posargs[*]}" |
|
|
|
|
|
[ "${action_opts[*]}" ] && debug " ${DARKWHITE}Action $DARKCYAN$action$NORMAL with opts:$NORMAL ${action_opts[*]}" |
|
|
|
|
|
[ "${remainder_args[*]}" ] && debug " ${DARKWHITE}Remainder args:$NORMAL ${remainder_args[*]}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
## |
|
@ -2496,41 +2651,40 @@ charm.sanity_checks || die "Sanity checks about charm-store failed. Please corre |
|
|
## Get services in command line. |
|
|
## Get services in command line. |
|
|
## |
|
|
## |
|
|
|
|
|
|
|
|
is_service_action= |
|
|
|
|
|
case "$action" in |
|
|
|
|
|
up|build|start|stop|config|graph) |
|
|
|
|
|
services="$(get_default_target_services "${action_posargs[@]}" "${remainder_args[@]}")" || exit 1 |
|
|
|
|
|
orig_services="${action_posargs[@]:1}" |
|
|
|
|
|
;; |
|
|
|
|
|
run) |
|
|
|
|
|
services="${action_posargs[0]}" |
|
|
|
|
|
;; |
|
|
|
|
|
""|down) |
|
|
|
|
|
services= |
|
|
|
|
|
;; |
|
|
|
|
|
*) |
|
|
|
|
|
if is_service_action=$(has_service_action "${action_posargs[0]}" "$action"); then |
|
|
|
|
|
{ |
|
|
|
|
|
read-0 action_type |
|
|
|
|
|
case "$action_type" in |
|
|
|
|
|
"relation") |
|
|
|
|
|
read-0 _ target_service _target_charm relation_name |
|
|
|
|
|
debug "Found action $DARKYELLOW${action_posargs[0]}$NORMAL/$DARKBLUE$relation_name$NORMAL/$DARKCYAN$action$NORMAL (in $DARKYELLOW$target_service$NORMAL)" |
|
|
|
|
|
;; |
|
|
|
|
|
"direct") |
|
|
|
|
|
debug "Found action $DARKYELLOW${action_posargs[0]}$NORMAL.$DARKCYAN$action$NORMAL" |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
} < <(has_service_action "${action_posargs[0]}" "$action") |
|
|
|
|
|
services="${action_posargs[0]}" |
|
|
|
|
|
else |
|
|
|
|
|
services="$(get_default_target_services "${action_posargs[@]}")" |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
|
|
|
if [ -z "$is_docker_compose_action" -a "$action" ]; then |
|
|
|
|
|
|
|
|
|
|
|
if is_service_action=$(has_service_action "${action_posargs[0]}" "$action"); then |
|
|
|
|
|
{ |
|
|
|
|
|
read-0 action_type |
|
|
|
|
|
case "$action_type" in |
|
|
|
|
|
"relation") |
|
|
|
|
|
read-0 _ target_service _target_charm relation_name |
|
|
|
|
|
debug "Found action $DARKYELLOW${action_posargs[0]}$NORMAL/$DARKBLUE$relation_name$NORMAL/$DARKCYAN$action$NORMAL (in $DARKYELLOW$target_service$NORMAL)" |
|
|
|
|
|
;; |
|
|
|
|
|
"direct") |
|
|
|
|
|
debug "Found action $DARKYELLOW${action_posargs[0]}$NORMAL.$DARKCYAN$action$NORMAL" |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
} < <(has_service_action "${action_posargs[0]}" "$action") |
|
|
|
|
|
services=("${action_posargs[0]}") |
|
|
|
|
|
else |
|
|
|
|
|
die "Unknown command: It doesn't match any docker-compose commands nor inner charm actions." |
|
|
|
|
|
fi |
|
|
|
|
|
else |
|
|
|
|
|
if [ "$action" == "up" -a "${#services_args[@]}" == 0 ]; then |
|
|
|
|
|
services_args=($(shyaml keys <"$COMPOSE_YML_FILE")) |
|
|
|
|
|
fi |
|
|
|
|
|
if [ "$action" == "config" ]; then |
|
|
|
|
|
services_args=("${action_posargs[@]}") |
|
|
|
|
|
fi |
|
|
|
|
|
if [ "$is_docker_compose_action" -a "${#services_args[@]}" -gt 0 ]; then |
|
|
|
|
|
services=($(get_master_services "${services_args[@]}")) || exit 1 |
|
|
|
|
|
action_posargs+=("${services[@]}") |
|
|
|
|
|
fi |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose $services >/dev/null || { ## precalculate variable \$_current_docker_compose |
|
|
|
|
|
|
|
|
get_docker_compose "${services[@]}" >/dev/null || { ## precalculate variable \$_current_docker_compose |
|
|
err "Fails to compile base 'docker-compose.yml'" |
|
|
err "Fails to compile base 'docker-compose.yml'" |
|
|
exit 1 |
|
|
exit 1 |
|
|
} |
|
|
} |
|
@ -2546,7 +2700,7 @@ case "$action" in |
|
|
full_init=true |
|
|
full_init=true |
|
|
post_hook=true |
|
|
post_hook=true |
|
|
;; |
|
|
;; |
|
|
""|down) |
|
|
|
|
|
|
|
|
""|down|restart|logs|config) |
|
|
full_init= |
|
|
full_init= |
|
|
;; |
|
|
;; |
|
|
*) |
|
|
*) |
|
@ -2572,24 +2726,22 @@ if [ "$full_init" ]; then |
|
|
|
|
|
|
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
export SERVICE_PACK="$services" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export SERVICE_PACK="${services[*]}" |
|
|
|
|
|
|
|
|
## |
|
|
## |
|
|
## Docker-compose |
|
|
## Docker-compose |
|
|
## |
|
|
## |
|
|
|
|
|
|
|
|
case "$action" in |
|
|
case "$action" in |
|
|
up|start|stop|build) |
|
|
|
|
|
master_services=$(get_master_services $SERVICE_PACK) || exit 1 |
|
|
|
|
|
|
|
|
up|start|stop|build|run) |
|
|
if [[ "$action" == "up" ]] && ! array_member action_opts -d; then ## force daemon mode for up |
|
|
if [[ "$action" == "up" ]] && ! array_member action_opts -d; then ## force daemon mode for up |
|
|
action_opts=("-d" "${action_opts[@]}") |
|
|
action_opts=("-d" "${action_opts[@]}") |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" $master_services |
|
|
|
|
|
|
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${action_posargs[@]}" "${remainder_args[@]}" |
|
|
;; |
|
|
;; |
|
|
run) |
|
|
|
|
|
master_service=$(get_master_services $SERVICE_PACK) || exit 1 |
|
|
|
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "$master_service" "${remainder_args[@]}" |
|
|
|
|
|
|
|
|
"") |
|
|
|
|
|
launch_docker_compose "${compose_opts[@]}" |
|
|
;; |
|
|
;; |
|
|
# enter) |
|
|
# enter) |
|
|
# master_service=$(get_master_services $SERVICE_PACK) || exit 1 |
|
|
# master_service=$(get_master_services $SERVICE_PACK) || exit 1 |
|
@ -2601,23 +2753,27 @@ case "$action" in |
|
|
;; |
|
|
;; |
|
|
config) |
|
|
config) |
|
|
## removing the services |
|
|
## removing the services |
|
|
|
|
|
services=($(get_master_services "${action_posargs[@]}")) || exit 1 |
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${remainder_args[@]}" |
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${remainder_args[@]}" |
|
|
warn "Runtime configuration modification (from relations) are not included here." |
|
|
warn "Runtime configuration modification (from relations) are not included here." |
|
|
;; |
|
|
;; |
|
|
down) |
|
|
down) |
|
|
remainder_args+=("--remove-orphans") |
|
|
|
|
|
|
|
|
if ! array_member action_opts --remove-orphans; then ## force daemon mode for up |
|
|
|
|
|
debug "Adding a default argument of '--remove-orphans'" |
|
|
|
|
|
action_opts+=("--remove-orphans") |
|
|
|
|
|
fi |
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${remainder_args[@]}" |
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${remainder_args[@]}" |
|
|
;; |
|
|
;; |
|
|
*) |
|
|
*) |
|
|
if [ "$is_service_action" ]; then |
|
|
if [ "$is_service_action" ]; then |
|
|
run_service_action "$SERVICE_PACK" "$action" "${remainder_args[@]}" |
|
|
run_service_action "$SERVICE_PACK" "$action" "${remainder_args[@]}" |
|
|
else |
|
|
else |
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${remainder_args[@]}" |
|
|
|
|
|
|
|
|
launch_docker_compose "${compose_opts[@]}" "$action" "${action_opts[@]}" "${action_posargs[@]}" "${remainder_args[@]}" |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
;; |
|
|
esac |
|
|
esac |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$post_hook" ]; then |
|
|
|
|
|
run_service_hook "$services" post_deploy || exit 1 |
|
|
|
|
|
|
|
|
if [ "$post_hook" -a "${#services[@]}" != 0 ]; then |
|
|
|
|
|
run_service_hook "${services[@]}" post_deploy || exit 1 |
|
|
fi |
|
|
fi |