diff --git a/bin/compose b/bin/compose index 1c9b3ec..946e442 100755 --- a/bin/compose +++ b/bin/compose @@ -32,9 +32,9 @@ } #:- - include pretty include parse +include charm depends shyaml docker @@ -930,7 +930,7 @@ service_base_docker_image() { echo "$service_def" >&2 return 1 fi - service_dockerfile="$CHARM_STORE/${service_build}/Dockerfile" + service_dockerfile="$(charm.get_dir "${service_build%%/*}")"/"${service_build#*/}"/Dockerfile if ! [ -e "$service_dockerfile" ]; then err "No Dockerfile found in '$service_dockerfile' location." return 1 @@ -953,7 +953,7 @@ get_charm_relation_def () { cat "$cache_file" return 0 fi - metadata="$(get_charm_metadata "$charm")" || return 1 + metadata="$(charm.metadata "$charm")" || return 1 relation_def="$(echo "$metadata" | shyaml get-value "provides.${relation_name}" 2>/dev/null)" echo "$relation_def" | tee "$cache_file" } @@ -1081,14 +1081,11 @@ run_service_hook () { fi charm=$(get_service_charm "$subservice") || return 1 - TARGET_SCRIPT="$CHARM_STORE/$charm/hooks/$action" - [ -e "$TARGET_SCRIPT" ] || continue + 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" < "$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 @@ -1343,7 +1330,7 @@ _run_service_relation () { if [ "$target_errlvl" == 0 ]; then errlvl=0 - if [ -e "$CHARM_STORE/$charm/$script_name" ]; then + if [ "$base_script_name" ]; then verb "Running ${DARKBLUE}$relation_name${NORMAL} relation-joined script" \ "for charm $DARKYELLOW$charm$NORMAL" RELATION_CONFIG="$relation_dir/config_providee" @@ -1352,12 +1339,11 @@ _run_service_relation () { export DOCKER_BASE_IMAGE RELATION_CONFIG RELATION_DATA { ( - cd "$CHARM_STORE/$charm" SERVICE_NAME=$service SERVICE_DATASTORE="$DATASTORE/$charm" SERVICE_CONFIGSTORE="$CONFIGSTORE/$charm" export SERVICE_NAME DOCKER_BASE_IMAGE SERVICE_DATASTORE SERVICE_CONFIGSTORE - "$script_name" + 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 @@ -1463,14 +1449,32 @@ export -f get_compose_relations run_service_relations () { local services="$1" loaded + + PROJECT_NAME=$(get_default_project_name) || return 1 + + export PROJECT_NAME + declare -A loaded for service in $(get_ordered_service_dependencies $services); do + # debug "Upping dep's relations of ${DARKYELLOW}$service${NORMAL}:" for subservice in $(get_service_deps "$service") "$service"; do [ "${loaded[$subservice]}" ] && continue + + export BASE_SERVICE_NAME=$service + MASTER_BASE_CHARM_NAME=$(get_top_master_charm_for_service "$subservice") || return 1 + RELATION_BASE_COMPOSE_DEF=$(get_compose_service_def "$subservice") || return 1 + export RELATION_BASE_COMPOSE_DEF MASTER_BASE_CHARM_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 + RELATION_TARGET_COMPOSE_DEF=$(get_compose_service_def "$target_service") || return 1 + export MASTER_TARGET_CHARM_NAME RELATION_TARGET_COMPOSE_DEF + Wrap -d "Building $DARKYELLOW$subservice$NORMAL --$DARKBLUE$relation_name$NORMAL--> $DARKYELLOW$target_service$NORMAL" < "$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 @@ -1523,10 +1526,10 @@ _run_service_action_direct() { export -f _run_service_action_direct _run_service_action_relation() { - local service="$1" action="$2" charm target_charm relation_name target_script relation_config _dummy + local service="$1" action="$2" charm target_charm relation_name relation_config _dummy shift; shift - read-0 charm target_charm relation_name target_script relation_config || true + read-0 charm target_charm relation_name relation_config || true if read-0 _dummy || [ "$_dummy" ]; then print_syntax_error "$FUNCNAME: too many arguments in action descriptor" @@ -1541,8 +1544,7 @@ _run_service_action_relation() { { ( set +e ## Prevents unwanted leaks from parent shell - cd "$CHARM_STORE/$charm" - export METADATA_CONFIG=$(cat "$CHARM_STORE/$charm/metadata.yml") + export METADATA_CONFIG=$(charm.metadata "$charm") export SERVICE_NAME=$service export RELATION_TARGET_CHARM="$target_charm" export RELATION_BASE_CHARM="$charm" @@ -1552,7 +1554,7 @@ _run_service_action_relation() { export SERVICE_DATASTORE="$DATASTORE/$service" export SERVICE_CONFIGSTORE="$CONFIGSTORE/$service" exname="$exname $ACTION_NAME $SERVICE_NAME" \ - stdbuf -oL -eL "$target_script" "$@" + stdbuf -oL -eL charm.run_relation_action "$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 @@ -1614,7 +1616,7 @@ export -f get_relation_data_file has_service_action () { local service="$1" action="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \ - target_script charm target_charm + charm target_charm if [ -e "$cache_file" ]; then # debug "$FUNCNAME: cache hit ($*)" cat "$cache_file" @@ -1625,17 +1627,15 @@ has_service_action () { ## Action directly provided ? - target_script="$CHARM_STORE/$charm/actions/$action" - if [ -x "$target_script" ]; then - echo -en "direct\0$charm\0$target_script" | tee "$cache_file" + if charm.has_direct_action "$charm" "$action"; then + 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 target_charm=$(get_service_charm "$target_service") || return 1 - target_script="$CHARM_STORE/$target_charm/actions/relations/$relation_name/$action" - if [ -x "$target_script" ]; then - echo -en "relation\0$charm\0$target_charm\0$relation_name\0$target_script\0$relation_config" | tee "$cache_file" + if charm.has_relation_action "$target_charm" "$relation_name" "$action"; then + echo -en "relation\0$charm\0$target_charm\0$relation_name\0$relation_config" | tee "$cache_file" return 0 fi done < <(get_compose_relations "$service") @@ -1656,7 +1656,7 @@ run_service_action () { { if ! read-0 action_type; then info "Service $DARKYELLOW$service$NORMAL does not have any action $DARKCYAN$action$NORMAL defined." - info " Add an executable script to '$CHARM_STORE/$charm/actions/$action' to implement action." + info " Add an executable script to 'actions/$action' to implement action." return 1 fi @@ -1776,7 +1776,10 @@ get_master_charm_for_service() { fi charm=$(get_service_charm "$service") || return 1 - metadata=$(get_charm_metadata "$charm") || return 1 + metadata=$(charm.metadata "$charm") || { + err "Failed to access metadata of charm $DARKYELLOW$charm$NORMAL" + return 1 + } result=$(_get_master_charm_for_service_cached "$service" "$charm" "$metadata") || return 1 echo "$result" | tee "$cache_file" } @@ -1805,20 +1808,6 @@ get_top_master_charm_for_service() { export -f get_top_master_charm_for_service -get_charm_metadata() { - local charm="$1" metadata_file - metadata_file="$CHARM_STORE/$charm/metadata.yml" - if ! [ -e "$metadata_file" ]; then - return 0 ## No metadata file is as if metadata was empty - fi - - if ! [ -d "$CHARM_STORE/$charm" ]; then - die "No charm $charm was found in charm store." - fi - cat "$metadata_file" -} -export -f get_charm_metadata - ## ## The result is a mixin that is not always a complete valid ## docker-compose entry (thinking of subordinates). The result @@ -1850,7 +1839,11 @@ _get_docker_compose_mixin_from_metadata_cached() { fi done < <(echo "$metadata" | shyaml get-values-0 "host-resources" 2>/dev/null) while read-0 resource; do - echo " - $CHARM_STORE/$charm/resources$resource:$resource:rw" + dest="$(charm.get_dir "$charm")/resources$resource" + if ! [ -e "$dest" ]; then + die "charm-resource: '$resource' does not exist (file: '$dest')." + fi + echo " - $dest:$resource:rw" done < <(echo "$metadata" | shyaml get-values-0 "charm-resources" 2>/dev/null) ) || return 1 if [ "$volumes" ]; then @@ -1875,7 +1868,7 @@ _get_docker_compose_mixin_from_metadata_cached() { return 1 fi image_or_build_statement="image: $image" - elif [ -d "$CHARM_STORE/$charm/build" ]; then + elif [ -d "$(charm.get_dir "$charm")/build" ]; then if [ "$subordinate" ]; then err "Subordinate charm can not have a 'build' sub directory." return 1 @@ -1898,7 +1891,7 @@ get_docker_compose_mixin_from_metadata() { return 0 fi - metadata="$(get_charm_metadata "$charm")" || return 1 + metadata="$(charm.metadata "$charm")" || return 1 mixin=$(_get_docker_compose_mixin_from_metadata_cached "$charm" "$metadata") || return 1 echo "$mixin" | tee "$cache_file" } @@ -1930,7 +1923,7 @@ export -f get_default_project_name launch_docker_compose() { - + local charm docker_compose_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) #debug "Creating temporary docker-compose directory in '$docker_compose_tmpdir'." # trap_add EXIT "debug \"Removing temporary docker-compose directory in $docker_compose_tmpdir.\";\ @@ -1951,11 +1944,15 @@ launch_docker_compose() { fi if [ -z "$(echo $(cat "$docker_compose_dir/docker-compose.yml"))" ]; then - die "Generated 'docker-compose.yml' is unexpectedly empty. Check your charm availability in '$CHARM_STORE'." + die "Generated 'docker-compose.yml' is unexpectedly empty." fi ## XXXvlab: could be more specific and only link the needed charms - ln -sf "$CHARM_STORE/"* "$docker_compose_dir/" + for charm in $(shyaml keys < "$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" { @@ -2234,7 +2231,6 @@ done ## Actual code ## -export CHARM_STORE=${CHARM_STORE:-/srv/charm-store} export DOCKER_DATASTORE=${DOCKER_DATASTORE:-/srv/docker-datastore} COMPOSE_YML_FILE=$(get_compose_yml_location) || exit 1 @@ -2252,20 +2248,7 @@ if [ "$?" != 0 ]; then exit 1 fi - -if ! [ -d "$CHARM_STORE" ]; then - err "Charm store path $YELLOW$CHARM_STORE$NORMAL does not exists. " - err "Please check your $YELLOW\$CHARM_STORE$NORMAL variable value." - exit 1 -fi - - -if [ -z "$(cd "$CHARM_STORE"; ls)" ]; then - err "no available charms in charm store $YELLOW$CHARM_STORE$NORMAL. Either:" - err " - check $YELLOW\$CHARM_STORE$NORMAL variable value" - err " - download charms in $CHARM_STORE" - print_error "Charm store is empty. Cannot continue." -fi +charm.sanity_checks || die "Sanity checks about charm-store failed. Please correct." ## ## Get services in command line.