forked from pipech/erpnext-docker-debian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
frank
190 lines (165 loc) · 4.24 KB
/
frank
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
# usage infomation
usage() {
echo "Named volume backup & restore utility"
echo "Usage: . frank <init|backup|restore|delete> <options>"
}
FRANK_CONFIG="frank.config"
init() {
echo "Stack name to backup, seperate by space:"
read STACK_NAME
DEFAULT_BASE_BACKUP_DIR="/backup"
echo "Backup dir (Default: ${DEFAULT_BASE_BACKUP_DIR}):"
read BASE_BACKUP_DIR
if [ "${BASE_BACKUP_DIR}" == "" ]; then
BASE_BACKUP_DIR="${DEFAULT_BASE_BACKUP_DIR}"
fi
DEFAULT_FOLDER_RETAIN_DAYS="7"
echo "Retain folder for n days (Default: ${DEFAULT_FOLDER_RETAIN_DAYS}):"
read FOLDER_RETAIN_DAYS
if [ "${FOLDER_RETAIN_DAYS}" == "" ]; then
FOLDER_RETAIN_DAYS="${DEFAULT_FOLDER_RETAIN_DAYS}"
fi
# write variable to config file
cat > "${FRANK_CONFIG}" <<EOF
STACK_NAME="${STACK_NAME}"
BASE_BACKUP_DIR="${BASE_BACKUP_DIR}"
FOLDER_RETAIN_DAYS="${FOLDER_RETAIN_DAYS}"
EOF
}
backup() {
BACKUP_DATE=`date '+%Y-%m-%d-%H%M%S'`
BACKUP_DIR="${BASE_BACKUP_DIR}/${BACKUP_DATE}"
echo "Starting backup ${BACKUP_DATE}"
for STACK in ${STACK_NAME}
do
# put output of docker volume into name_volumes array
# -q quiet will show only name
# -f filter will filter name with STACK
mapfile -t NAME_VOLUMES < <(docker volume ls -q -f "name=${STACK}_")
if [[ ${#NAME_VOLUMES[@]} -eq 0 ]]; then
echo "Error: Not found volume"
return 0
fi
# make folder
mkdir -p ${BACKUP_DIR}
if [[ ! -d ${BACKUP_DIR} ]]; then
echo "Error: Cannot create folder"
return 0
fi
# backup
echo "Stack ${STACK}"
# loop through array
for NAME_VOLUME in "${NAME_VOLUMES[@]}"
do
echo "Backing up ${NAME_VOLUME}"
# backup docker volume using loomchild/volume-backup docker image
docker run --rm \
-v ${NAME_VOLUME}:/volume \
-v ${BACKUP_DIR}:/backup \
loomchild/volume-backup \
backup \
${NAME_VOLUME}
done
done
cp "${BASE_BACKUP_DIR}/backup_logs.txt" "${BACKUP_DIR}/logs.txt"
return 1
}
restore() {
BACKUP_DIR="${BASE_BACKUP_DIR}/${BACKUP_FOLDER}"
# check folder
if [[ ! -d ${BACKUP_DIR} ]]; then
echo "Error: Folder not found"
return 0
fi
# get file in backup into array
shopt -s extglob nullglob
TAR_VOLUMES=(${BACKUP_DIR}/*.tar.bz2)
shopt -u extglob nullglob
if [[ ${#TAR_VOLUMES[@]} -eq 0 ]]; then
echo "Error: TAR file not found"
return 0
fi
# restore
echo "Starting restore"
# loop through array
for TAR_VOLUME in "${TAR_VOLUMES[@]}"
do
echo "Restoring ${TAR_VOLUME}"
FILE=$(basename -- "${TAR_VOLUME}")
FILE_NAME="${FILE%%.*}"
# restore docker volume using loomchild/volume-backup docker image
cat ${TAR_VOLUME} | docker run -i --rm \
-v ${FILE_NAME}:/volume \
loomchild/volume-backup \
restore \
-
done
return 1
}
delete() {
# get folder name in base_backup_dir
shopt -s extglob nullglob
BACKUP_FOLDER_NAMES=(${BASE_BACKUP_DIR}/*/)
shopt -u extglob nullglob
# loop through folder
for FOLDER_PATH in "${BACKUP_FOLDER_NAMES[@]}"
do
FOLDER_NAME=$(basename -- "${FOLDER_PATH}")
FOLDER_DATE=${FOLDER_NAME:0:10}
FOLDER_AGE=$(datediff ${FOLDER_DATE})
if [[ "${FOLDER_AGE}" -gt "${FOLDER_RETAIN_DAYS}" ]]; then
# never delete folder younger that 3 days
if [[ "${FOLDER_AGE}" -gt "3" ]]; then
echo "Delete folder ${FOLDER_PATH}"
sudo rm -rf "${FOLDER_PATH}"
fi
fi
done
return 1
}
datediff() {
# calculate date diff
# Usage: datediff "2018-07-15" "2018-07-01"
D1=$(date -d "$1" +%s)
# if there're only one arguments it will calculate datediff from today
if [[ -z $2 ]]; then
D2=$(date +%s)
else
D2=$(date -d "$2" +%s)
fi
# return value in days
echo $(( ((D1-D2) > 0 ? (D1-D2) : (D2-D1)) / 86400 ))
}
# read value from config, if not init
if [ "$1" != "init" ]; then
# TODO:
# Using source is dangerous because whatever is in <filename>
# will be run in your shell, such as rm -rf /, which could be very dangerous.
# https://askubuntu.com/questions/367136/how-do-i-read-a-variable-from-a-file/367143#367143
source "${FRANK_CONFIG}"
fi
# command
case $1 in
"init")
init
;;
"backup")
backup > "${BASE_BACKUP_DIR}/backup_logs.txt"
;;
"restore")
if [[ -z $2 ]]; then
echo "Error: Specify folder name"
echo "Usage: . frank restore 2018-07-20-161800"
else
BACKUP_FOLDER=$2
restore
fi
;;
"delete")
delete > "${BASE_BACKUP_DIR}/delete_logs.txt"
;;
*)
usage
;;
esac