provisioning tool for building opinionated architecture
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.

200 lines
5.2 KiB

10 months ago
  1. #!/bin/bash
  2. confirm() {
  3. read -p "$1 ([y]es or [N]o): "
  4. case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
  5. y | yes) echo "yes" ;;
  6. *) echo "no" ;;
  7. esac
  8. }
  9. synopsis() {
  10. echo "usage: "
  11. printf "\t list | console | connections\n"
  12. printf "\t ---------------------------\n"
  13. printf "\t use <DB_NAME>\n"
  14. printf "\t lookup <DB_NAME> <TERM>\n"
  15. printf "\t create <DB_NAME> [PASSWORD]\n"
  16. printf "\t ---------------------------\n"
  17. printf "\t backup <DB_NAME> [FOLDER]\n"
  18. printf "\t restore <DB_NAME> <FILE> [--yes]\n"
  19. printf "\t ---------------------------\n"
  20. printf "\t rename <DB_NAME> <NEW_NAME>\n"
  21. }
  22. list() {
  23. lxc exec ct1 -- su - postgres -c "psql -Atc \"SELECT datname FROM pg_database WHERE datistemplate=false AND datname<>'postgres';\""
  24. }
  25. console() {
  26. if [[ -z $1 ]]; then
  27. lxc exec ct1 -- su - postgres
  28. else
  29. lxc exec ct1 -- su - postgres -c "$1"
  30. fi
  31. }
  32. connections() {
  33. PROCESSES=$(console "psql -c \"select pid as process_id, usename as username, datname as database_name, client_addr as client_address, application_name, backend_start, state, state_change from pg_stat_activity WHERE datname<>'postgres' ORDER BY datname, usename;\"")
  34. printf "$PROCESSES\n"
  35. }
  36. use() {
  37. echo >&2 "about to connect to <${DB_NAME}> ..."
  38. if [[ -z $1 ]]; then
  39. lxc exec ct1 -- su - postgres -c "psql $DB_NAME"
  40. else
  41. local sql="psql -A -t $DB_NAME -c \\\"$1;\\\""
  42. local command="su - postgres -c \"$sql\""
  43. lxc exec ct1 -- sh -c "$command"
  44. fi
  45. }
  46. create() {
  47. echo >&2 "about to create to <${DB_NAME}> ..."
  48. source /opt/debian-bash/lib/functions.sh
  49. local DBs=($(list))
  50. if ! $(containsElement DBs $DB_NAME); then
  51. local SQL="CREATE USER \\\\\\\"$DB_NAME\\\\\\\" WITH PASSWORD '$DB_PASSWORD'"
  52. local command="su - postgres sh -c \"psql -c \\\"$SQL\\\"\" && su - postgres sh -c \"createdb -O $DB_NAME $DB_NAME\" && echo CREATE DB"
  53. # echo $command
  54. lxc exec ct1 -- sh -c "$command"
  55. else
  56. echo $DB_NAME already exists!
  57. fi
  58. }
  59. lookup() {
  60. if [[ ${#TERM} -ge 4 ]]; then
  61. echo >&2 "about to lookup term <${TERM}> over all tables of database <$DB_NAME> ..."
  62. local command="pg_dump --data-only --inserts $DB_NAME 2>/dev/null | grep --color \"$TERM\""
  63. lxc exec ct1 -- su - postgres -c "$command"
  64. else
  65. echo "term <$TERM> should contain 4 chars minimum!" && exit 2
  66. fi
  67. }
  68. backup() {
  69. if [[ ! -d "$FOLDER" ]]; then
  70. echo "error: Folder required!"
  71. file $FOLDER
  72. exit 2
  73. fi
  74. DATE=$(date '+%F')
  75. ARCHIVE="$FOLDER"/$DB_NAME-$DATE.postgres.gz
  76. if [[ -f $ARCHIVE ]]; then
  77. VERSION_CONTROL=numbered mv -b $ARCHIVE "$FOLDER"/$DB_NAME-$DATE-daily.postgres.gz
  78. fi
  79. echo "backup $DB_NAME $FOLDER"
  80. PGPASSWORD=$DB_NAME pg_dump -U $DB_NAME $DB_NAME -h ct1.lxd | gzip >"$ARCHIVE"
  81. echo "archive file created: $ARCHIVE"
  82. }
  83. restore() {
  84. echo "restore $DB_NAME $FILE"
  85. if [[ ! -f "$FILE" ]]; then
  86. echo "error: Backup file (*.postgres.gz) required!"
  87. file $FILE
  88. exit 2
  89. fi
  90. PROCESSES=$(console "psql -c \"select pid as process_id, usename as username, datname as database_name, client_addr as client_address, application_name, backend_start, state, state_change from pg_stat_activity WHERE datname='$DB_NAME';\"")
  91. PROCESS_COUNT=$(echo "$PROCESSES" | wc -l)
  92. if [[ $PROCESS_COUNT -gt 3 ]]; then
  93. echo "FAILURE: There are some connections to database, please consider stopping bound services"
  94. echo
  95. printf "$PROCESSES\n"
  96. exit 2
  97. fi
  98. if [[ $YES == "true" || "yes" == $(confirm "RESTORATION will drop DATABASE, please acknowledge with care!!!") ]]; then
  99. FOLDER="$HOME/RECOVERY_POSTGRES"
  100. mkdir -p "$FOLDER"
  101. backup
  102. echo "backup successful, now drop and restore"
  103. lxc exec ct1 -- su - postgres -c "dropdb $DB_NAME && createdb -O $DB_NAME $DB_NAME"
  104. gunzip -c "$FILE" | grep -v "^CREATE DATABASE" | PGPASSWORD=$DB_NAME PGOPTIONS='--client-min-messages=warning' psql -X -q -1 -v ON_ERROR_STOP=1 --pset pager=off -U $DB_NAME -h ct1.lxd $DB_NAME 2>&1 >/dev/null
  105. else
  106. exit 1
  107. fi
  108. }
  109. rename() {
  110. echo "rename <$DB_NAME> to <$DB_NEW_NAME>"
  111. mapfile -t LIST <<<"$(list)"
  112. found=false
  113. for db in "${LIST[@]}"; do
  114. [[ "$db" == "$DB_NEW_NAME" ]] && echoerr "destination database <$DB_NEW_NAME> already exists! Please provide another name." && exit 11
  115. [[ "$db" == "$DB_NAME" ]] && found=true
  116. done
  117. $found || (echoerr "source database <$DB_NAME> not found!" && exit 12)
  118. console "psql -c \"ALTER DATABASE \\\"$DB_NAME\\\" RENAME TO \\\"$DB_NEW_NAME\\\" \""
  119. console "psql -c \"ALTER USER \\\"$DB_NAME\\\" RENAME TO \\\"$DB_NEW_NAME\\\" \""
  120. console "psql -c \"ALTER USER \\\"$DB_NEW_NAME\\\" PASSWORD '$DB_NEW_NAME' \""
  121. }
  122. # MAIN
  123. . "$MIAOU_BASEDIR/lib/init.sh"
  124. [[ $# -lt 1 ]] && synopsis && exit 1
  125. ACTION=$1
  126. case $ACTION in
  127. console)
  128. shift
  129. TAIL="$@"
  130. console "$TAIL"
  131. ;;
  132. list)
  133. list
  134. ;;
  135. connections)
  136. connections
  137. ;;
  138. use)
  139. [[ $# -lt 2 ]] && synopsis && exit 1
  140. DB_NAME=$2
  141. shift 2
  142. TAIL="$@"
  143. use "$TAIL"
  144. ;;
  145. create)
  146. [[ $# -lt 2 ]] && synopsis && exit 1
  147. DB_NAME=$2
  148. DB_PASSWORD=${3:-$DB_NAME}
  149. create
  150. ;;
  151. lookup)
  152. [[ $# -lt 3 ]] && synopsis && exit 1
  153. DB_NAME=$2
  154. TERM=$3
  155. lookup
  156. ;;
  157. backup)
  158. [[ $# -lt 2 ]] && synopsis && exit 1
  159. DB_NAME=$2
  160. FOLDER=${3:-.}
  161. backup
  162. ;;
  163. restore)
  164. [[ $# -lt 3 ]] && synopsis && exit 1
  165. DB_NAME=$2
  166. FILE=$3
  167. YES=true
  168. restore
  169. ;;
  170. rename)
  171. [[ $# -lt 3 ]] && synopsis && exit 1
  172. DB_NAME=$2
  173. DB_NEW_NAME=$3
  174. rename
  175. ;;
  176. *)
  177. synopsis
  178. exit 1
  179. ;;
  180. esac