You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.5 KiB

  1. #!/bin/bash
  2. ## compose: no-hooks
  3. if [ -z "$SERVICE_DATASTORE" ]; then
  4. echo "This script is meant to be run through 'compose' to work properly." >&2
  5. exit 1
  6. fi
  7. version=0.1
  8. usage="$exname [-h|--help] [--force|-f] [DBNAME]"
  9. help="
  10. USAGE:
  11. $usage
  12. DESCRIPTION:
  13. Read stdin and send it to the restore API of odoo service to restore
  14. in the database DBNAME. If DBNAME is not provided, it'll take the
  15. default odoo database from the ${DARKCYAN}postgres-database${NORMAL} relation of
  16. current service.
  17. EXAMPLES:
  18. $exname < dump.zip
  19. $exname odoo2 < odoo2.zip
  20. "
  21. dbname=
  22. neutralize=
  23. while [ "$1" ]; do
  24. case "$1" in
  25. "--help"|"-h")
  26. print_help >&2
  27. exit 0
  28. ;;
  29. "--neutralize"|"-n")
  30. neutralize=yes
  31. ;;
  32. "--force"|"-f")
  33. force=yes
  34. ;;
  35. --*|-*)
  36. err "Unexpected optional argument '$1'"
  37. print_usage >&2
  38. exit 1
  39. ;;
  40. *)
  41. [ -z "$dbname" ] && { dbname=$1 ; shift ; continue ; }
  42. err "Unexpected positional argument '$1'"
  43. print_usage >&2
  44. exit 1
  45. ;;
  46. esac
  47. shift
  48. done
  49. version:ge() { [ "$(printf '%s\n' "$@" | sort -rV | head -n 1)" == "$1" ]; }
  50. version:lt() { ! version:ge "$@"; }
  51. if [ -z "$dbname" ]; then
  52. dbname=$(relation:get "$SERVICE_NAME:postgres-database" dbname) || {
  53. err "Couldn't retrieve information of" \
  54. "${DARKYELLOW}$SERVICE_NAME${NORMAL}-->${DARKCYAN}postgres-database${NORMAL}."
  55. exit 1
  56. }
  57. fi
  58. . "$CHARM_PATH/lib/common"
  59. set -e
  60. curl_opts=()
  61. ADMIN_PASSWORD=$(odoo:get-admin-password) || {
  62. err "Couldn't retrieve admin password for ${DARKYELLOW}$SERVICE_NAME${NORMAL}."
  63. exit 1
  64. }
  65. container="$(get_running_container_for_service "$SERVICE_NAME")" || {
  66. err "Couldn't find running container for service ${DARKYELLOW}$SERVICE_NAME${NORMAL}."
  67. exit 1
  68. }
  69. odoo_version=$(docker exec "$container" python -c 'import odoo.release; print(odoo.release.version)') || {
  70. err "Failed to get odoo version."
  71. exit 1
  72. }
  73. if version:lt "$odoo_version" "16.0" && [ -n "$neutralize" ]; then
  74. err "Option \`\`--neutralize\`\` (or \`\`-n\`\`)" \
  75. "is only available for odoo ${WHITE}16.0${NORMAL}+."
  76. echo " Service ${DARKYELLOW}$SERVICE_NAME${NORMAL} is running odoo ${WHITE}$odoo_version${NORMAL}" >&2
  77. exit 1
  78. fi
  79. if [ -n "$neutralize" ]; then
  80. curl_opts+=(-F "neutralize_database=true")
  81. fi
  82. container_network_ip=$(get_healthy_container_ip_for_service "$SERVICE_NAME" 8069 4) || {
  83. err "Please ensure that $DARKYELLOW$service$NORMAL is running before using '$exname'."
  84. exit 1
  85. }
  86. container_ip=${container_network_ip##*:}
  87. container_network=${container_network_ip%%:*}
  88. DEFAULT_CURL_IMAGE=${DEFAULT_CURL_IMAGE:-docker.0k.io/curl}
  89. check_input() {
  90. local chars
  91. read -n 2 -r chars
  92. if [ "$chars" != "PK" ]; then
  93. err "Unexpected input not matching ZIP signature. Invalid dump."
  94. echo " First chars: '$chars'"
  95. exit 1
  96. fi
  97. {
  98. printf "%s" "$chars"
  99. cat
  100. }
  101. }
  102. ## Beware that we are not on the host, so we need to create the
  103. ## fifo in a place we can share with the curl container.
  104. export TMPDIR=/var/cache/compose
  105. settmpdir RESTORE_TMPDIR
  106. mkfifo "$RESTORE_TMPDIR/fifo"
  107. ## Using fifo because if using ``@-`` curl will load all the database
  108. ## in memory before sending it, which is NOT desirable as the size of
  109. ## the database can be greater than available memory. Using fifo, we
  110. ## force the data to be streamed.
  111. cmd=(
  112. docker run -i --rm --network "$container_network"
  113. -v "$RESTORE_TMPDIR/fifo:/tmp/restore/fifo"
  114. "$DEFAULT_CURL_IMAGE"
  115. -sS
  116. -X POST
  117. -F "master_pwd=${ADMIN_PASSWORD}"
  118. -F "name=${dbname}"
  119. "${curl_opts[@]}"
  120. -F "backup_file=@/tmp/restore/fifo"
  121. http://${container_ip}:8069/web/database/restore
  122. )
  123. ## XXXvlab: contains password, left only for advanced debug
  124. #echo "COMMAND: ${cmd[@]}" >&2
  125. "${cmd[@]}" > "$RESTORE_TMPDIR/out" &
  126. pid=$!
  127. check_input > "$RESTORE_TMPDIR/fifo"
  128. wait "$pid" || {
  129. die "Posting to odoo restore API through curl was unsuccessfull."
  130. }
  131. out=$(cat "$RESTORE_TMPDIR/out")
  132. if [[ "$out" == *"<html>"* ]]; then
  133. errmsg=$(echo "$out" | grep "alert-danger")
  134. errmsg=${errmsg#*>}
  135. errmsg=${errmsg%%<*}
  136. if [ "$errmsg" ]; then
  137. errmsg=$(echo "$errmsg" | recode html..utf8)
  138. die "$errmsg"
  139. fi
  140. die "Unexpected output. Restore probably failed."
  141. fi >&2
  142. info "Restored stdin dump to odoo '$dbname'."