Compare commits

...

6 Commits

  1. 597
      bin/compose-core

597
bin/compose-core

@ -82,6 +82,9 @@ $WHITE$exname$NORMAL reads '/etc/compose.conf' for global variables, and
"
time_now() { date +%s.%3N; }
time_elapsed() { echo "scale=3; $2 - $1" | bc; }
## XXXvlab: this doesn't seem to work when 'compose' is called in
## a hook of a charm.
#[[ "${BASH_SOURCE[0]}" == "" ]] && SOURCED=true
@ -101,6 +104,8 @@ else
fi
export VARDIR CACHEDIR
export SERVICE_STATE_PATH=${SERVICE_STATE_PATH:-/var/lib/compose/state}
md5_compat() { md5sum | cut -c -32; }
quick_cat_file() { quick_cat_stdin < "$1"; }
@ -159,6 +164,82 @@ wyq-r() {
}
err-d () {
local msg="$*"
shift
err "$msg"
print:traceback 1
}
print:traceback() {
local omit_level="${1:-0}"
if [ -z "$DEBUG" ]; then
echo " Note: traceback available if you provide {--debug|-d} option." >&2
return 0
fi
echo "${WHITE}Traceback (most recent call last):${NORMAL}" >&2
local i
for ((i=${#FUNCNAME[@]} - 1; i > "$omit_level"; i--)); do
local file="${BASH_SOURCE[$i]}"
local line="${BASH_LINENO[$i - 1]}"
local func="${FUNCNAME[$i]}"
if [[ -f "$file" ]]; then
# Get total number of lines in the file
local total_lines
total_lines=$(wc -l < "$file")
# Calculate start and end lines for context
local start_line=$((line - 2))
local end_line=$((line + 2))
[[ $start_line -lt 1 ]] && start_line=1
[[ $end_line -gt $total_lines ]] && end_line=$total_lines
# Extract context lines
mapfile -s $((start_line - 1)) -n $((end_line - start_line + 1)) context_lines < "$file"
# Calculate minimal indentation
local min_indent=9999
for line_text in "${context_lines[@]}"; do
if [[ -n "$line_text" ]]; then
# Get leading whitespace
local leading_whitespace="${line_text%%[![:space:]]*}"
local indent=${#leading_whitespace}
if [[ $indent -lt $min_indent ]]; then
min_indent=$indent
fi
fi
done
# Remove minimal indentation from each line
for idx in "${!context_lines[@]}"; do
context_lines[$idx]="${context_lines[$idx]:$min_indent}"
done
else
context_lines=("<source unavailable>")
min_indent=0
start_line=1
end_line=1
fi
# Print the traceback frame
echo " File \"$file\", line $line, in ${WHITE}$func${NORMAL}:"
# Print the context with line numbers
local current_line=$start_line
for context_line in "${context_lines[@]}"; do
context_line="${context_line%$'\n'}"
if [[ $current_line -eq $line ]]; then
echo " ${DARKYELLOW}$current_line${NORMAL} ${context_line}"
else
echo " ${DARKGRAY}$current_line${NORMAL} ${context_line}"
fi
((current_line++))
done
done >&2
}
clean_cache() {
local i=0
for f in $(ls -t "$CACHEDIR/"*.cache.* 2>/dev/null | tail -n +500); do
@ -1378,7 +1459,6 @@ export -f _get_service_charm_cached
get_service_charm () {
local service="$1"
if [ -z "$service" ]; then
echo ${FUNCNAME[@]} >&2
print_syntax_error "$FUNCNAME: Please specify a service as first argument."
return 1
fi
@ -2398,16 +2478,21 @@ export -f get_compose_relations
get_all_services() {
local cache_file="$state_tmpdir/$FUNCNAME.cache.$(H "$GLOBAL_ALL_RELATIONS_HASH")" \
s rn ts rc td services
local services compose_yml_services service
if [ -z "$GLOBAL_ALL_RELATIONS_HASH" ]; then
err-d "Can't access global \$GLOBAL_ALL_RELATIONS_HASH"
return 1
fi
local cache_file="$CACHEDIR/$FUNCNAME.cache.$(H "$GLOBAL_ALL_RELATIONS_HASH" "$(declare -f "$FUNCNAME")")" \
s rn ts rc td services service
if [ -e "$cache_file" ]; then
#debug "$FUNCNAME: SESSION cache hit $1"
#debug "$FUNCNAME: cache hit $1"
cat "$cache_file"
return 0
fi
if [ -z "$GLOBAL_ALL_RELATIONS" ]; then
err "Can't access global \$GLOBAL_ALL_RELATIONS"
err-d "Can't access global \$GLOBAL_ALL_RELATIONS"
return 1
fi
@ -2418,8 +2503,17 @@ get_all_services() {
services["$service"]=1
echo "$service"
done
done < <(cat "$GLOBAL_ALL_RELATIONS") > "$cache_file"
done < "$GLOBAL_ALL_RELATIONS" > "$cache_file.wip"
compose_yml_services=($(compose:yml:root:services)) || return 1
for service in "${compose_yml_services[@]}"; do
[ "${services[$service]}" ] && continue
services["$service"]=1
echo "$service"
done >> "$cache_file.wip"
mv "$cache_file"{.wip,} || return 1
cat "$cache_file"
}
export -f get_all_services
@ -2435,7 +2529,7 @@ get_service_relations () {
fi
if [ -z "$GLOBAL_ALL_RELATIONS" ]; then
err "Can't access global \$GLOBAL_ALL_RELATIONS"
err-d "Can't access global \$GLOBAL_ALL_RELATIONS"
return 1
fi
@ -2483,25 +2577,26 @@ export -f get_service_relation
## (base_service, relation_config)
##
get_service_incoming_relations() {
local service="$1" relation="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$(H "$@" "$GLOBAL_ALL_RELATIONS_HASH")" \
if [ -z "$SUBSET_ALL_RELATIONS_HASH" ]; then
err-d "Expected \$SUBSET_ALL_RELATIONS_HASH to be set."
return 1
fi
local service="$1" relation="$2" \
cache_file="$state_tmpdir/$FUNCNAME.cache.$(H "$@" "$SUBSET_ALL_RELATIONS_HASH")" \
s rn ts rc td
if [ -e "$cache_file" ]; then
#debug "$FUNCNAME: SESSION cache hit $1"
debug "$FUNCNAME: SESSION cache hit $1"
cat "$cache_file"
return 0
fi
if [ -z "$GLOBAL_ALL_RELATIONS" ]; then
err "Can't access global \$GLOBAL_ALL_RELATIONS"
return 1
fi
while read-0 s rn ts rc _td; do
[[ "$ts" == "$service" ]] || continue
[[ "$rn" == "$relation" ]] || continue
relation_data_file=$(get_relation_data_file "$s" "$ts" "$rn" "$rc") || return 1
printf "%s\0" "$s" "$(cat "$relation_data_file")"
done < "$GLOBAL_ALL_RELATIONS" > "$cache_file"
printf "%s\0" "$s" "$(cat "$relation_data_file")" || return 1
debug "Found relation $rn from $s to $ts" >&2
done < "$SUBSET_ALL_RELATIONS" > "$cache_file.wip"
mv "$cache_file"{.wip,} || return 1
cat "$cache_file"
}
export -f get_service_incoming_relations
@ -2841,14 +2936,170 @@ _out_after_value_from_def() {
}
get_all_relations () {
local cache_file="$state_tmpdir/$FUNCNAME.cache.$(H "$@" "$(declare -p without_relations)")" \
services
get_all_compose_yml_service() {
if [ -z "$COMPOSE_YML_CONTENT_HASH" ]; then
COMPOSE_YML_CONTENT_HASH=$(compose:yml:hash) || {
err "Failed to get compose yml hash"
return 1
}
fi
local cache_file="$CACHEDIR/$FUNCNAME.cache.$COMPOSE_YML_CONTENT_HASH"
if [ -e "${cache_file}" ]; then
#debug "$FUNCNAME: cache hit: ${cache_file}"
cat "${cache_file}"
return 0
fi
compose_yml_content=$(get_compose_yml_content) || return 1
printf "%s" "${compose_yml_content}" | shyaml keys-0 2>/dev/null > "${cache_file}.wip" || {
err "Failed to get keys of compose content."
return 1
}
mv "${cache_file}"{.wip,} || return 1
cat "${cache_file}"
}
## Outputs all relations array.
_service:all:relations_cached() {
local services service E
services=($(compose:yml:root:services)) || return 1
get_all_relations "${services[@]}" || return 1
}
## Outputs all relations array.
service:all:relations() {
if [ -z "$COMPOSE_YML_CONTENT_HASH" ]; then
COMPOSE_YML_CONTENT_HASH=$(compose:yml:hash) || {
err "Failed to get compose yml hash."
return 1
}
fi
local cache_file="$CACHEDIR/$FUNCNAME.cache.$COMPOSE_YML_CONTENT_HASH"
if [ -e "${cache_file}" ]; then
# debug "$FUNCNAME: SESSION cache hit $1"
cat "${cache_file}"
return 0
fi
_service:all:relations_cached > "${cache_file}.wip" || {
err-d "Failed to compute all relations."
return 1
}
mv "${cache_file}"{.wip,} || return 1
cat "${cache_file}"
}
_service:all:relations_hash_cached() {
if [ -z "$COMPOSE_YML_CONTENT_HASH" ]; then
COMPOSE_YML_CONTENT_HASH=$(compose:yml:hash) || {
err "Failed to get compose yml hash."
return 1
}
fi
local cache_file="$CACHEDIR/$FUNCNAME.cache.$COMPOSE_YML_CONTENT_HASH" \
hash
if [ -e "${cache_file}" ]; then
# debug "$FUNCNAME: SESSION cache hit $1"
cat "${cache_file}"
return 0
fi
service:all:relations > "${cache_file}.pre" || {
err-d "Failed to get all relations."
return 1
}
{
p0 "$(hash_get < "${cache_file}.pre")" || return 1
cat "${cache_file}.pre"
rm "${cache_file}.pre"
} > "${cache_file}".wip || return 1
mv "${cache_file}"{.wip,} || return 1
cat "${cache_file}"
}
## Get all relations from all services in the current compose file.
## Sets GLOBAL_ALL_RELATIONS_HASH and returns all relations array.
service:all:set_relations_hash() {
if [ -n "$GLOBAL_ALL_RELATIONS" ]; then
if [ -z "$GLOBAL_ALL_RELATIONS_HASH" ]; then
err "Can't access global \$GLOBAL_ALL_RELATIONS_HASH"
echo " (despite \$GLOBAL_ALL_RELATIONS being set)" >&2
return 1
fi
return 0
fi
## sets COMPOSE_YML_CONTENT_HASH
_service:all:relations_hash_cached >/dev/null || return 1
{
read-0 GLOBAL_ALL_RELATIONS_HASH || return 1
export GLOBAL_ALL_RELATIONS_HASH
## transfer to statedir
export GLOBAL_ALL_RELATIONS="$state_tmpdir/$FUNCNAME.cache.$COMPOSE_YML_CONTENT_HASH"
cat > "$GLOBAL_ALL_RELATIONS"
} < <(_service:all:relations_hash_cached)
if [ -z "$GLOBAL_ALL_RELATIONS" ]; then
err "Failed to set \$GLOBAL_ALL_RELATIONS."
return 1
fi
if [ -z "$GLOBAL_ALL_RELATIONS_HASH" ]; then
err "Failed to set \$GLOBAL_ALL_RELATIONS_HASH."
return 1
fi
}
get_subset_relations () {
local service all_services services start
if [ -n "$SUBSET_ALL_RELATIONS" ]; then
return 0
fi
if [ -z "$GLOBAL_ALL_RELATIONS_HASH" ]; then
err-d "Can't access global \$GLOBAL_ALL_RELATIONS_HASH"
return 1
fi
cache_hash=$(H "$@" "$GLOBAL_ALL_RELATIONS_HASH" "$(declare -f get_subset_relations)")
local cache_file="$CACHEDIR/$FUNCNAME.cache.$cache_hash"
if [ -e "${cache_file}" ]; then
export SUBSET_ALL_RELATIONS="$cache_file"
hash=$(hash_get < "$cache_file") || return 1
export SUBSET_ALL_RELATIONS_HASH="$hash"
cat "${cache_file}"
return 0
fi
## collect all connected services first
all_services=("$@")
while [ "${#all_services[@]}" != 0 ]; do
array_pop all_services service
#debug " Getting relations for $DARKYELLOW$service$NORMAL"
while read-0 s rn ts rc td; do
[[ "$s" == "$service" ]] || continue
#debug " adding relation $DARKBLUE$rn$NORMAL to $DARKYELLOW$ts$NORMAL"
p0 "$service" "$rn" "$ts" "$rc" "$td"
[ -n "${services[$ts]}" ] || all_services+=("$ts")
done < "$GLOBAL_ALL_RELATIONS"
services["$service"]=1
done > "$cache_file.wip"
mv "$cache_file"{.wip,} || return 1
export SUBSET_ALL_RELATIONS="$cache_file"
hash=$(hash_get < "$cache_file") || return 1
export SUBSET_ALL_RELATIONS_HASH="$hash"
cat "$cache_file"
}
get_all_relations () {
if [ -z "$COMPOSE_YML_CONTENT_HASH" ]; then
COMPOSE_YML_CONTENT_HASH=$(compose:yml:hash) || return 1
fi
if [ -n "$GLOBAL_ALL_RELATIONS" ]; then
cat "$GLOBAL_ALL_RELATIONS" || return 1
return 0
fi
local cache_file="$state_tmpdir/$FUNCNAME.cache.$(H "$@" "$COMPOSE_YML_CONTENT_HASH" "$(declare -p without_relations)")" \
services all_services service services_uses services_provides \
changed summon required recommended optional
if [ -e "${cache_file}" ]; then
#debug "$FUNCNAME: SESSION cache hit $1"
@ -2860,11 +3111,11 @@ get_all_relations () {
declare -A services
services_uses=()
## XXXvlab: bwerk, leveraging cache to be able to get the errorlevel here.
_get_services_uses "$@" || return 1
_get_services_uses "$@" >/dev/null || return 1
array_read-0 services_uses < <(_get_services_uses "$@")
services_provides=()
## XXXvlab: bwerk, leveraging cache to be able to get the errorlevel here.
_get_services_provides "$@" || return 1
_get_services_provides "$@" >/dev/null || return 1
array_read-0 services_provides < <(_get_services_provides "$@")
for service in "$@"; do
@ -3096,7 +3347,7 @@ get_all_relations () {
while read-0 p s rn ts rc td; do
if [ -z "$p" ] || [ "$p" == "," ]; then
relation_done["$s:$rn"]=1
# printf " .. %-30s %-30s %-30s\n" "--" "$s" "$rn" >&2
# printf " .. %-30s %-30s %-30s\n" "$s" "$ts" "$rn" >&2
printf "%s\0" "$s" "$rn" "$ts" "$rc" "$td" >> "${cache_file}.wip.final"
had_new_relation=1
else
@ -3823,25 +4074,10 @@ clean_unused_docker_compose() {
export -f clean_unused_docker_compose
stdin_get_hash() {
local sha
sha=$(sha256sum) || return 1
sha=${sha:0:64}
echo "$sha"
}
export -f stdin_get_hash
file_get_hash() {
stdin_get_hash < "$1" || return 1
}
export -f file_get_hash
docker_compose_store() {
local file="$1" sha
sha=$(file_get_hash "$file") || return 1
sha=$(hash_get 64 < "$file") || return 1
project=$(get_default_project_name) || return 1
dst="/var/lib/compose/docker-compose/$sha/$project"
mkdir -p "$dst" || return 1
@ -4015,7 +4251,7 @@ get_compose_yml_content() {
COMPOSE_YML_FILE=$(get_compose_yml_location) || return 1
fi
if [ -e "$COMPOSE_YML_FILE" ]; then
debug "Found $WHITE$exname$NORMAL YAML file in '$COMPOSE_YML_FILE'."
# debug "Found $WHITE$exname$NORMAL YAML file in '$COMPOSE_YML_FILE'."
COMPOSE_YML_CONTENT=$(cat "$COMPOSE_YML_FILE") || {
err "Could not read '$COMPOSE_YML_FILE'."
return 1
@ -4046,6 +4282,37 @@ get_compose_yml_content() {
}
export -f get_compose_yml_content
compose:yml:hash() {
local cache_file="$state_tmpdir/$FUNCNAME.cache"
if [ -e "$cache_file" ]; then
cat "$cache_file" &&
touch "$cache_file" || return 1
return 0
fi
compose_yml_content=$(get_compose_yml_content) || return 1
compose_yml_hash=$(echo "$compose_yml_content" | hash_get) || return 1
e "$compose_yml_hash" | tee "$cache_file" || return 1
}
export -f compose:yml:hash
compose:yml:root:services() {
local cache_file="$state_tmpdir/$FUNCNAME.cache" services compose_yml_content
if [ -e "$cache_file" ]; then
cat "$cache_file" &&
touch "$cache_file" || return 1
return 0
fi
compose_yml_content=$(get_compose_yml_content) || return 1
services=($(e "$compose_yml_content" | shyaml keys)) || return 1
e "${services[*]}" | tee "$cache_file" || return 1
}
export -f compose:yml:root:services
get_default_target_services() {
local services=("$@")
@ -4284,9 +4551,12 @@ display_commands_help() {
get_docker_charm_action() {
local services service charm relation_name target_service relation_config \
target_charm
services=($(get_compose_yml_content | yq -r 'keys().[]' 2>/dev/null)) || return 1
NO_CONSTRAINT_CHECK=1 get_all_relations "${services[@]}" >/dev/null || return 1
target_charm services
## XXXvlab: this is for get_service_relations
NO_CONSTRAINT_CHECK=True service:all:set_relations_hash || {
err-d "Failed to set relations hash."
return 1
}
services=($(get_all_services)) || return 1
for service in "${services[@]}"; do
printf "%s:\n" "$service"
@ -4310,8 +4580,12 @@ export -f get_docker_charm_action
get_docker_charm_action_help() {
local services service charm relation_name target_service relation_config \
target_charm
services=($(get_compose_yml_content | shyaml keys 2>/dev/null))
NO_CONSTRAINT_CHECK=1 get_all_relations "${services[@]}" >/dev/null || return 1
## XXXvlab: this is for get_service_relations
NO_CONSTRAINT_CHECK=True service:all:set_relations_hash || {
err-d "Failed to set relations hash."
return 1
}
services=($(get_all_services)) || return 1
for service in "${services[@]}"; do
out=$(
charm=$(get_service_charm "$service") || return 1
@ -4602,6 +4876,7 @@ no_init=
action=
stage="main" ## switches from 'main', to 'action', 'remainder'
is_docker_compose_action=
is_docker_compose_action_multi_service=
rebuild_relations_to_service=()
color=
declare -A without_relations
@ -4741,6 +5016,12 @@ while read-0 arg; do
fi
pos_args=($(echo "$DC_USAGE" | sed -r 's/\[-[^]]+\] ?//g;s/\[options\] ?//g'))
pos_args=("${pos_args[@]:1}")
if [[ "${pos_args[0]}" == "[SERVICE...]" ]]; then
is_docker_compose_action_multi_service=1
elif [[ "${pos_args[0]}" == "SERVICE" ]]; then
is_docker_compose_action_multi_service=0
fi
# echo "USAGE: $DC_USAGE"
# echo "pos_args: ${pos_args[@]}"
# echo "MULTI: $DC_MATCH_MULTI"
@ -4799,8 +5080,22 @@ while read-0 arg; do
shift
done < <(cla.normalize "$@")
more_actions=(status)
if [[ "$action" == *" "* ]]; then
err "Invalid action name containing spaces: ${DARKCYAN}$action${NORMAL}"
exit 1
fi
is_more_action=
[[ " ${more_actions[*]} " == *" $action "* ]] && is_more_action=true
[ -n "$CACHEDIR" ] || die "No cache directory defined."
[ -d "$CACHEDIR" ] || die "Cache directory '$CACHEDIR' doesn't exists."
case "$action" in
cache)
case "${remainder_args[0]}" in
@ -4851,8 +5146,8 @@ aexport remainder_args
COMPOSE_YML_FILE=$(get_compose_yml_location) || exit 1
COMPOSE_YML_CONTENT=$(get_compose_yml_content) || exit 1
export COMPOSE_YML_FILE COMPOSE_YML_CONTENT
COMPOSE_YML_CONTENT_HASH=$(compose:yml:hash) || exit 1
export COMPOSE_YML_FILE COMPOSE_YML_CONTENT COMPOSE_YML_CONTENT_HASH
charm.sanity_checks || die "Sanity checks about charm-store failed. Please correct."
@ -4860,7 +5155,8 @@ charm.sanity_checks || die "Sanity checks about charm-store failed. Please corre
## Get services in command line.
##
if [ -z "$is_docker_compose_action" -a "$action" ]; then
if [ -z "$is_docker_compose_action" ] && [ -z "$is_more_action" ] && [ -n "$action" ]; then
action_service=${remainder_args[0]}
if [ -z "$action_service" ]; then
err "No such command or action: ${DARKCYAN}$action${NORMAL}"
@ -4868,10 +5164,9 @@ if [ -z "$is_docker_compose_action" -a "$action" ]; then
exit 1
fi
services_args=($(compose:yml:root:services)) || return 1
## Required by has_service_action
array_read-0 services_args < <(printf "%s" "$COMPOSE_YML_CONTENT" | shyaml keys-0 2>/dev/null)
NO_CONSTRAINT_CHECK=1 get_all_relations "${services_args[@]}" >/dev/null || exit 1
service:all:set_relations_hash
remainder_args=("${remainder_args[@]:1}")
if has_service_action "$action_service" "$action" >/dev/null; then
@ -4906,7 +5201,13 @@ else
case "$action" in
ps|up)
if [ "${#services_args[@]}" == 0 ]; then
array_read-0 services_args < <(printf "%s" "$COMPOSE_YML_CONTENT" | shyaml keys-0 2>/dev/null)
services_args=($(compose:yml:root:services)) || return 1
fi
;;
status)
services_args=("${remainder_args[@]}")
if [ "${#services_args[@]}" == 0 ]; then
services_args=($(compose:yml:root:services)) || return 1
fi
;;
config)
@ -4918,19 +5219,117 @@ fi
export COMPOSE_ACTION="$action"
NO_CONSTRAINT_CHECK=True
case "$action" in
up)
up|status)
NO_CONSTRAINT_CHECK=
if [ -n "$DEBUG" ]; then
Elt "solve all relations"
start=$(time_now)
fi
service:all:set_relations_hash || exit 1
if [ -n "$DEBUG" ]; then
elapsed="$(time_elapsed $start "$(time_now)")" || exit 1
print_info "$(printf "%.3fs" "$elapsed")"
Feedback
fi
all_services=($(get_all_services)) || exit 1
## check that services_args is a subset of all_services
for service in "${services_args[@]}"; do
[[ " ${all_services[*]} " == *" $service "* ]] || {
err "Service ${DARKYELLOW}$service${NORMAL} is not defined in the current compose file."
echo " Neither is is a dependency of a service in the compose file." >&2
echo " These are the services directly or indirectly available from current compose file:" >&2
for service in "${all_services[@]}"; do
echo " - ${DARKYELLOW}$service${NORMAL}" >&2
done
exit 1
}
done
;;
esac
get_all_relations "${services_args[@]}" >/dev/null || exit 1
case "$action" in
up)
PROJECT_NAME=$(get_default_project_name) || exit 1
## Required by get_ordered_service_dependencies
array_read-0 services_args < <(printf "%s" "$COMPOSE_YML_CONTENT" | shyaml keys-0 2>/dev/null)
NO_CONSTRAINT_CHECK=1 get_all_relations "${services_args[@]}" >/dev/null || exit 1
## Remove all intents (*ing states)
rm -f "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/*ing || true
## Notify that we have the intent to bring up all these
## This will be use in inner or concurrent 'run' to include the
## services that are supposed to be up.
mkdir -p "$SERVICE_STATE_PATH/$PROJECT_NAME" || exit 1
services_args_deps=($(get_ordered_service_dependencies "${services_args[@]}")) || exit 1
for service in "${services_args_deps[@]}"; do
mkdir -p "$SERVICE_STATE_PATH/$PROJECT_NAME"/"$service" || exit 1
[ -e "$SERVICE_STATE_PATH/$PROJECT_NAME"/"$service"/up ] || {
touch "$SERVICE_STATE_PATH/$PROJECT_NAME"/"$service"/deploying || exit 1
}
done
## remove services not included in compose.yml anymore
array_read-0 all_services < <(printf "%s" "$COMPOSE_YML_CONTENT" | shyaml keys-0 2>/dev/null)
all_services_deps=($(get_ordered_service_dependencies "${all_services[@]}")) || exit 1
for service in "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/up; do
[ -e "$service" ] || continue
state=${service##*/}
service=${service%/$state}
service=${service##*/}
if [[ " ${all_services_deps[*]} " != *" ${service} "* ]]; then
touch "$SERVICE_STATE_PATH/$PROJECT_NAME"/"${service}"/orphaning || exit 1
fi
done
;;
if [ "$is_docker_compose_action" -a "${#services_args[@]}" -gt 0 ]; then
run)
PROJECT_NAME=$(get_default_project_name) || return 1
if [ -d "$SERVICE_STATE_PATH/$PROJECT_NAME" ]; then
## Notify that we have the intent to bring up all these
## This will be use in inner or concurrent 'run' to include the
## services that are supposed to be up.
for service in "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/{up,deploying}; do
[ -e "$service" ] || continue
state=${service##*/}
service=${service%/$state}
service=${service##*/}
## don't add if orphaning
[ -e "$SERVICE_STATE_PATH/$PROJECT_NAME"/"${service}"/orphaning ] && continue
## add in ${services_args[@]} if not already there
if [[ " ${services_args[*]} " != *" ${service} "* ]]; then
services_args+=("$service")
fi
done
fi
;;
esac
if [ -n "$is_docker_compose_action_multi_service" ]; then
if [ -n "$DEBUG" ]; then
Elt "get relation subet"
start=$(time_now)
fi
get_subset_relations "${services_args[@]}" >/dev/null || exit 1
if [ -n "$DEBUG" ]; then
elapsed="$(time_elapsed $start "$(time_now)")" || exit 1
print_info "$(printf "%.3fs" "$elapsed")"
Feedback
fi
fi
if [ -n "$is_docker_compose_action" ] && [ "${#services_args[@]}" -gt 0 ]; then
services=($(get_master_services "${services_args[@]}")) || exit 1
if [ "$action" == "up" ]; then
declare -A seen
for service in $(get_ordered_service_dependencies "${services_args[@]}"); do
services=($(get_ordered_service_dependencies "${services_args[@]}")) || exit 1
for service in "${services[@]}"; do
mservice=$(get_master_service_for_service "$service") || exit 1
[ "${seen[$mservice]}" ] && continue
type="$(get_service_type "$mservice")" || exit 1
@ -4940,18 +5339,23 @@ if [ "$is_docker_compose_action" -a "${#services_args[@]}" -gt 0 ]; then
seen[$mservice]=1
action_posargs+=("$mservice")
done
else
elif [ "$is_docker_compose_action_multi_service" == "1" ]; then
action_posargs+=("${services[@]}")
elif [ "$is_docker_compose_action_multi_service" == "0" ]; then
action_posargs+=("${services[0]}") ## only the first service is the legit one
fi
## Get rid of subordinates
action_posargs=($(get_master_services "${action_posargs[@]}")) || exit 1
fi
get_docker_compose "${services_args[@]}" >/dev/null || { ## precalculate variable \$_current_docker_compose
# if [ "$action" != "status" ]; then
get_docker_compose "${services_args[@]}" >/dev/null || { ## precalculate variable \$_current_docker_compose
err "Fails to compile base 'docker-compose.yml'"
exit 1
}
}
# fi
##
## Pre-action
@ -4967,7 +5371,7 @@ case "$action" in
full_init=true
post_hook=true
;;
""|down|restart|logs|config|ps)
""|down|restart|logs|config|ps|status)
full_init=
;;
*)
@ -5032,6 +5436,47 @@ fi
[ "$action" == "build" ] && exit 0
service:state() {
local service="$1" states state
project_name=$(get_default_project_name) || return 1
states=()
for state in "$SERVICE_STATE_PATH"/"$project_name"/"$service"/*; do
[ -e "$state" ] || continue
state=${state##*/}
states+=("$state")
done
if [[ " ${states[*]} " == *" deploying "* ]]; then
echo "deploying"
elif [[ " ${states[*]} " == *" up "* ]]; then
echo "up"
else
echo "down"
fi
}
if [ "$action" == "status" ]; then
for service in "${services_args[@]}"; do
msgs=""
if has_service_action "$service" "get-version" >/dev/null; then
version_msg=$(run_service_action "$service" "get-version") || exit 1
if [[ "$version_msg" == *$'\n'* ]]; then
version="${version_msg%%$'\n'*}"
msgs="${version_msg#*$'\n'}"
else
version=${version_msg}
fi
else
version="N/A"
fi
state=$(service:state "$service")
printf "%-20s %8s %10s %s\n" "$service" "$state" "$version" "$msgs"
done
exit 0
fi
if [ "$action" == "run" ] && [ "${#services_args}" != 0 ]; then
charm=$(get_service_charm "${services_args[0]}") || exit 1
metadata=$(charm.metadata "$charm") || exit 1
@ -5114,6 +5559,38 @@ if [ "$action" == "run" -a "${#services_args}" != 0 ]; then
fi
fi
case "$action" in
up)
## Notify that services in 'deploying' states have been deployed
for service in "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/deploying; do
[ -e "$service" ] || continue
state=${service##*/}
service=${service%/$state}
service=${service##*/}
mv "$SERVICE_STATE_PATH/$PROJECT_NAME"/"${service}"/{deploying,up}
done
## Notify that services in 'orphaning' states have been removed
for service in "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/orphaning; do
[ -e "$service" ] || continue
state=${service##*/}
service=${service%/$state}
service=${service##*/}
rm "$SERVICE_STATE_PATH/$PROJECT_NAME"/"${service}"/orphaning
done
;;
down)
PROJECT_NAME=$(get_default_project_name) || return 1
if [ -d "$SERVICE_STATE_PATH/$PROJECT_NAME" ]; then
if ! dir_is_empty "$SERVICE_STATE_PATH/$PROJECT_NAME"; then
rm -f "$SERVICE_STATE_PATH/$PROJECT_NAME"/*/*
fi
rmdir "$SERVICE_STATE_PATH/$PROJECT_NAME"/{*,}
fi
;;
esac
clean_unused_docker_compose || exit 1
exit "$errlvl"
Loading…
Cancel
Save