|
@ -113,36 +113,6 @@ 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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
read-0-err() { |
|
|
|
|
|
local ret="$1" eof="" idx=0 last= |
|
|
|
|
|
read -r -- "${ret?}" <<<"0" |
|
|
|
|
|
shift |
|
|
|
|
|
while [ "$1" ]; do |
|
|
|
|
|
last=$idx |
|
|
|
|
|
read -r -d '' -- "$1" || { |
|
|
|
|
|
## Put this last value in ${!ret} |
|
|
|
|
|
eof="$1" |
|
|
|
|
|
read -r -- "$ret" <<<"${!eof}" |
|
|
|
|
|
break |
|
|
|
|
|
} |
|
|
|
|
|
((idx++)) |
|
|
|
|
|
shift |
|
|
|
|
|
done |
|
|
|
|
|
[ -z "$eof" ] || { |
|
|
|
|
|
if [ "$last" != 0 ]; then |
|
|
|
|
|
echo "Error: read-0-err couldn't fill all value" >&2 |
|
|
|
|
|
read -r -- "$ret" <<<"127" |
|
|
|
|
|
else |
|
|
|
|
|
if [ -z "${!ret}" ]; then |
|
|
|
|
|
echo "Error: last value is not a number, did you finish with an errorlevel ?" >&2 |
|
|
|
|
|
read -r -- "$ret" <<<"126" |
|
|
|
|
|
fi |
|
|
|
|
|
fi |
|
|
|
|
|
false |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
export -f read-0-err |
|
|
|
|
|
|
|
|
|
|
|
p-err() { |
|
|
p-err() { |
|
|
"$@" |
|
|
"$@" |
|
|
echo "$?" |
|
|
echo "$?" |
|
@ -2692,9 +2662,7 @@ service:state() { |
|
|
echo "down" |
|
|
echo "down" |
|
|
fi |
|
|
fi |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export -f service:state |
|
|
|
|
|
|
|
|
_get_charm_metadata_uses() { |
|
|
_get_charm_metadata_uses() { |
|
|
local metadata="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(printf "%s\0" "$@" | md5_compat)" |
|
|
local metadata="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(printf "%s\0" "$@" | md5_compat)" |
|
@ -4585,6 +4553,10 @@ get_docker_compose_single_opts_list() { |
|
|
display_commands_help() { |
|
|
display_commands_help() { |
|
|
local charm_actions |
|
|
local charm_actions |
|
|
echo |
|
|
echo |
|
|
|
|
|
echo "${WHITE}Commands${NORMAL} (added by compose):" |
|
|
|
|
|
echo " ${DARKCYAN}cache${NORMAL} Control compose's cache" |
|
|
|
|
|
echo " ${DARKCYAN}status${NORMAL} Display statuses of services" |
|
|
|
|
|
echo |
|
|
echo "${WHITE}Commands${NORMAL} (thanks to docker-compose):" |
|
|
echo "${WHITE}Commands${NORMAL} (thanks to docker-compose):" |
|
|
get_docker_compose_commands_help | sed -r "s/ ([a-z]+)(\s+)/ ${DARKCYAN}\1${NORMAL}\2/g" |
|
|
get_docker_compose_commands_help | sed -r "s/ ([a-z]+)(\s+)/ ${DARKCYAN}\1${NORMAL}\2/g" |
|
|
charm_actions_help=$(get_docker_charm_action_help) || return 1 |
|
|
charm_actions_help=$(get_docker_charm_action_help) || return 1 |
|
@ -5127,8 +5099,21 @@ while read-0 arg; do |
|
|
shift |
|
|
shift |
|
|
done < <(cla.normalize "$@") |
|
|
done < <(cla.normalize "$@") |
|
|
|
|
|
|
|
|
|
|
|
## These actions are additions to docker-compose actions and charm |
|
|
|
|
|
## actions |
|
|
|
|
|
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." |
|
|
[ -n "$CACHEDIR" ] || die "No cache directory defined." |
|
|
[ -d "$CACHEDIR" ] || die "Cache directory '$CACHEDIR' doesn't exists." |
|
|
[ -d "$CACHEDIR" ] || die "Cache directory '$CACHEDIR' doesn't exists." |
|
|
|
|
|
|
|
|
case "$action" in |
|
|
case "$action" in |
|
|
cache) |
|
|
cache) |
|
|
case "${remainder_args[0]}" in |
|
|
case "${remainder_args[0]}" in |
|
@ -5156,6 +5141,109 @@ EOF |
|
|
;; |
|
|
;; |
|
|
esac |
|
|
esac |
|
|
;; |
|
|
;; |
|
|
|
|
|
status) |
|
|
|
|
|
state_inner_cols=(name charm type state root) |
|
|
|
|
|
state_all_services= |
|
|
|
|
|
state_services=() |
|
|
|
|
|
state_columns=() |
|
|
|
|
|
state_columns_default=(name charm type state version) |
|
|
|
|
|
state_filters=() |
|
|
|
|
|
state_columns_default_msg="" |
|
|
|
|
|
for col in "${state_columns_default[@]}"; do |
|
|
|
|
|
if [ -n "$state_columns_default_msg" ]; then |
|
|
|
|
|
state_columns_default_msg+="," |
|
|
|
|
|
fi |
|
|
|
|
|
state_columns_default_msg+="$col" |
|
|
|
|
|
done |
|
|
|
|
|
help="\ |
|
|
|
|
|
Display status information on services. |
|
|
|
|
|
|
|
|
|
|
|
If no services are provided, all services in the root compose file |
|
|
|
|
|
will be displayed. Use the --all option to display status of all |
|
|
|
|
|
services (including dependencies). |
|
|
|
|
|
|
|
|
|
|
|
$exname offers a few possible columns that can be complete on a charm |
|
|
|
|
|
level by implementing an \`actions/get-COLNAME\` script. |
|
|
|
|
|
|
|
|
|
|
|
These are the compose's columns: ${state_inner_cols[@]}. |
|
|
|
|
|
|
|
|
|
|
|
Usage: status [options] [SERVICE...] |
|
|
|
|
|
|
|
|
|
|
|
Options: |
|
|
|
|
|
-h, --help Print this message and quit |
|
|
|
|
|
-a, --all Display status of all services |
|
|
|
|
|
(removes all filter, and will add a |
|
|
|
|
|
'root' first column by default) |
|
|
|
|
|
-c, --column Column to display, can provide several |
|
|
|
|
|
separated by commas, or option can be repeated. |
|
|
|
|
|
(default: ${state_columns_default_msg}) |
|
|
|
|
|
-f, --filter Filter services by a key=value pair, |
|
|
|
|
|
separated by commas or can be repeated. |
|
|
|
|
|
(default: --filter root=yes) |
|
|
|
|
|
" |
|
|
|
|
|
while read-0 arg; do |
|
|
|
|
|
case "$arg" in |
|
|
|
|
|
--help|-h) |
|
|
|
|
|
echo "$help" |
|
|
|
|
|
exit 0 |
|
|
|
|
|
;; |
|
|
|
|
|
--all|-a) |
|
|
|
|
|
if [ "${#state_services[@]}" -gt 0 ]; then |
|
|
|
|
|
err "Cannot use --all and provide services at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
if [[ "${#state_filters[@]}" -gt 0 ]]; then |
|
|
|
|
|
err "Cannot use --all and provide filters at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
state_all_services=1 |
|
|
|
|
|
;; |
|
|
|
|
|
--column|-c) |
|
|
|
|
|
read-0 value |
|
|
|
|
|
if [[ "$value" == *,* ]]; then |
|
|
|
|
|
state_columns+=(${value//,/ }) |
|
|
|
|
|
else |
|
|
|
|
|
state_columns+=("$value") |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
--filter|-f) |
|
|
|
|
|
if [ "${#state_services[@]}" -gt 0 ]; then |
|
|
|
|
|
err "Cannot use --filter and provide services at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
if [ -n "$state_all_services" ]; then |
|
|
|
|
|
err "Cannot use --all and provide filters at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
read-0 value |
|
|
|
|
|
if [[ "$value" == *,* ]]; then |
|
|
|
|
|
state_filters+=(${value//,/ }) |
|
|
|
|
|
else |
|
|
|
|
|
state_filters+=("$value") |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
--*|-*) |
|
|
|
|
|
err "Unknown option '$arg'. Please check help:" |
|
|
|
|
|
echo "$help" >&2 |
|
|
|
|
|
;; |
|
|
|
|
|
*) |
|
|
|
|
|
if [ -n "$state_all_services" ]; then |
|
|
|
|
|
err "Cannot use --all and provide services at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
if [[ "${#state_filters[@]}" -gt 0 ]]; then |
|
|
|
|
|
err "Cannot use --filter and provide filters at the same time." |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
state_services+=("$arg") |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
done < <(cla.normalize "${remainder_args[@]}") |
|
|
|
|
|
|
|
|
|
|
|
if [ "${#state_columns[@]}" == 0 ]; then |
|
|
|
|
|
state_columns=("${state_columns_default[@]}") |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
esac |
|
|
esac |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -5188,7 +5276,8 @@ charm.sanity_checks || die "Sanity checks about charm-store failed. Please corre |
|
|
## Get services in command line. |
|
|
## 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]} |
|
|
action_service=${remainder_args[0]} |
|
|
if [ -z "$action_service" ]; then |
|
|
if [ -z "$action_service" ]; then |
|
|
err "No such command or action: ${DARKCYAN}$action${NORMAL}" |
|
|
err "No such command or action: ${DARKCYAN}$action${NORMAL}" |
|
@ -5236,6 +5325,12 @@ else |
|
|
services_args=($(compose:yml:root:services)) || return 1 |
|
|
services_args=($(compose:yml:root:services)) || return 1 |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
;; |
|
|
|
|
|
status) |
|
|
|
|
|
services_args=("${state_services[@]}") |
|
|
|
|
|
if [ "${#services_args[@]}" == 0 ] && [ -z "$state_all_services" ]; then |
|
|
|
|
|
services_args=($(compose:yml:root:services)) || return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
config) |
|
|
config) |
|
|
services_args=("${action_posargs[@]}") |
|
|
services_args=("${action_posargs[@]}") |
|
|
;; |
|
|
;; |
|
@ -5245,7 +5340,7 @@ fi |
|
|
export COMPOSE_ACTION="$action" |
|
|
export COMPOSE_ACTION="$action" |
|
|
NO_CONSTRAINT_CHECK=True |
|
|
NO_CONSTRAINT_CHECK=True |
|
|
case "$action" in |
|
|
case "$action" in |
|
|
up) |
|
|
|
|
|
|
|
|
up|status) |
|
|
NO_CONSTRAINT_CHECK= |
|
|
NO_CONSTRAINT_CHECK= |
|
|
if [ -n "$DEBUG" ]; then |
|
|
if [ -n "$DEBUG" ]; then |
|
|
Elt "solve all relations" |
|
|
Elt "solve all relations" |
|
@ -5325,6 +5420,11 @@ case "$action" in |
|
|
done |
|
|
done |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
;; |
|
|
|
|
|
status) |
|
|
|
|
|
if [ -n "${state_all_services}" ] || [[ "${#state_filters[@]}" -gt 0 ]]; then |
|
|
|
|
|
services_args=("${all_services[@]}") |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
esac |
|
|
esac |
|
|
|
|
|
|
|
|
if [ -n "$is_docker_compose_action_multi_service" ]; then |
|
|
if [ -n "$is_docker_compose_action_multi_service" ]; then |
|
@ -5372,6 +5472,7 @@ get_docker_compose "${services_args[@]}" >/dev/null || { ## precalculate variab |
|
|
exit 1 |
|
|
exit 1 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
## |
|
|
## Pre-action |
|
|
## Pre-action |
|
|
## |
|
|
## |
|
@ -5386,7 +5487,7 @@ case "$action" in |
|
|
full_init=true |
|
|
full_init=true |
|
|
post_hook=true |
|
|
post_hook=true |
|
|
;; |
|
|
;; |
|
|
""|down|restart|logs|config|ps) |
|
|
|
|
|
|
|
|
""|down|restart|logs|config|ps|status) |
|
|
full_init= |
|
|
full_init= |
|
|
;; |
|
|
;; |
|
|
*) |
|
|
*) |
|
@ -5450,6 +5551,149 @@ if [ "${PIPESTATUS[0]}" != 0 ]; then |
|
|
fi |
|
|
fi |
|
|
[ "$action" == "build" ] && exit 0 |
|
|
[ "$action" == "build" ] && exit 0 |
|
|
|
|
|
|
|
|
|
|
|
if [ "$action" == "status" ]; then |
|
|
|
|
|
if [[ -n "${state_all_services}" ]] || [[ "${#state_filters[@]}" -gt 0 ]]; then |
|
|
|
|
|
compose_yml_services=($(compose:yml:root:services)) || exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
if [[ -n "${state_all_services}" ]]; then |
|
|
|
|
|
state_columns=("root" ${state_columns[@]}) |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
state_columns_raw=() |
|
|
|
|
|
for col in "${state_columns[@]}"; do |
|
|
|
|
|
if [[ "$col" == "-"* ]]; then |
|
|
|
|
|
col=${col#-} |
|
|
|
|
|
fi |
|
|
|
|
|
state_columns_raw+=("$col") |
|
|
|
|
|
done |
|
|
|
|
|
state_columns_align="" |
|
|
|
|
|
for col in "${state_columns[@]}"; do |
|
|
|
|
|
if [[ "$col" == "-"* ]]; then |
|
|
|
|
|
state_columns_align+="+" |
|
|
|
|
|
else |
|
|
|
|
|
state_columns_align+="-" |
|
|
|
|
|
fi |
|
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
|
|
while read-0-err E "${state_columns_raw[@]}"; do |
|
|
|
|
|
values=() |
|
|
|
|
|
for col in "${state_columns_raw[@]}"; do |
|
|
|
|
|
color= |
|
|
|
|
|
value="${!col}" |
|
|
|
|
|
read -r -- value_trim <<<"${!col}" |
|
|
|
|
|
case "$col" in |
|
|
|
|
|
root) |
|
|
|
|
|
case "$value_trim" in |
|
|
|
|
|
0) value=" ";; |
|
|
|
|
|
1) value="*";; |
|
|
|
|
|
esac |
|
|
|
|
|
;; |
|
|
|
|
|
name) color=darkyellow;; |
|
|
|
|
|
charm) color=darkpink;; |
|
|
|
|
|
state) |
|
|
|
|
|
case "$value_trim" in |
|
|
|
|
|
up) color=green;; |
|
|
|
|
|
down) color=gray;; |
|
|
|
|
|
deploying) color=yellow;; |
|
|
|
|
|
*) color=red;; |
|
|
|
|
|
esac |
|
|
|
|
|
;; |
|
|
|
|
|
type) |
|
|
|
|
|
case "$value_trim" in |
|
|
|
|
|
run-once) color=gray;; |
|
|
|
|
|
stub) color=gray;; |
|
|
|
|
|
*) color=darkcyan;; |
|
|
|
|
|
esac |
|
|
|
|
|
;; |
|
|
|
|
|
*) |
|
|
|
|
|
if [[ "${value_trim}" == "N/A" ]]; then |
|
|
|
|
|
color=gray |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
color="${color^^}" |
|
|
|
|
|
if [ -n "$color" ]; then |
|
|
|
|
|
values+=("${!color}$value${NORMAL}") |
|
|
|
|
|
else |
|
|
|
|
|
values+=("$value") |
|
|
|
|
|
fi |
|
|
|
|
|
done |
|
|
|
|
|
first=1 |
|
|
|
|
|
for value in "${values[@]}"; do |
|
|
|
|
|
if [ -n "$first" ]; then |
|
|
|
|
|
first= |
|
|
|
|
|
else |
|
|
|
|
|
printf " " |
|
|
|
|
|
fi |
|
|
|
|
|
printf "%s" "$value" |
|
|
|
|
|
done |
|
|
|
|
|
printf "\n" |
|
|
|
|
|
done < <( |
|
|
|
|
|
set -o pipefail |
|
|
|
|
|
filter_cols=() |
|
|
|
|
|
for filter in "${state_filters[@]}"; do |
|
|
|
|
|
IFS="=" read -r key value <<<"$filter" |
|
|
|
|
|
## if not already in state_columns_raw |
|
|
|
|
|
[[ " ${state_columns_raw[*]} " == *" $key "* ]] || |
|
|
|
|
|
filter_cols+=("$key") |
|
|
|
|
|
done |
|
|
|
|
|
for service in "${services_args[@]}"; do |
|
|
|
|
|
declare -A values=() |
|
|
|
|
|
for col in "${state_columns_raw[@]}" "${filter_cols[@]}"; do |
|
|
|
|
|
case "$col" in |
|
|
|
|
|
root) |
|
|
|
|
|
if [[ " ${compose_yml_services[*]} " == *" ${service} "* ]]; then |
|
|
|
|
|
value="1" |
|
|
|
|
|
else |
|
|
|
|
|
value="0" |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
name) value="$service" ;; |
|
|
|
|
|
charm) |
|
|
|
|
|
value=$(get_service_charm "$service") || { echo 1; exit 1; } |
|
|
|
|
|
;; |
|
|
|
|
|
state) |
|
|
|
|
|
value=$(service:state "$service") || { echo 1; exit 1; } |
|
|
|
|
|
;; |
|
|
|
|
|
type) |
|
|
|
|
|
value=$(get_service_type "$service") || { echo 1; exit 1; } |
|
|
|
|
|
;; |
|
|
|
|
|
*) |
|
|
|
|
|
if has_service_action "$service" "get-$col" >/dev/null; then |
|
|
|
|
|
state_msg=$(run_service_action "$service" "get-$col") || { echo 1; exit 1 ; } |
|
|
|
|
|
if [[ "$state_msg" == *$'\n'* ]]; then |
|
|
|
|
|
value="${state_msg%%$'\n'*}" |
|
|
|
|
|
## XXXvlab: For now, these are not used, but we could |
|
|
|
|
|
## display them in additional lines (in same "cell") |
|
|
|
|
|
msgs="${state_msg#*$'\n'}" |
|
|
|
|
|
else |
|
|
|
|
|
value=${state_msg} |
|
|
|
|
|
fi |
|
|
|
|
|
else |
|
|
|
|
|
value="N/A" |
|
|
|
|
|
fi |
|
|
|
|
|
;; |
|
|
|
|
|
esac |
|
|
|
|
|
values["$col"]="$value" |
|
|
|
|
|
done |
|
|
|
|
|
for filter in "${state_filters[@]}"; do |
|
|
|
|
|
IFS="=" read -r key value <<<"$filter" |
|
|
|
|
|
[[ "${values[$key]}" != "$value" ]] && |
|
|
|
|
|
continue 2 |
|
|
|
|
|
done |
|
|
|
|
|
for col in "${state_columns_raw[@]}"; do |
|
|
|
|
|
p0 "${values[$col]}" |
|
|
|
|
|
done |
|
|
|
|
|
done | col-0:normalize:size "${state_columns_align}" |
|
|
|
|
|
echo 0 |
|
|
|
|
|
) |
|
|
|
|
|
if [ "$E" != 0 ]; then |
|
|
|
|
|
echo "E: '$E'" >&2 |
|
|
|
|
|
exit 1 |
|
|
|
|
|
fi |
|
|
|
|
|
exit 0 |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$action" == "run" ] && [ "${#services_args}" != 0 ]; then |
|
|
if [ "$action" == "run" ] && [ "${#services_args}" != 0 ]; then |
|
|
charm=$(get_service_charm "${services_args[0]}") || exit 1 |
|
|
charm=$(get_service_charm "${services_args[0]}") || exit 1 |
|
|