Browse Source

chg: [odoo-tecnativa] rewrite ``load`` and ``save`` to use stdin and stdout, add ``drop`` action.

The previous implementation had several shortcoming about file
due to ``compose`` being run in a docker container. By shifting to
``stdin`` and ``stdout`` usage, we make a more elegant proposition.

See ``--help`` to get full doc with examples of usage.

Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>
pull/19/head
Valentin Lab 3 years ago
parent
commit
7b86833518
  1. 142
      odoo-tecnativa/actions/drop
  2. 134
      odoo-tecnativa/actions/load
  3. 123
      odoo-tecnativa/actions/save

142
odoo-tecnativa/actions/drop

@ -0,0 +1,142 @@
#!/bin/bash
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:
Drop odoo 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
$exname odoo2
"
dbname=
output=
while [ "$1" ]; do
case "$1" in
"--help"|"-h")
print_help >&2
exit 0
;;
"--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
if [ -z "$dbname" ]; then
##
## Fetch default dbname in relation to postgres-database
##
## XXXvlab: can't get real config here
if ! read-0 ts _ _ < <(get_service_relation "$SERVICE_NAME" "postgres-database"); then
err "Couldn't find relation ${DARKCYAN}postgres-database${NORMAL}."
exit 1
fi
relation_file=$(get_relation_data_dir "$SERVICE_NAME" "$ts" "postgres-database") || {
err "Failed to find relation file"
exit 1
}
postgres_config=$(cat "$relation_file"/data) || exit 2
dbname="$(e "$postgres_config" | shyaml get-value dbname)" || {
err "Couldn't retrieve information of ${DARKCYAN}mysql-database${NORMAL}'s relation."
exit 1
}
fi
set -e
## Ensure odoo is launched
service_def=$(get_compose_service_def "$SERVICE_NAME")
## XXXvlab: should be moved to lib
CONFIG=$SERVICE_CONFIGSTORE/etc/odoo-server.conf
ADMIN_PASSWORD=$(echo "$service_def" | shyaml -q get-value options.admin-password) || {
if [ -e "$CONFIG" ]; then
ADMIN_PASSWORD=$(grep ^admin_passwd "$CONFIG" | sed -r 's/^admin_passwd\s+=\s+(.+)$/\1/g')
fi
if [ -z "$ADMIN_PASSWORD" ]; then
err "Could not find 'admin-password' in $SERVICE_NAME service definition nor in config file."
exit 1
fi
}
containers="$(get_running_containers_for_service "$SERVICE_NAME")"
if [ -z "$containers" ]; then
err "No containers running for service $DARKYELLOW$SERVICE_NAME$NORMAL."
die "Please ensure that $DARKYELLOW$SERVICE_NAME$NORMAL is running before using '$exname'."
fi
## XXXvlab: taking first container is probably not a good idea
container="$(echo "$containers" | head -n 1)"
## XXXvlab: taking first ip is probably not a good idea
read-0 container_network container_ip < <(get_container_network_ip "$container")
DEFAULT_CURL_IMAGE=${DEFAULT_CURL_IMAGE:-docker.0k.io/curl}
cmd=(
docker run -i --rm --network "$container_network"
"$DEFAULT_CURL_IMAGE"
-sS
-X POST
-F "master_pwd=${ADMIN_PASSWORD}"
-F "name=${dbname}"
http://${container_ip}:8069/web/database/drop
)
## XXXvlab: contains password, left only for advanced debug
#debug "${cmd[@]}"
out=$("${cmd[@]}") || {
die "Posting to odoo drop API through curl was unsuccessfull."
}
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. Drop probably failed."
fi >&2
info "Dropped odoo database '$dbname'."

134
odoo-tecnativa/actions/load

