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

10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
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. 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