Browse Source

new: ``charm`` and ``service`` are cleanly separated concepts now

``charm`` is the general recipes. ``service`` is a practical
functionality that will (if not subordinated) spawn a docker container.
In your compose file, you define services that will apply some general
rules borrowed from ``charm``s. Different services can link to the same
charm.
raw-remaining-args
Valentin Lab 6 years ago
parent
commit
97d6535943
  1. 244
      bin/compose

244
bin/compose

@ -58,7 +58,8 @@ run without launching ${WHITE}docker-compose${NORMAL}.
In compose message, color coding is enforced as such:
- ${DARKCYAN}action$NORMAL,
- ${DARKBLUE}relation$NORMAL,
- ${DARKYELLOW}charm${NORMAL}/${DARKYELLOW}service${NORMAL},
- ${DARKPINK}charm${NORMAL},
- ${DARKYELLOW}service${NORMAL},
- ${WHITE}option-name${NORMAL}/${WHITE}command-name${NORMAL}/${WHITE}Section-Title${NORMAL}
$WHITE$exname$NORMAL reads '/etc/compose.conf' for global variables, and
@ -99,7 +100,7 @@ clean_cache() {
trap_add "EXIT" clean_cache
usage="$exname CHARM"'
usage="$exname SERVICE"'
Deploy and manage a swarm of containers to provide services based on
a ``compose.yml`` definition and charms from a ``charm-store``.
@ -273,22 +274,22 @@ docker_has_image() {
export -f docker_has_image
cmd_on_base_image() {
local charm="$1" base_image
local service="$1" base_image
shift
base_image=$(service_base_docker_image "$charm") || return 1
base_image=$(service_base_docker_image "$service") || return 1
docker run -i --entrypoint /bin/bash "$base_image" -c "$*"
}
export -f cmd_on_base_image
cached_cmd_on_base_image() {
local charm="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)"
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)"
shift
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: cache hit ($*)"
quick_cat_stdin < "$cache_file"
return 0
fi
result=$(cmd_on_base_image "$charm" "$@") || return 1
result=$(cmd_on_base_image "$service" "$@") || return 1
echo "$result" | tee "$cache_file"
}
export -f cached_cmd_on_base_image
@ -696,7 +697,8 @@ export -f get_running_containers_for_service
get_docker_compose_links() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
links charm charm_part master_charm
deps master_service master_target_service _relation_name \
target_service _relation_config tech_dep
if [ -z "$service" ]; then
print_syntax_error "$FUNCNAME: Please specify a service as first argument."
return 1
@ -708,16 +710,16 @@ get_docker_compose_links() {
return 0
fi
master_charm=$(get_top_master_charm_for_service "$service") || return 1
master_service=$(get_top_master_service_for_service "$service") || return 1
deps=()
while read-0 relation_name target_service relation_config tech_dep; do
master_target_charm="$(get_top_master_charm_for_service "$target_service")"
[ "$master_charm" == "$master_target_charm" ] && continue
while read-0 _relation_name target_service _relation_config tech_dep; do
master_target_service="$(get_top_master_service_for_service "$target_service")"
[ "$master_service" == "$master_target_service" ] && continue
if [ "$tech_dep" == "reversed" ]; then
deps+=("$(echo -en "$master_target_charm:\n links:\n - $master_charm")")
deps+=("$(echo -en "$master_target_service:\n links:\n - $master_service")")
elif [ "$tech_dep" == "True" ]; then
deps+=("$(echo -en "$master_charm:\n links:\n - $master_target_charm")")
deps+=("$(echo -en "$master_service:\n links:\n - $master_target_service")")
fi
done < <(get_compose_relations "$service") || return 1
@ -731,7 +733,7 @@ get_docker_compose_links() {
_get_docker_compose_opts() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
links charm charm_part master_charm
compose_def master_service docker_compose_opts
if [ -z "$service" ]; then
print_syntax_error "$FUNCNAME: Please specify a service as first argument."
return 1
@ -744,11 +746,11 @@ _get_docker_compose_opts() {
fi
compose_def="$(get_compose_service_def "$service")" || return 1
master_charm="$(get_top_master_charm_for_service "$service")"
master_service="$(get_top_master_service_for_service "$service")"
docker_compose_opts=$(echo "$compose_def" | shyaml get-value "docker-compose" 2>/dev/null)
if [ "$docker_compose_opts" ]; then
yaml_key_val_str "$master_charm" "$docker_compose_opts"
yaml_key_val_str "$master_service" "$docker_compose_opts"
fi | tee "$cache_file"
if [ "${PIPESTATUS[0]}" != 0 ]; then
rm "$cache_file"
@ -762,7 +764,9 @@ _get_docker_compose_opts() {
## Some metadata.yml (of subordinates) will indeed modify other
## services than themselves.
_get_docker_compose_service_mixin() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" links charm charm_part
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
links_yaml base_mixin links_yaml docker_compose_options \
charm charm_part
if [ -z "$service" ]; then
print_syntax_error "$FUNCNAME: Please specify a service as first argument."
return 1
@ -774,17 +778,17 @@ _get_docker_compose_service_mixin() {
return 0
fi
master_charm=$(get_top_master_charm_for_service "$service") || {
err "Failed to get top master charm for service $DARKYELLOW$service$NORMAL"
master_service=$(get_top_master_service_for_service "$service") || {
err "Failed to get top master service for service $DARKYELLOW$service$NORMAL"
return 1
}
## The compose part
base_mixin="$master_charm:
base_mixin="$master_service:
labels:
- \"compose.service=$service\"
- \"compose.master-charm=${master_charm}\"
- \"compose.master-service=${master_service}\"
- \"compose.project=$(get_default_project_name)\""
links_yaml=$(get_docker_compose_links "$service") || return 1
docker_compose_options=$(_get_docker_compose_opts "$service") || return 1
@ -793,11 +797,11 @@ _get_docker_compose_service_mixin() {
#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 "$charm") || return 1
charm_part=$(get_docker_compose_mixin_from_metadata "$service" "$charm") || return 1
## Merge results
if [ "$charm_part" ]; then
charm_yaml="$(yaml_key_val_str "$master_charm" "$charm_part")" || return 1
charm_yaml="$(yaml_key_val_str "$master_service" "$charm_part")" || return 1
merge_yaml_str "$base_mixin" "$links_yaml" "$charm_yaml" "$docker_compose_options" || return 1
else
merge_yaml_str "$base_mixin" "$links_yaml" "$docker_compose_options" || return 1
@ -831,7 +835,7 @@ get_docker_compose () {
declare -A entries
start_compilation=$SECONDS
debug "Compiling 'docker-compose.yml' base for $DARKYELLOW$@$NORMAL..."
debug "Compiling 'docker-compose.yml' base for ${DARKYELLOW}$*$NORMAL..."
for target_service in "$@"; do
start=$SECONDS
services=$(get_ordered_service_dependencies "$target_service") || {
@ -933,7 +937,7 @@ _get_service_charm_cached () {
fi
charm=$(echo "$service_def" | shyaml get-value charm 2>/dev/null)
if [ -z "$charm" ]; then
err "Missing charm in service $DARKYELLOW$service$NORMAL definition."
err "Missing ${WHITE}charm${NORMAL} value in service $DARKYELLOW$service$NORMAL definition."
return 1
fi
echo "$charm" | tee "$cache_file"
@ -973,18 +977,18 @@ export -f get_service_def
## Return the base docker image name of a service
service_base_docker_image() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
master_charm charm service_image service_build service_dockerfile
master_service service_def service_image service_build service_dockerfile
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: cache hit ($*)"
cat "$cache_file"
return 0
fi
master_charm="$(get_top_master_charm_for_service "$service")" || {
err "Could not compute base charm for service $DARKYELLOW$service$NORMAL."
master_service="$(get_top_master_service_for_service "$service")" || {
err "Could not compute master service for service $DARKYELLOW$service$NORMAL."
return 1
}
service_def="$(get_service_def "$master_charm")" || {
err "Could not get docker-compose service definition for $DARKYELLOW$master_charm$NORMAL."
service_def="$(get_service_def "$master_service")" || {
err "Could not get docker-compose service definition for $DARKYELLOW$master_service$NORMAL."
return 1
}
service_image=$(echo "$service_def" | shyaml get-value image 2>/dev/null)
@ -995,7 +999,7 @@ service_base_docker_image() {
echo "$service_def" >&2
return 1
fi
service_dockerfile="$(charm.get_dir "${service_build%%/*}")"/"${service_build#*/}"/Dockerfile
service_dockerfile="${service_build}"/Dockerfile
if ! [ -e "$service_dockerfile" ]; then
err "No Dockerfile found in '$service_dockerfile' location."
return 1
@ -1027,7 +1031,7 @@ export -f get_charm_relation_def
get_charm_tech_dep_orientation_for_relation() {
local charm="$1" relation_name="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1.$2" \
relation_def metadata value
relation_def value
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: cache hit ($*)"
cat "$cache_file"
@ -1150,17 +1154,19 @@ run_service_hook () {
charm.has_hook "$charm" "$action" >/dev/null || continue
PROJECT_NAME=$(get_default_project_name) || return 1
Wrap -d "$YELLOW$action$NORMAL hook of charm $DARKYELLOW$charm$NORMAL" <<EOF || return 1
export MASTER_BASE_SERVICE_NAME=$(get_top_master_service_for_service "$subservice") || return 1
export MASTER_BASE_CHARM_NAME=$(get_service_charm "$MASTER_BASE_SERVICE_NAME") || return 1
Wrap -d "running $YELLOW$action$NORMAL hook of $DARKYELLOW$subservice$NORMAL in charm $DARKPINK$charm$NORMAL" <<EOF || return 1
export SERVICE_NAME=$subservice
export MASTER_BASE_CHARM_NAME=$(get_top_master_charm_for_service "$subservice") || return 1
export IMAGE_NAME=$(echo "${PROJECT_NAME}" | tr -d "_-")_\${MASTER_BASE_CHARM_NAME}
export IMAGE_NAME=$(echo "${PROJECT_NAME}" | tr -d "_-")_\${SERVICE_NAME}
export CONTAINER_NAME=\${IMAGE_NAME}_1
export CHARM_NAME="$charm"
export PROJECT_NAME=$PROJECT_NAME
export DOCKER_BASE_IMAGE=$(service_base_docker_image "$charm")
export SERVICE_DATASTORE="$DATASTORE/$charm"
export SERVICE_CONFIGSTORE="$CONFIGSTORE/$charm"
export DOCKER_BASE_IMAGE=$(service_base_docker_image "$MASTER_BASE_SERVICE_NAME")
export SERVICE_DATASTORE="$DATASTORE/$subservice"
export SERVICE_CONFIGSTORE="$CONFIGSTORE/$subservice"
charm.run_hook "$charm" "$action"
@ -1366,34 +1372,37 @@ _run_service_relation () {
target_script_name=$(charm.has_relation_hook "$target_charm" "$relation_name" relation-joined) || true
[ "$base_script_name" -o "$target_script_name" ] || return 0
relation_dir=$(get_relation_data_dir "$charm" "$target_charm" "$relation_name") || return 1
RELATION_DATA_FILE=$(get_relation_data_file "$charm" "$target_charm" "$relation_name" "$relation_config") || return 1
relation_dir=$(get_relation_data_dir "$service" "$target_service" "$relation_name") || return 1
RELATION_DATA_FILE=$(get_relation_data_file "$service" "$target_service" "$relation_name" "$relation_config") || return 1
export BASE_SERVICE_NAME=$service
export BASE_CHARM_NAME=$charm
export BASE_CHARM_PATH=$(charm.get_dir "$charm")
export TARGET_SERVICE_NAME=$target_service
export TARGET_CHARM_NAME=$target_charm
export TARGET_CHARM_PATH=$(charm.get_dir "$target_charm")
export RELATION_DATA_FILE
target_errlvl=0
if [ -z "$target_script_name" ]; then
verb "No relation script $DARKBLUE$relation_name$NORMAL in target $DARKYELLOW$target_charm$NORMAL."
verb "No relation script $DARKBLUE$relation_name$NORMAL in target $DARKPINK$target_charm$NORMAL."
else
verb "Running ${DARKBLUE}$relation_name${NORMAL} relation-joined script" \
"for target charm $DARKYELLOW$target_charm$NORMAL"
"for target $DARKYELLOW$target_service$NORMAL (charm $DARKPINK$target_charm$NORMAL)"
RELATION_CONFIG="$relation_dir/config_provider"
DOCKER_BASE_IMAGE=$(service_base_docker_image "$target_service") || return 1
export DOCKER_BASE_IMAGE RELATION_CONFIG RELATION_DATA
{
(
SERVICE_NAME=$target_service
SERVICE_DATASTORE="$DATASTORE/$target_charm"
SERVICE_CONFIGSTORE="$CONFIGSTORE/$target_charm"
SERVICE_DATASTORE="$DATASTORE/$target_service"
SERVICE_CONFIGSTORE="$CONFIGSTORE/$target_service"
export SERVICE_NAME DOCKER_BASE_IMAGE SERVICE_DATASTORE SERVICE_CONFIGSTORE
charm.run_relation_hook "$target_charm" "$relation_name" relation-joined
echo "$?" > "$relation_dir/target_errlvl"
) | logstdout "$DARKYELLOW$target_charm$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$target_charm$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${RED}@${NORMAL}" 3>&1 1>&2 2>&3
) | logstdout "$DARKYELLOW$target_service$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$target_service$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${RED}@${NORMAL}" 3>&1 1>&2 2>&3
target_errlvl="$(cat "$relation_dir/target_errlvl")" || {
err "Relation script '$script_name' in $DARKYELLOW$target_charm$NORMAL" \
err "Relation script '$script_name' in $DARKPINK$target_charm$NORMAL" \
"failed before outputing an errorlevel."
((target_errlvl |= "1" ))
}
@ -1409,7 +1418,7 @@ _run_service_relation () {
errlvl=0
if [ "$base_script_name" ]; then
verb "Running ${DARKBLUE}$relation_name${NORMAL} relation-joined script" \
"for charm $DARKYELLOW$charm$NORMAL"
"for $DARKYELLOW$service$NORMAL (charm $DARKPINK$charm$NORMAL)"
RELATION_CONFIG="$relation_dir/config_providee"
RELATION_DATA="$(cat "$RELATION_DATA_FILE")"
DOCKER_BASE_IMAGE=$(service_base_docker_image "$service") || return 1
@ -1417,15 +1426,15 @@ _run_service_relation () {
{
(
SERVICE_NAME=$service
SERVICE_DATASTORE="$DATASTORE/$charm"
SERVICE_CONFIGSTORE="$CONFIGSTORE/$charm"
SERVICE_DATASTORE="$DATASTORE/$service"
SERVICE_CONFIGSTORE="$CONFIGSTORE/$service"
export SERVICE_NAME DOCKER_BASE_IMAGE SERVICE_DATASTORE SERVICE_CONFIGSTORE
charm.run_relation_hook "$charm" "$relation_name" relation-joined
echo "$?" > "$relation_dir/errlvl"
) | logstdout "$DARKYELLOW$charm$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$charm$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${RED}@$NORMAL" 3>&1 1>&2 2>&3
) | logstdout "$DARKYELLOW$service$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$service$NORMAL/$DARKBLUE$relation_name$NORMAL (joined) ${RED}@$NORMAL" 3>&1 1>&2 2>&3
errlvl="$(cat "$relation_dir/errlvl")" || {
err "Relation script '$script_name' in $DARKYELLOW$charm$NORMAL" \
err "Relation script '$script_name' in $DARKPINK$charm$NORMAL" \
"failed before outputing an errorlevel."
((errlvl |= "1" ))
}
@ -1435,13 +1444,13 @@ _run_service_relation () {
((errlvl |= "$?" ))
fi
if [ "$errlvl" != 0 ]; then
err "Relation $DARKBLUE$relation_name$NORMAL on $DARKYELLOW$charm$NORMAL failed to run properly."
err "Relation $DARKBLUE$relation_name$NORMAL on $DARKYELLOW$service$NORMAL failed to run properly."
fi
else
verb "No relation script '$script_name' in charm $DARKYELLOW$charm$NORMAL. Ignoring."
verb "No relation script '$script_name' in charm $DARKPINK$charm$NORMAL. Ignoring."
fi
else
err "Relation $DARKBLUE$relation_name$NORMAL on $DARKYELLOW$target_charm$NORMAL failed to run properly."
err "Relation $DARKBLUE$relation_name$NORMAL on $DARKYELLOW$target_service$NORMAL failed to run properly."
fi
if [ "$target_errlvl" == 0 -a "$errlvl" == 0 ]; then
@ -1473,18 +1482,21 @@ _get_compose_relations_cached () {
case "$(echo "$relation_def" | shyaml get-type 2>/dev/null)" in
"str")
target_service="$(echo "$relation_def" | shyaml get-value 2>/dev/null)"
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_service" "$relation_name")"
target_charm=$(get_service_charm "$target_service")
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"
;;
"sequence")
while read-0 target_service; do
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_service" "$relation_name")"
target_charm=$(get_service_charm "$target_service")
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"
done < <(echo "$relation_def" | shyaml get-values-0 2>/dev/null)
;;
"struct")
while read-0 target_service relation_config; do
tech_dep="$(get_charm_tech_dep_orientation_for_relation "$target_service" "$relation_name")"
target_charm=$(get_service_charm "$target_service")
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"
done < <(echo "$relation_def" | shyaml key-values-0 2>/dev/null)
;;
@ -1539,18 +1551,20 @@ run_service_relations () {
[ "${loaded[$subservice]}" ] && continue
export BASE_SERVICE_NAME=$service
MASTER_BASE_CHARM_NAME=$(get_top_master_charm_for_service "$subservice") || return 1
MASTER_BASE_SERVICE_NAME=$(get_top_master_service_for_service "$subservice") || return 1
MASTER_BASE_CHARM_NAME=$(get_service_charm "$MASTER_BASE_SERVICE_NAME") || return 1
RELATION_BASE_COMPOSE_DEF=$(get_compose_service_def "$subservice") || return 1
export RELATION_BASE_COMPOSE_DEF MASTER_BASE_CHARM_NAME
export RELATION_BASE_COMPOSE_DEF MASTER_BASE_{CHARM,SERVICE}_NAME
# debug " Relations of ${DARKYELLOW}$subservice${NORMAL}:"
while read-0 relation_name target_service relation_config tech_dep; do
export relation_config
export TARGET_SERVICE_NAME=$target_service
MASTER_TARGET_CHARM_NAME=$(get_top_master_charm_for_service "$target_service") || return 1
MASTER_TARGET_SERVICE_NAME=$(get_top_master_service_for_service "$target_service") || return 1
MASTER_TARGET_CHARM_NAME=$(get_service_charm "$MASTER_TARGET_SERVICE_NAME") || return 1
RELATION_TARGET_COMPOSE_DEF=$(get_compose_service_def "$target_service") || return 1
export MASTER_TARGET_CHARM_NAME RELATION_TARGET_COMPOSE_DEF
export RELATION_TARGET_COMPOSE_DEF MASTER_TARGET_{CHARM,SERVICE}_NAME
Wrap -d "Building $DARKYELLOW$subservice$NORMAL --$DARKBLUE$relation_name$NORMAL--> $DARKYELLOW$target_service$NORMAL" <<EOF || return 1
_run_service_relation "$relation_name" "$subservice" "$target_service" "\$relation_config"
@ -1564,7 +1578,7 @@ export -f run_service_relations
_run_service_action_direct() {
local service="$1" action="$2" charm _dummy
local service="$1" action="$2" charm _dummy
shift; shift
read-0 charm || true ## against 'set -e' that could be setup in parent scripts
@ -1584,15 +1598,15 @@ _run_service_action_direct() {
export METADATA_CONFIG=$(charm.metadata "$charm")
export SERVICE_NAME=$service
export ACTION_NAME=$action
export CONTAINER_NAME=$(get_top_master_charm_for_service "$service")
export CONTAINER_NAME=$(get_top_master_service_for_service "$service")
export DOCKER_BASE_IMAGE=$(service_base_docker_image "$CONTAINER_NAME")
export SERVICE_DATASTORE="$DATASTORE/$service"
export SERVICE_CONFIGSTORE="$CONFIGSTORE/$service"
exname="$exname $ACTION_NAME $SERVICE_NAME" \
stdbuf -oL -eL bash -c 'charm.run_direct_action "$@"' -- "$charm" "$action" "$@"
echo "$?" > "$action_errlvl_file"
) | logstdout "$DARKYELLOW$charm$NORMAL/${DARKCYAN}$action${NORMAL} ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$charm$NORMAL/${DARKCYAN}$action${NORMAL} ${RED}@$NORMAL" 3>&1 1>&2 2>&3
) | logstdout "$DARKYELLOW$service$NORMAL/${DARKCYAN}$action${NORMAL} ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$service$NORMAL/${DARKCYAN}$action${NORMAL} ${RED}@$NORMAL" 3>&1 1>&2 2>&3
if ! [ -e "$action_errlvl_file" ]; then
err "Action $DARKYELLOW$service$NORMAL:$DARKCYAN$action$NORMAL has failed without having time" \
"to output an errlvl"
@ -1606,14 +1620,14 @@ _run_service_action_relation() {
local service="$1" action="$2" charm target_charm relation_name relation_config _dummy
shift; shift
read-0 charm target_charm relation_name relation_config || true
read-0 charm target_service target_charm relation_name relation_config || true
if read-0 _dummy || [ "$_dummy" ]; then
print_syntax_error "$FUNCNAME: too many arguments in action descriptor"
return 1
fi
export RELATION_DATA_FILE=$(get_relation_data_file "$charm" "$target_charm" "$relation_name" "$relation_config")
export RELATION_DATA_FILE=$(get_relation_data_file "$service" "$target_service" "$relation_name" "$relation_config")
compose_file=$(get_compose_yml_location) || return 1
export action_errlvl_file="$state_tmpdir/action-$service-$charm-$action-errlvl"
@ -1623,18 +1637,20 @@ _run_service_action_relation() {
set +e ## Prevents unwanted leaks from parent shell
export METADATA_CONFIG=$(charm.metadata "$charm")
export SERVICE_NAME=$service
export RELATION_TARGET_SERVICE="$target_service"
export RELATION_TARGET_CHARM="$target_charm"
export RELATION_BASE_SERVICE="$service"
export RELATION_BASE_CHARM="$charm"
export ACTION_NAME=$action
export CONTAINER_NAME=$(get_top_master_charm_for_service "$service")
export CONTAINER_NAME=$(get_top_master_service_for_service "$service")
export DOCKER_BASE_IMAGE=$(service_base_docker_image "$CONTAINER_NAME")
export SERVICE_DATASTORE="$DATASTORE/$service"
export SERVICE_CONFIGSTORE="$CONFIGSTORE/$service"
exname="$exname $ACTION_NAME $SERVICE_NAME" \
stdbuf -oL -eL bash -c 'charm.run_relation_action "$@"' -- "$target_charm" "$relation_name" "$action" "$@"
echo "$?" > "$action_errlvl_file"
) | logstdout "$DARKYELLOW$charm$NORMAL/${DARKCYAN}$action${NORMAL} ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$charm$NORMAL/${DARKCYAN}$action${NORMAL} ${RED}@$NORMAL" 3>&1 1>&2 2>&3
) | logstdout "$DARKYELLOW$service$NORMAL/${DARKCYAN}$action${NORMAL} ${GREEN}@${NORMAL}"
} 3>&1 1>&2 2>&3 | logstderr "$DARKYELLOW$service$NORMAL/${DARKCYAN}$action${NORMAL} ${RED}@$NORMAL" 3>&1 1>&2 2>&3
if ! [ -e "$action_errlvl_file" ]; then
err "Action $DARKYELLOW$service$NORMAL:$DARKCYAN$action$NORMAL has failed without having time" \
"to output an errlvl"
@ -1646,7 +1662,7 @@ export -f _run_service_action_relation
get_relation_data_dir() {
local charm="$1" target_charm="$2" relation_name="$3" cache_file="$state_tmpdir/$FUNCNAME.cache.$1"
local service="$1" target_service="$2" relation_name="$3" cache_file="$state_tmpdir/$FUNCNAME.cache.$1"
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: cache hit ($*)"
cat "$cache_file"
@ -1654,7 +1670,7 @@ get_relation_data_dir() {
fi
project=$(get_default_project_name) || return 1
relation_dir="$VARDIR/relations/$project/$charm-$target_charm/$relation_name"
relation_dir="$VARDIR/relations/$project/${service}-${target_service}/$relation_name"
if ! [ -d "$relation_dir" ]; then
mkdir -p "$relation_dir" || return 1
chmod go-rwx "$relation_dir" || return 1 ## protecting this directory
@ -1665,9 +1681,9 @@ export -f get_relation_data_dir
get_relation_data_file() {
local charm="$1" target_charm="$2" relation_name="$3" relation_config="$4"
local service="$1" target_service="$2" relation_name="$3" relation_config="$4"
relation_dir=$(get_relation_data_dir "$charm" "$target_charm" "$relation_name") || return 1
relation_dir=$(get_relation_data_dir "$service" "$target_service" "$relation_name") || return 1
relation_data_file="$relation_dir/data"
new=
@ -1693,7 +1709,7 @@ export -f get_relation_data_file
has_service_action () {
local service="$1" action="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
charm target_charm
charm target_charm relation_name target_service relation_config _tech_dep
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: cache hit ($*)"
cat "$cache_file"
@ -1708,17 +1724,19 @@ has_service_action () {
echo -en "direct\0$charm" | tee "$cache_file"
return 0
fi
## Action provided by relation ?
while read-0 relation_name target_service relation_config tech_dep; do
while read-0 relation_name target_service relation_config _tech_dep; do
target_charm=$(get_service_charm "$target_service") || return 1
if charm.has_relation_action "$target_charm" "$relation_name" "$action" >/dev/null; then
echo -en "relation\0$charm\0$target_charm\0$relation_name\0$relation_config" | tee "$cache_file"
echo -en "relation\0$charm\0$target_service\0$target_charm\0$relation_name\0$relation_config" | tee "$cache_file"
return 0
fi
done < <(get_compose_relations "$service")
return 1
# master=$(get_top_master_charm_for_service "$charm")
# master=$(get_top_master_service_for_service "$service")
# [ "$master" == "$charm" ] && return 1
# has_service_action "$master" "$action"
@ -1782,9 +1800,9 @@ export -f get_compose_relation_config
# export -f get_compose_relation_config_for_service
_get_master_charm_for_service_cached () {
_get_master_service_for_service_cached () {
local service="$1" charm="$2" metadata="$3" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \
charm requires master_charm target_charm target_service service_def
charm requires master_charm target_charm target_service service_def found
if [ -e "$cache_file" ]; then
# debug "$FUNCNAME: STATIC cache hit ($1)"
cat "$cache_file"
@ -1793,15 +1811,15 @@ _get_master_charm_for_service_cached () {
fi
if [ "$(echo "$metadata" | shyaml get-value "subordinate" 2>/dev/null)" != "True" ]; then
## just return charm name
echo "$charm" | tee "$cache_file"
## just return service name
echo "$service" | tee "$cache_file"
return 0
fi
## fetch the container relation
requires="$(echo "$metadata" | shyaml get-value "requires" 2>/dev/null)"
if [ -z "$requires" ]; then
die "Charm $DARKYELLOW$charm$NORMAL is a subordinate but does not have any 'requires' " \
die "Charm $DARKPINK$charm$NORMAL is a subordinate but does not have any 'requires' " \
"section."
fi
found=
@ -1812,7 +1830,7 @@ _get_master_charm_for_service_cached () {
}
done < <(echo "$requires" | shyaml key-values-0 2>/dev/null)
if [ -z "$found" ]; then
die "Charm $DARKYELLOW$charm$NORMAL is a subordinate but does not have any required relation declaration with" \
die "Charm $DARKPINK$charm$NORMAL is a subordinate but does not have any required relation declaration with" \
" ${WHITE}scope${NORMAL} set to 'container'."
fi
@ -1836,12 +1854,11 @@ _get_master_charm_for_service_cached () {
"${DARKYELLOW}$service$NORMAL compose definition."
return 1
fi
master_charm=$(get_service_charm "$target_service") || return 1
echo "$master_charm" | tee "$cache_file"
echo "$target_service" | tee "$cache_file"
}
export -f _get_master_charm_for_service_cached
export -f _get_master_service_for_service_cached
get_master_charm_for_service() {
get_master_service_for_service() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
charm metadata result
@ -1852,17 +1869,17 @@ get_master_charm_for_service() {
fi
charm=$(get_service_charm "$service") || return 1
metadata=$(charm.metadata "$charm") || {
err "Failed to access metadata of charm $DARKYELLOW$charm$NORMAL"
return 1
metadata=$(charm.metadata "$charm" 2>/dev/null) || {
metadata=""
warn "No charm $DARKPINK$charm$NORMAL found."
}
result=$(_get_master_charm_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"
}
export -f get_master_charm_for_service
export -f get_master_service_for_service
get_top_master_charm_for_service() {
get_top_master_service_for_service() {
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \
current_service
@ -1874,14 +1891,14 @@ get_top_master_charm_for_service() {
current_service="$service"
while true; do
master_service=$(get_master_charm_for_service "$current_service") || return 1
master_service=$(get_master_service_for_service "$current_service") || return 1
[ "$master_service" == "$current_service" ] && break
current_service="$master_service"
done
echo "$current_service" | tee "$cache_file"
return 0
}
export -f get_top_master_charm_for_service
export -f get_top_master_service_for_service
##
@ -1889,7 +1906,7 @@ export -f get_top_master_charm_for_service
## docker-compose entry (thinking of subordinates). The result
## will be merge with master charms.
_get_docker_compose_mixin_from_metadata_cached() {
local charm="$1" metadata="$2" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \
local service="$1" charm="$2" metadata="$3" cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \
metadata_file metadata volumes docker_compose subordinate image
if [ -e "$cache_file" ]; then
#debug "$FUNCNAME: STATIC cache hit $1"
@ -1904,7 +1921,7 @@ _get_docker_compose_mixin_from_metadata_cached() {
volumes=$(
for resource_type in data config; do
while read-0 resource; do
eval "echo \" - \$${resource_type^^}STORE/\$charm\$resource:\$resource:rw\""
eval "echo \" - \$${resource_type^^}STORE/\$service\$resource:\$resource:rw\""
done < <(echo "$metadata" | shyaml get-values-0 "${resource_type}-resources" 2>/dev/null)
done
while read-0 resource; do
@ -1925,7 +1942,7 @@ _get_docker_compose_mixin_from_metadata_cached() {
if [ "$volumes" ]; then
mixin=$(merge_yaml_str "$mixin" "$(echo -en "volumes:\n$volumes")") || {
err "Failed to merge mixin with ${WHITE}docker-compose${NORMAL} option" \
"from charm ${DARKYELLOW}$charm$NORMAL."
"from charm ${DARKPINK}$charm$NORMAL."
return 1
}
fi
@ -1934,7 +1951,7 @@ _get_docker_compose_mixin_from_metadata_cached() {
if [ "$docker_compose" ]; then
mixin=$(merge_yaml_str "$mixin" "$docker_compose") || {
err "Failed to merge mixin with ${WHITE}docker-compose${NORMAL} option" \
"from charm ${DARKYELLOW}$charm$NORMAL."
"from charm ${DARKPINK}$charm$NORMAL."
return 1
}
fi
@ -1957,7 +1974,7 @@ _get_docker_compose_mixin_from_metadata_cached() {
err "Subordinate charm can not have a 'build' sub directory."
return 1
fi
image_or_build_statement="build: $charm/build"
image_or_build_statement="build: $(charm.get_dir "$charm")/build"
fi
if [ "$image_or_build_statement" ]; then
mixin=$(merge_yaml_str "$mixin" "$image_or_build_statement")
@ -1968,15 +1985,15 @@ export -f _get_docker_compose_mixin_from_metadata_cached
get_docker_compose_mixin_from_metadata() {
local charm="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1"
local service="$1" charm="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1"
if [ -e "$cache_file" ]; then
#debug "$FUNCNAME: SESSION cache hit ($*)"
cat "$cache_file"
return 0
fi
metadata="$(charm.metadata "$charm")" || return 1
mixin=$(_get_docker_compose_mixin_from_metadata_cached "$charm" "$metadata") || return 1
metadata="$(charm.metadata "$charm" 2>/dev/null)"
mixin=$(_get_docker_compose_mixin_from_metadata_cached "$service" "$charm" "$metadata") || return 1
echo "$mixin" | tee "$cache_file"
}
export -f get_docker_compose_mixin_from_metadata
@ -2032,11 +2049,12 @@ launch_docker_compose() {
fi
## XXXvlab: could be more specific and only link the needed charms
for charm in $(shyaml keys services < "$docker_compose_dir/docker-compose.yml"); do
if charm.exists "$charm"; then
ln -sf "$(charm.get_dir "$charm")" "$docker_compose_dir/$charm" || exit 1
fi
done
## XXXvlab: why do we need these links ? If this is for the build command, then it is not useful anymore.
# for charm in $(shyaml keys services < "$docker_compose_dir/docker-compose.yml"); do
# if charm.exists "$charm"; then
# ln -sf "$(charm.get_dir "$charm")" "$docker_compose_dir/$charm" || exit 1
# fi
# done
mkdir "$docker_compose_dir/.data"
{
@ -2110,7 +2128,7 @@ get_master_services() {
local loaded master_service
declare -A loaded
for service in "$@"; do
master_service=$(get_top_master_charm_for_service "$service") || return 1
master_service=$(get_top_master_service_for_service "$service") || return 1
if [ "${loaded[$master_service]}" ]; then
continue
fi
@ -2496,7 +2514,7 @@ case "$action" in
read-0 action_type
case "$action_type" in
"relation")
read-0 _ target_service relation_name
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")

Loading…
Cancel
Save