@ -1,66 +1,84 @@
#!/bin/bash
## Load action gets a first argument a DIRECTORY holding the necessary files.
##
##
if [ -z "$SERVICE_DATASTORE" ]; then
echo "This script is meant to be run through 'compose' to work properly." >&2
exit 1
fi
usage="$exname [-h|--help] SRC_FILE DBNAME"
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=
source=
output=
while [ "$1" ]; do
case "$1" in
"--help"|"-h")
print_usage
print_help >&2
exit 0
;;
"--force"|"-f")
force=yes
;;
--*|-*)
err "Unexpected optional argument '$1'"
print_usage
print_usage >&2
exit 1
;;
*)
[ -z "$source" ] && { source=$1 ; shift ; continue ; }
[ -z "$dbname" ] && { dbname=$1 ; shift ; continue ; }
err "Unexpected positional argument '$1'"
print_usage
print_usage >&2
exit 1
;;
esac
shift
done
if [ -z "$source" ]; then
err "You must provide a source filename name as first argument."
print_usage
exit 1
fi
if [ -z "$dbname" ]; then
err "You must provide a database name as second argument."
print_usage
exit 1
fi
if ! [ -e "$source" ]; then
err "File '$source' not found. Please provide an existing file as first argument."
print_usage
##
## Fetch default dbname in relation to postgres-database
##
## XXXvlab: can't get real config here
if ! read-0 ts _ _ < <(get_service_relation "$SERVICE_NAME" "postgres-database"); then
err "Couldn't find relation ${DARKCYAN}postgres-database${NORMAL}."
exit 1
fi
realpath=$(realpath "$source") || exit 1
dirname="$(dirname "$realpath")" || exit 1
basename=$(basename "$realpath") || exit 1
host_path="$(get_host_path "$dirname")" || {
die "Failed to find host path for local directory: $dirname"
relation_file=$(get_relation_data_dir "$SERVICE_NAME" "$ts" "postgres-database") || {
err "Failed to find relation file"
exit 1
}
postgres_config=$(cat "$relation_file"/data) || exit 2
dbname="$(e "$postgres_config" | shyaml get-value dbname)" || {
err "Couldn't retrieve information of ${DARKCYAN}mysql-database${NORMAL}'s relation."
exit 1
}
fi
set -e
@ -79,7 +97,6 @@ ADMIN_PASSWORD=$(echo "$service_def" | shyaml -q get-value options.admin-passwor
fi
}
containers="$(get_running_containers_for_service "$SERVICE_NAME")"
if [ -z "$containers" ]; then
@ -95,25 +112,48 @@ read-0 container_network container_ip < <(get_container_network_ip "$container")
DEFAULT_CURL_IMAGE=${DEFAULT_CURL_IMAGE:-docker.0k.io/curl}
debug docker run --rm --network "$container_network" \
"-v" "$host_path:/tmp/work" \
"$DEFAULT_CURL_IMAGE" \
-sS \
-X POST \
-F "master_pwd=<hidden>" \
-F "backup_file=@/tmp/work/${source}" \
-F "name=${dbname}" \
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
{
echo -n "$chars"
cat
}
}
cmd=(
docker run -i --rm --network "$container_network"
"$DEFAULT_CURL_IMAGE"
-sS
-X POST
-F "master_pwd=${ADMIN_PASSWORD}"
-F "backup_file=@-"
-F "name=${dbname}"
http://${container_ip}:8069/web/database/restore
docker run --rm --network "$container_network" \
"-v" "$host_path:/tmp/work" \
"$DEFAULT_CURL_IMAGE" \
-sS \
-X POST \
-F "master_pwd=${ADMIN_PASSWORD}" \
-F "backup_file=@/tmp/work/${basename}" \
-F "name=${dbname}" \
http://${container_ip}:8069/web/database/restore >/dev/null || {
die "Querying odoo through curl was unsuccessfull."
)
## XXXvlab: contains password, left only for advanced debug
#debug "${cmd[@]}"
out=$(set -o pipefail; check_input | "${cmd[@]}") || {
die "Posting to odoo restore API through curl was unsuccessfull."
}
info "Restored '$source' odoo database and filestore to '$dbname'."
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'."

123
odoo-tecnativa/actions/save

