|
1 | 1 | #!/bin/bash |
2 | 2 |
|
| 3 | +# Exit immediately if a command exits with a non-zero status |
| 4 | +set -e |
| 5 | + |
| 6 | +# Print error line if something goes wrong |
| 7 | +trap 'echo "ERROR: Restore failed at line $LINENO"; exit 1' ERR |
| 8 | + |
3 | 9 | # Enable automatic export of variables |
4 | 10 | set -a |
5 | 11 |
|
6 | | -# Load the .env file from the project root |
| 12 | +# Load environment variables from the project root |
7 | 13 | source "$(dirname "$0")/../../.env" |
8 | 14 |
|
9 | | -# Dynamically generate volume names based on the project |
| 15 | +# Generate volume names |
10 | 16 | DB_VOLUME="${COMPOSE_PROJECT_NAME}_db_volume" |
11 | 17 | USERDATA_VOLUME="${COMPOSE_PROJECT_NAME}_userdata_volume" |
12 | 18 |
|
13 | | -# Check if the /restore folder exists and create it if necessary |
14 | | -if [ ! -d "/restore" ]; then |
15 | | - mkdir -p /restore |
16 | | -fi |
| 19 | +# Ensure /restore directory exists |
| 20 | +mkdir -p /restore |
17 | 21 |
|
18 | | -# Functions for the various restore processes |
| 22 | +# ------------------------- |
| 23 | +# Restore functions |
| 24 | +# ------------------------- |
19 | 25 |
|
20 | 26 | restore_db() { |
| 27 | + local BACKUP_NAME |
21 | 28 | if [ -z "$1" ]; then |
22 | | - echo "Restoring the latest database backup..." |
23 | | - # Get the latest database backup |
24 | | - LATEST_DB_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/db | head -n 1") |
| 29 | + echo "[DB] Restoring latest backup..." |
| 30 | + BACKUP_NAME=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/db | head -n 1") |
25 | 31 | else |
26 | | - echo "Restoring database backup from $1..." |
27 | | - LATEST_DB_BACKUP="database_$1.tar.gz" |
| 32 | + echo "[DB] Restoring backup from timestamp: $1" |
| 33 | + BACKUP_NAME="database_$1.tar.gz" |
28 | 34 | fi |
29 | | - scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/db/${LATEST_DB_BACKUP} /restore/database.tar.gz |
| 35 | + |
| 36 | + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/db/${BACKUP_NAME} /restore/database.tar.gz |
30 | 37 | docker run --rm -v ${DB_VOLUME}:/volume -v /restore:/restore alpine sh -c "tar -xzf /restore/database.tar.gz -C /volume" |
| 38 | + rm /restore/database.tar.gz |
31 | 39 | docker restart ${MYSQL_CONTAINER_NAME} |
| 40 | + echo "[DB] Restore complete" |
32 | 41 | } |
33 | 42 |
|
34 | 43 | restore_userdata() { |
| 44 | + local BACKUP_NAME |
35 | 45 | if [ -z "$1" ]; then |
36 | | - echo "Restoring the latest userdata backup..." |
37 | | - # Get the latest userdata backup |
38 | | - LATEST_USERDATA_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/userdata | head -n 1") |
| 46 | + echo "[USERDATA] Restoring latest backup..." |
| 47 | + BACKUP_NAME=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/userdata | head -n 1") |
39 | 48 | else |
40 | | - echo "Restoring userdata backup from $1..." |
41 | | - LATEST_USERDATA_BACKUP="userdata_$1.tar.gz" |
| 49 | + echo "[USERDATA] Restoring backup from timestamp: $1" |
| 50 | + BACKUP_NAME="userdata_$1.tar.gz" |
42 | 51 | fi |
43 | | - scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata/${LATEST_USERDATA_BACKUP} /restore/userdata.tar.gz |
| 52 | + |
| 53 | + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/userdata/${BACKUP_NAME} /restore/userdata.tar.gz |
44 | 54 | docker run --rm -v ${USERDATA_VOLUME}:/volume -v /restore:/restore alpine sh -c "tar -xzf /restore/userdata.tar.gz -C /volume" |
| 55 | + rm /restore/userdata.tar.gz |
45 | 56 | docker restart ${LUCEE_CONTAINER_NAME} |
| 57 | + echo "[USERDATA] Restore complete" |
46 | 58 | } |
47 | 59 |
|
48 | 60 | restore_lucee_image() { |
| 61 | + local BACKUP_NAME |
49 | 62 | if [ -z "$1" ]; then |
50 | | - echo "Restoring the latest Lucee image backup..." |
51 | | - # Get the latest Lucee image backup |
52 | | - LATEST_LUCEE_BACKUP=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/lucee | head -n 1") |
| 63 | + echo "[LUCEE] Restoring latest image..." |
| 64 | + BACKUP_NAME=$(ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls -t ${REMOTE_BACKUP_PATH}/lucee | head -n 1") |
53 | 65 | else |
54 | | - echo "Restoring Lucee image backup from $1..." |
55 | | - LATEST_LUCEE_BACKUP="image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}_$1.tar" |
| 66 | + echo "[LUCEE] Restoring image from timestamp: $1" |
| 67 | + BACKUP_NAME="image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}_$1.tar" |
56 | 68 | fi |
57 | | - scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/lucee/${LATEST_LUCEE_BACKUP} /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar |
58 | | - docker load -i /restore/image_${LUCEE_IMAGE}_${LUCEE_IMAGE_VERSION}.tar |
| 69 | + |
| 70 | + scp -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP}:${REMOTE_BACKUP_PATH}/lucee/${BACKUP_NAME} /restore/image.tar |
| 71 | + docker load -i /restore/image.tar |
| 72 | + rm /restore/image.tar |
| 73 | + echo "[LUCEE] Image restore complete" |
59 | 74 | } |
60 | 75 |
|
61 | 76 | list_backups() { |
62 | 77 | echo "Available backups on remote server:" |
63 | | - echo "Database backups:" |
| 78 | + echo "-----------------------------------" |
| 79 | + echo "Database:" |
64 | 80 | ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/db" |
65 | 81 | echo "" |
66 | | - echo "Userdata backups:" |
| 82 | + echo "Userdata:" |
67 | 83 | ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/userdata" |
68 | 84 | echo "" |
69 | | - echo "Lucee image backups:" |
| 85 | + echo "Lucee images:" |
70 | 86 | ssh -i ${SSH_KEY_PATH} ${SERVER_USER}@${SERVER_IP} "ls ${REMOTE_BACKUP_PATH}/lucee" |
71 | 87 | echo "" |
72 | 88 | } |
73 | 89 |
|
74 | | -# Show help if no options have been specified |
| 90 | +# ------------------------- |
| 91 | +# CLI Argument handling |
| 92 | +# ------------------------- |
| 93 | + |
75 | 94 | if [ $# -eq 0 ]; then |
76 | | - echo "Usage: $0 [--db [TIMESTAMP]] [--userdata [TIMESTAMP]] [--lucee-image [TIMESTAMP]] [--list]" |
| 95 | + echo "Usage:" |
| 96 | + echo " $0 --db [TIMESTAMP] Restore database (latest if none given)" |
| 97 | + echo " $0 --userdata [TIMESTAMP] Restore userdata volume" |
| 98 | + echo " $0 --lucee-image [TIMESTAMP] Restore Lucee image" |
| 99 | + echo " $0 --list List available backups" |
77 | 100 | exit 1 |
78 | 101 | fi |
79 | 102 |
|
80 | | -# Process the specified options |
81 | 103 | while [[ "$#" -gt 0 ]]; do |
82 | 104 | case $1 in |
83 | | - --db) restore_db "$2"; shift ;; |
84 | | - --userdata) restore_userdata "$2"; shift ;; |
85 | | - --lucee-image) restore_lucee_image "$2"; shift ;; |
86 | | - --list) list_backups; exit 0 ;; |
87 | | - *) echo "Unknown option: $1"; exit 1 ;; |
| 105 | + --db) |
| 106 | + if [[ -n "$2" && "$2" != --* ]]; then |
| 107 | + restore_db "$2" |
| 108 | + shift |
| 109 | + else |
| 110 | + restore_db |
| 111 | + fi |
| 112 | + ;; |
| 113 | + --userdata) |
| 114 | + if [[ -n "$2" && "$2" != --* ]]; then |
| 115 | + restore_userdata "$2" |
| 116 | + shift |
| 117 | + else |
| 118 | + restore_userdata |
| 119 | + fi |
| 120 | + ;; |
| 121 | + --lucee-image) |
| 122 | + if [[ -n "$2" && "$2" != --* ]]; then |
| 123 | + restore_lucee_image "$2" |
| 124 | + shift |
| 125 | + else |
| 126 | + restore_lucee_image |
| 127 | + fi |
| 128 | + ;; |
| 129 | + --list) |
| 130 | + list_backups |
| 131 | + exit 0 |
| 132 | + ;; |
| 133 | + *) |
| 134 | + echo "ERROR: Unknown option: $1" |
| 135 | + exit 1 |
| 136 | + ;; |
88 | 137 | esac |
89 | 138 | shift |
90 | 139 | done |
91 | 140 |
|
92 | | -# Disable automatic export of variables |
93 | 141 | set +a |
0 commit comments