|
|
#!/bin/bash ## compose: no-hooks
if [ -z "$SERVICE_DATASTORE" ]; then echo "This script is meant to be run through 'compose' to work properly." >&2 exit 1 fi
version=0.1 usage="$exname [-h|--help] [--force|-f] [DBNAME]" help=" USAGE:
$usage
DESCRIPTION:
Read stdin and send it to the restore API of odoo service to restore in the database DBNAME. If DBNAME is not provided, it'll take the default odoo database from the ${DARKCYAN}postgres-database${NORMAL} relation of current service.
EXAMPLES:
$exname < dump.zip $exname odoo2 < odoo2.zip
"
dbname= neutralize= while [ "$1" ]; do case "$1" in "--help"|"-h") print_help >&2 exit 0 ;; "--neutralize"|"-n") neutralize=yes ;; "--force"|"-f") force=yes ;; --*|-*) err "Unexpected optional argument '$1'" print_usage >&2 exit 1 ;; *) [ -z "$dbname" ] && { dbname=$1 ; shift ; continue ; } err "Unexpected positional argument '$1'" print_usage >&2 exit 1 ;; esac shift done
version:ge() { [ "$(printf '%s\n' "$@" | sort -rV | head -n 1)" == "$1" ]; } version:lt() { ! version:ge "$@"; }
if [ -z "$dbname" ]; then dbname=$(relation:get "$SERVICE_NAME:postgres-database" dbname) || { err "Couldn't retrieve information of" \ "${DARKYELLOW}$SERVICE_NAME${NORMAL}-->${DARKCYAN}postgres-database${NORMAL}." exit 1 } fi
. "$CHARM_PATH/lib/common"
set -e
curl_opts=()
ADMIN_PASSWORD=$(odoo:get-admin-password) || { err "Couldn't retrieve admin password for ${DARKYELLOW}$SERVICE_NAME${NORMAL}." exit 1 }
container="$(get_running_container_for_service "$SERVICE_NAME")" || { err "Couldn't find running container for service ${DARKYELLOW}$SERVICE_NAME${NORMAL}." exit 1 }
odoo_version=$(docker exec "$container" python -c 'import odoo.release; print(odoo.release.version)') || { err "Failed to get odoo version." exit 1 } if version:lt "$odoo_version" "16.0" && [ -n "$neutralize" ]; then err "Option \`\`--neutralize\`\` (or \`\`-n\`\`)" \ "is only available for odoo ${WHITE}16.0${NORMAL}+." echo " Service ${DARKYELLOW}$SERVICE_NAME${NORMAL} is running odoo ${WHITE}$odoo_version${NORMAL}" >&2 exit 1 fi
if [ -n "$neutralize" ]; then curl_opts+=(-F "neutralize_database=true") fi
container_network_ip=$(get_healthy_container_ip_for_service "$SERVICE_NAME" 8069 4) || { err "Please ensure that $DARKYELLOW$service$NORMAL is running before using '$exname'." exit 1 }
container_ip=${container_network_ip##*:} container_network=${container_network_ip%%:*}
DEFAULT_CURL_IMAGE=${DEFAULT_CURL_IMAGE:-docker.0k.io/curl}
check_input() { local chars read -n 2 -r chars if [ "$chars" != "PK" ]; then err "Unexpected input not matching ZIP signature. Invalid dump." echo " First chars: '$chars'" exit 1 fi { printf "%s" "$chars" cat } }
## Beware that we are not on the host, so we need to create the ## fifo in a place we can share with the curl container. export TMPDIR=/var/cache/compose settmpdir RESTORE_TMPDIR
mkfifo "$RESTORE_TMPDIR/fifo"
## Using fifo because if using ``@-`` curl will load all the database ## in memory before sending it, which is NOT desirable as the size of ## the database can be greater than available memory. Using fifo, we ## force the data to be streamed. cmd=( docker run -i --rm --network "$container_network" -v "$RESTORE_TMPDIR/fifo:/tmp/restore/fifo" "$DEFAULT_CURL_IMAGE" -sS -X POST -F "master_pwd=${ADMIN_PASSWORD}" -F "name=${dbname}" "${curl_opts[@]}" -F "backup_file=@/tmp/restore/fifo" http://${container_ip}:8069/web/database/restore )
## XXXvlab: contains password, left only for advanced debug #echo "COMMAND: ${cmd[@]}" >&2
"${cmd[@]}" > "$RESTORE_TMPDIR/out" & pid=$! check_input > "$RESTORE_TMPDIR/fifo" wait "$pid" || { die "Posting to odoo restore API through curl was unsuccessfull." }
out=$(cat "$RESTORE_TMPDIR/out")
if [[ "$out" == *"<html>"* ]]; then errmsg=$(echo "$out" | grep "alert-danger") errmsg=${errmsg#*>} errmsg=${errmsg%%<*} if [ "$errmsg" ]; then errmsg=$(echo "$errmsg" | recode html..utf8) die "$errmsg" fi die "Unexpected output. Restore probably failed." fi >&2
info "Restored stdin dump to odoo '$dbname'."
|