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.

215 lines
5.5 KiB

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