@ -1,23 +1,38 @@
#!/bin/bash
## Load action gets a first argument a DIRECTORY holding the necessary files.
##
##
if [ -z "$SERVICE_DATASTORE" ]; then
echo "This script is meant to be run through 'compose' to work properly." >&2
exit 1
fi
usage="$exname [-h|--help] [--force|-f] DBNAME DEST_FILENAME"
version=0.1
usage="$exname [-h|--help] [--force|-f] [DBNAME]"
help="
USAGE:
$usage
DESCRIPTION:
Outputs to stdout the odoo zip dump of 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=
output=
while [ "$1" ]; do
case "$1" in
"--help"|"-h")
print_usage
print_help >&2
exit 0
;;
"--force"|"-f")
@ -25,45 +40,44 @@ while [ "$1" ]; do
;;
--*|-*)
err "Unexpected optional argument '$1'"
print_usage
print_usage >&2
exit 1
;;
*)
[ -z "$dbname" ] && { dbname=$1 ; shift ; continue ; }
[ -z "$output" ] && { output=$1 ; shift ; continue ; }
err "Unexpected positional argument '$1'"
print_usage
print_usage >&2
exit 1
;;
esac
shift
done
if [ -z "$dbname" ]; then
err "You must provide a database name as first argument."
print_usage
##
## Fetch default dbname in relation to postgres-database
##
## XXXvlab: can't get real config here
if ! read-0 ts _ _ < <(get_service_relation "$SERVICE_NAME" "postgres-database"); then
err "Couldn't find relation ${DARKCYAN}postgres-database${NORMAL}."
exit 1
fi
if [ -z "$output" ]; then
err "You must provide a destination filename name as second argument."
print_usage
relation_file=$(get_relation_data_dir "$SERVICE_NAME" "$ts" "postgres-database") || {
err "Failed to find relation file"
exit 1
fi
}
postgres_config=$(cat "$relation_file"/data) || exit 2
if [ -e "$output" -a -z "$force" ]; then
err "File '$output' exists already. Force overwrite with -f or --force."
print_usage
dbname="$(e "$postgres_config" | shyaml get-value dbname)" || {
err "Couldn't retrieve information of ${DARKCYAN}mysql-database${NORMAL}'s relation."
exit 1
fi
realpath=$(realpath "$output") || exit 1
dirname="$(dirname "$realpath")" || exit 1
basename=$(basename "$realpath") || exit 1
host_path="$(get_host_path "$dirname")" || {
die "Failed to find host path for local directory: $dirname"
}
fi
set -e
@ -82,7 +96,6 @@ ADMIN_PASSWORD=$(echo "$service_def" | shyaml -q get-value options.admin-passwor
fi
}
containers="$(get_running_containers_for_service "$SERVICE_NAME")"
if [ -z "$containers" ]; then
@ -99,28 +112,42 @@ read-0 container_network container_ip < <(get_container_network_ip "$container")
DEFAULT_CURL_IMAGE=${DEFAULT_CURL_IMAGE:-docker.0k.io/curl}
debug docker run --rm --network "$container_network" \
"-v" "$host_path:/tmp/work" \
"$DEFAULT_CURL_IMAGE" \
-X POST \
-F "master_pwd=<hidden>" \
-F "name=${dbname}" \
-F "backup_format=zip" \
-o "/tmp/work/$basename" \
http://${container_ip}:8069/web/database/backup
docker run --rm --network "$container_network" \
"-v" "$host_path:/tmp/work" \
"$DEFAULT_CURL_IMAGE" \
-sS \
-X POST \
-F "master_pwd=${ADMIN_PASSWORD}" \
-F "name=${dbname}" \
-F "backup_format=zip" \
-o "/tmp/work/$basename" \
http://${container_ip}:8069/web/database/backup || {
die "Querying odoo through curl was unsuccessfull."
check_output() {
local chars
read -n 2 -r chars
if [ "$chars" != "PK" ]; then
out=$(cat)
errmsg=$(echo "$out" | grep "alert-danger")
errmsg=${errmsg#*>}
errmsg=${errmsg%%<*}
if [ -n "$errmsg" ]; then
errmsg=$(echo "$errmsg" | recode html..utf8)
die "$errmsg"
fi
err "Unexpected output not matching ZIP signature. Dump probably failed."
exit 1
fi
{
echo -n "$chars"
cat
}
}
info "Saved '$dbname' odoo database and filestore to '$output'."
cmd=(
docker run --rm --network "$container_network"
"$DEFAULT_CURL_IMAGE"
-sS
-X POST
-F "master_pwd=${ADMIN_PASSWORD}"
-F "name=${dbname}"
-F "backup_format=zip"
http://${container_ip}:8069/web/database/backup
)
## XXXvlab: contains password, left only for advanced debug
#debug "${cmd[@]}"
set -o pipefail
"${cmd[@]}" | check_output &&
info "Requested odoo '$dbname' dump and outputted result to stdout."
Loading…
Cancel
Save