mirror of
https://github.com/tiredofit/docker-db-backup.git
synced 2025-12-21 21:33:28 +01:00
mongoDB restore always dropped schema, irrespective of flag variant, due to wildcard being the first option in case.
1176 lines
38 KiB
Plaintext
Executable File
1176 lines
38 KiB
Plaintext
Executable File
#!/command/with-contenv /bin/bash
|
|
|
|
source /assets/functions/00-container
|
|
source /assets/defaults/10-db-backup
|
|
source /assets/functions/10-db-backup
|
|
PROCESS_NAME="db-backup-restore"
|
|
|
|
oldcolumns=$COLUMNS
|
|
|
|
########################################################################################
|
|
### System Functions ###
|
|
########################################################################################
|
|
### Colours
|
|
# Foreground (Text) Colors
|
|
cdgy="\e[90m" # Color Dark Gray
|
|
clg="\e[92m" # Color Light Green
|
|
clm="\e[95m" # Color Light Magenta
|
|
cwh="\e[97m" # Color White
|
|
|
|
# Turns off all formatting
|
|
coff="\e[0m" # Color Off
|
|
|
|
# Background Colors
|
|
bdr="\e[41m" # Background Color Dark Red
|
|
bdg="\e[42m" # Background Color Dark Green
|
|
bdb="\e[44m" # Background Color Dark Blue
|
|
bdm="\e[45m" # Background Color Dark Magenta
|
|
bdgy="\e[100m" # Background Color Dark Gray
|
|
blr="\e[101m" # Background Color Light Red
|
|
boff="\e[49m" # Background Color Off
|
|
|
|
|
|
if [ -z "${1}" ] ; then
|
|
interactive_mode=true
|
|
else
|
|
case "$1" in
|
|
"-h" )
|
|
cat <<EOF
|
|
${IMAGE_NAME} Restore Tool ${IMAGE_VERSION}
|
|
(c) 2023 Dave Conroy (https://github.com/tiredofit) (https://www.tiredofit.ca)
|
|
|
|
This script will assist you in recovering databases taken by the Docker image.
|
|
You will be presented with a series of menus allowing you to choose:
|
|
- What file to restore
|
|
- What type of DB Backup
|
|
- What Host to restore to
|
|
- What Database Name to restore to
|
|
- What Database User to use
|
|
- What Database Password to use
|
|
- What Database Port to use
|
|
|
|
The image will try to do autodetection based on the filename for the type, hostname, and database name.
|
|
The image will also allow you to use environment variables or Docker secrets used to backup the images
|
|
|
|
The script can also be executed skipping the interactive mode by using the following syntax/
|
|
|
|
$(basename "$0") <filename> <db_type> <db_hostname> <db_name> <db_user> <db_pass> <db_port>
|
|
|
|
If you only enter some of the arguments you will be prompted to fill them in.
|
|
|
|
Other arguments
|
|
-h This help screen
|
|
|
|
EOF
|
|
exit 0
|
|
;;
|
|
"-i" )
|
|
echo "interactive mode"
|
|
interactive_mode=true
|
|
;;
|
|
* )
|
|
interactive_mode=false
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
|
|
control_c() {
|
|
if [ -f "${restore_vars}" ] ; then rm -rf "${restore_vars}" ; fi
|
|
print_warn "User aborted"
|
|
exit
|
|
}
|
|
|
|
get_filename() {
|
|
COLUMNS=12
|
|
prompt="Please select a file to restore:"
|
|
options=( $(find "${DEFAULT_FILESYSTEM_PATH}" -type f -maxdepth 2 -not -name '*.md5' -not -name '*.sha1' -print0 | sort -z | xargs -0) )
|
|
PS3="$prompt "
|
|
select opt in "${options[@]}" "Custom" "Quit" ; do
|
|
if (( REPLY == 2 + ${#options[@]} )) ; then
|
|
echo "Bye!"
|
|
exit 2
|
|
elif (( REPLY == 1 + ${#options[@]} )) ; then
|
|
while [ ! -f "${opt}" ] ; do
|
|
read -p "What path and filename to restore: " opt
|
|
if [ ! -f "${opt}" ] ; then
|
|
print_error "File not found. Please retry.."
|
|
fi
|
|
done
|
|
break
|
|
elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
|
|
break
|
|
else
|
|
echo "Invalid option. Try another one."
|
|
fi
|
|
done
|
|
COLUMNS=$oldcolumns
|
|
r_filename=${opt}
|
|
}
|
|
|
|
get_dbhost() {
|
|
p_dbhost=$(basename -- "${r_filename}" | cut -d _ -f 3)
|
|
if [ -n "${p_dbhost}" ]; then
|
|
parsed_host=true
|
|
print_debug "Parsed DBHost: ${p_dbhost}"
|
|
|
|
if grep -q "${p_dbhost}" "${restore_vars}" ; then
|
|
detected_host_num=$(grep "${p_dbhost}" "${restore_vars}" | head -n1 | cut -c 3,4)
|
|
detected_host_value=$(grep "${p_dbhost}" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
fi
|
|
|
|
if [ -z "${detected_host_value}" ] && [ -z "${parsed_host}" ]; then
|
|
print_debug "Parsed DBHost Variant: 1 - No Env, No Parsed Filename"
|
|
q_dbhost_variant=1
|
|
q_dbhost_menu=$(cat <<EOF
|
|
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_host_value}" ] && [ -z "${parsed_host}" ]; then
|
|
print_debug "Parsed DBHost Variant: 2 - Env, No Parsed Filename"
|
|
q_dbhost_variant=2
|
|
q_dbhost_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Hostname
|
|
E ) Environment Variable DB${detected_host_num}_HOST: '${detected_host_value}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -z "${detected_host_value}" ] && [ -n "${parsed_host}" ]; then
|
|
print_debug "Parsed DBHost Variant: 3 - No Env, Parsed Filename"
|
|
q_dbhost_variant=3
|
|
q_dbhost_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Hostname
|
|
F ) Parsed Filename Host: '${p_dbhost}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_host_value}" ] && [ -n "${parsed_host}" ]; then
|
|
print_debug "Parsed DBHost Variant: 4 - Env, Parsed Filename"
|
|
q_dbhost_variant=4
|
|
q_dbhost_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Hostname
|
|
E ) Environment Variable DB${detected_host_num}_HOST: '${detected_host_value}'
|
|
F ) Parsed Filename Host: '${p_dbhost}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What Hostname do you wish to restore to:
|
|
${q_dbhost_menu}
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbhost_variant}" in
|
|
1 )
|
|
counter=1
|
|
q_dbhost=" "
|
|
while [[ $q_dbhost = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Hostnames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Host do you want to restore to:\ ${coff})" q_dbhost
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbhost=${q_dbhost}
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E\*${cdgy}\) : ${cwh}${coff}) " q_dbhost_menu
|
|
case "${q_dbhost_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbhost=" "
|
|
while [[ $q_dbhost = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Hostnames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Host do you want to restore to:\ ${coff})" q_dbhost
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbhost=${q_dbhost}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbhost=${detected_host_value}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
3 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}F\*${cdgy}\) : ${cwh}${coff}) " q_dbhost_menu
|
|
case "${q_dbhost_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbhost=" "
|
|
while [[ $q_dbhost = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Hostnames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Host do you want to restore to:\ ${coff})" q_dbhost
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbhost=${q_dbhost}
|
|
break
|
|
;;
|
|
f* | "" )
|
|
r_dbhost=${p_dbhost}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
|
|
4 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E\*${cdgy}\) \| \(${cwh}F${cdgy}\) : ${cwh}${coff}) " q_dbhost_menu
|
|
case "${q_dbhost_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbhost=" "
|
|
while [[ $q_dbhost = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Hostnames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Host do you want to restore to:\ ${coff})" q_dbhost
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbhost=${q_dbhost}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbhost=${detected_host_value}
|
|
break
|
|
;;
|
|
f* )
|
|
r_dbhost=${p_dbhost}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_dbname() {
|
|
p_dbname=$(basename -- "${r_filename}" | cut -d _ -f 2)
|
|
|
|
if [ -n "${p_dbname}" ]; then
|
|
parsed_name=true
|
|
print_debug "Parsed DBName: ${p_dbname}"
|
|
fi
|
|
|
|
if grep -q "^DB${detected_host_num}_NAME=${p_dbname}" "${restore_vars}" ; then
|
|
detected_name_value=$(grep -q "^DB${detected_host_num}_NAME=${p_dbname}" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
|
|
if [ -z "${detected_name_value}" ] && [ -z "${parsed_name}" ]; then
|
|
print_debug "Parsed DBName Variant: 1 - No Env, No Parsed Filename"
|
|
q_dbname_variant=1
|
|
q_dbname_menu=$(cat <<EOF
|
|
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_name_value}" ] && [ -z "${parsed_name}" ]; then
|
|
print_debug "Parsed DBName Variant: 2 - Env, No Parsed Filename"
|
|
q_dbname_variant=2
|
|
q_dbname_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Name
|
|
E ) Environment Variable DB${detected_host_num}_NAME: '${detected_name_value}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -z "${detected_name_value}" ] && [ -n "${parsed_name}" ]; then
|
|
print_debug "Parsed DBName Variant: 3 - No Env, Parsed Filename"
|
|
q_dbname_variant=3
|
|
q_dbname_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Name
|
|
F ) Parsed Filename DB Name: '${p_dbname}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_name_value}" ] && [ -n "${parsed_name}" ]; then
|
|
print_debug "Parsed DBname Variant: 4 - Env, Parsed Filename"
|
|
q_dbname_variant=4
|
|
q_dbname_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Name
|
|
E ) Environment Variable DB${detected_host_num}_NAME: '${detected_name_value}'
|
|
F ) Parsed Filename DB Name: '${p_dbname}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What Database Name do you want to restore to?
|
|
${q_dbname_menu}
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbname_variant}" in
|
|
1 )
|
|
counter=1
|
|
q_dbname=" "
|
|
while [[ $q_dbname = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB names can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Name do you want to restore to:\ ${coff})" q_dbname
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbname=${q_dbname}
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E\*${cdgy}\) : ${cwh}${coff}) " q_dbname_menu
|
|
case "${q_dbname_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbname=" "
|
|
while [[ $q_dbname = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB Names can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB name do you want to restore to:\ ${coff})" q_dbname
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbname=${q_dbname}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbname=${detected_name_value}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
3 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}F\*${cdgy}\) : ${cwh}${coff}) " q_dbname_menu
|
|
case "${q_dbname_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbname=" "
|
|
while [[ $q_dbname = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB names can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB name do you want to restore to:\ ${coff})" q_dbname
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbname=${q_dbname}
|
|
break
|
|
;;
|
|
f* | "" )
|
|
r_dbname=${p_dbname}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
|
|
4 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E\*${cdgy}\) \| \(${cwh}F${cdgy}\) : ${cwh}${coff}) " q_dbname_menu
|
|
case "${q_dbname_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbname=" "
|
|
while [[ $q_dbname = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB names can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB name do you want to restore to:\ ${coff})" q_dbname
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbname=${q_dbname}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbname=${detected_name_value}
|
|
break
|
|
;;
|
|
f* )
|
|
r_dbname=${p_dbname}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_dbpass() {
|
|
if grep -q "^DB${detected_host_num}_PASS=" "${restore_vars}" ; then
|
|
detected_pass_value=$(grep "^DB${detected_host_num}_PASS=" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
|
|
if [ -z "${detected_pass_value}" ] ; then
|
|
print_debug "Parsed DBPass Variant: 1 - No Env"
|
|
q_dbpass_variant=1
|
|
q_dbpass_menu=$(cat <<EOF
|
|
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_pass_value}" ] ; then
|
|
print_debug "Parsed DBPass Variant: 2 - Env"
|
|
q_dbpass_variant=2
|
|
q_dbpass_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Password
|
|
E ) Environment Variable DB${detected_host_num}_PASS
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What Database Password will be used to restore?
|
|
${q_dbpass_menu}
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbpass_variant}" in
|
|
1 )
|
|
counter=1
|
|
q_dbpass=" "
|
|
while [[ $q_dbpass = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB Passwords can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Password do you wish to use:\ ${coff})" q_dbpass
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbpass=${q_dbpass}
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E\*${cdgy}\) : ${cwh}${coff}) " q_dbpass_menu
|
|
case "${q_dbpass_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbpass=" "
|
|
while [[ $q_dbpass = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB Passwords can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Password do you wish to use:\ ${coff})" q_dbpass
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbpass=${q_dbpass}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbpass=${detected_pass_value}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_dbport() {
|
|
if grep -q "^DB${detected_host_num}_PORT=" "${restore_vars}" ; then
|
|
detected_port_value=$(grep "^DB${detected_host_num}_PORT=" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
|
|
if [ -z "${detected_port_value}" ] ; then
|
|
print_debug "Parsed DBPort Variant: 1 - No Env"
|
|
q_dbport_variant=1
|
|
q_dbport_menu_opt_default="| (${cwh}D${cdgy}) * "
|
|
q_dbport_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Port
|
|
D ) Default Port for Database type '${r_dbtype}': '${DEFAULT_PORT}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_port_value}" ] ; then
|
|
print_debug "Parsed DBPort Variant: 2 - Env"
|
|
q_dbport_variant=2
|
|
q_dbport_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database Port
|
|
D ) Default Port for Database type '${r_dbtype}': '${DEFAULT_PORT}'
|
|
E ) Environment Variable DB${detected_host_num}_PORT: '${detected_port_value}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What Database Port do you wish to use? MySQL/MariaDB typcially listens on port 3306. Postrgresql port 5432. MongoDB 27017
|
|
${q_dbport_menu}
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbport_variant}" in
|
|
1 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}D\*${cdgy}\) : ${cwh}${coff}) " q_dbport_menu
|
|
case "${q_dbport_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbport=" "
|
|
q_dbportre='^[0-9]+$'
|
|
while ! [[ $q_dbport =~ ${q_dbportre} ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Must be a port number, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Port do you want to use:\ ${coff})" q_dbport
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbport=${q_dbport}
|
|
break
|
|
;;
|
|
d* | "" )
|
|
r_dbport=${DEFAULT_PORT}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}D${cdgy}\) \| \(${cwh}E\*${cdgy}\) : ${cwh}${coff}) " q_dbport_menu
|
|
case "${q_dbport_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbport=" "
|
|
q_dbportre='^[0-9]+$'
|
|
while ! [[ $q_dbport =~ ${q_dbportre} ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "Must be a port number, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB Port do you want to use:\ ${coff})" q_dbport
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbport=${q_dbport}
|
|
break
|
|
;;
|
|
d* )
|
|
r_dbport=${DEFAULT_PORT}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbport=${detected_port_value}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_dbtype() {
|
|
p_dbtype=$(basename -- "${r_filename}" | cut -d _ -f 1)
|
|
|
|
case "${p_dbtype}" in
|
|
mongo* )
|
|
parsed_type=true
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
print_debug "Parsed DBType: MongoDB"
|
|
;;
|
|
mariadb | mysql )
|
|
parsed_type=true
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
print_debug "Parsed DBType: MariaDB/MySQL"
|
|
;;
|
|
pgsql | postgres* )
|
|
parsed_type=true
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
print_debug "Parsed DBType: Postgresql"
|
|
;;
|
|
* )
|
|
print_debug "Parsed DBType: UNKNOWN"
|
|
;;
|
|
esac
|
|
|
|
if [ -z "${DB_TYPE}" ] && [ -z "${parsed_type}" ]; then
|
|
print_debug "Parsed DBType Variant: 1 - No Env, No Parsed Filename"
|
|
q_dbtype_variant=1
|
|
q_dbtype_menu=$(cat <<EOF
|
|
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${DB_TYPE}" ] && [ -z "${parsed_type}" ]; then
|
|
print_debug "Parsed DBType Variant: 2 - Env, No Parsed Filename"
|
|
q_dbtype_variant=2
|
|
q_dbtype_menu=$(cat <<EOF
|
|
|
|
E ) Environment Variable DB_TYPE: '${DB_TYPE}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -z "${DB_TYPE}" ] && [ -n "${parsed_type}" ]; then
|
|
print_debug "Parsed DBType Variant: 3 - No Env, Parsed Filename"
|
|
q_dbtype_variant=3
|
|
q_dbtype_menu=$(cat <<EOF
|
|
|
|
F ) Parsed Filename Type: '${p_dbtype}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${DB_TYPE}" ] && [ -n "${parsed_type}" ]; then
|
|
print_debug "Parsed DBType Variant: 4 - Env, Parsed Filename"
|
|
q_dbtype_variant=4
|
|
q_dbtype_menu=$(cat <<EOF
|
|
|
|
E ) Environment Variable DB_TYPE: '${DB_TYPE}'
|
|
F ) Parsed Filename Type: '${p_dbtype}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What Database Type are you looking to restore?
|
|
${q_dbtype_menu}
|
|
|
|
M ) MySQL / MariaDB
|
|
O ) MongoDB
|
|
P ) Postgresql
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbtype_variant}" in
|
|
1 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}M${cdgy}\) \| \(${cwh}O${cdgy}\) \| \(${cwh}P${cdgy}\) : ${cwh}${coff}) " q_dbtype
|
|
case "${q_dbtype,,}" in
|
|
m* )
|
|
r_dbtype=mysql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
break
|
|
;;
|
|
o* )
|
|
r_dbtype=mongo
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
break
|
|
;;
|
|
p* )
|
|
r_dbtype=postgresql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}E${cdgy}\) \| \(${cwh}M${cdgy}\) \| \(${cwh}O${cdgy}\) \| \(${cwh}P${cdgy}\) : ${cwh}${coff}) " q_dbtype
|
|
case "${q_dbtype,,}" in
|
|
e* | "" )
|
|
r_dbtype=${DB_TYPE}
|
|
break
|
|
;;
|
|
m* )
|
|
r_dbtype=mysql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
break
|
|
;;
|
|
o* )
|
|
r_dbtype=mongo
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
break
|
|
;;
|
|
p* )
|
|
r_dbtype=postgresql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
3 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}F${cdgy}\) \(Default\) \| \(${cwh}M${cdgy}\) \| \(${cwh}O${cdgy}\) \| \(${cwh}P${cdgy}\) : ${cwh}${coff}) " q_dbtype
|
|
case "${q_dbtype,,}" in
|
|
f* | "" )
|
|
r_dbtype=${p_dbtype}
|
|
case "${r_dbtype}" in
|
|
mongo )
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
;;
|
|
mysql )
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
;;
|
|
pgsql )
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
;;
|
|
esac
|
|
break
|
|
;;
|
|
m* )
|
|
r_dbtype=mysql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
break
|
|
;;
|
|
o* )
|
|
r_dbtype=mongo
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
break
|
|
;;
|
|
p* )
|
|
r_dbtype=postgresql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
|
|
4 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}E${cdgy}\) \| \(${cwh}F${cdgy}\) \| \(${cwh}M${cdgy}\) \| \(${cwh}O${cdgy}\) \| \(${cwh}P${cdgy}\) : ${cwh}${coff}) " q_dbtype
|
|
case "${q_dbtype,,}" in
|
|
e* | "" )
|
|
r_dbtype=${DB_TYPE}
|
|
break
|
|
;;
|
|
f* )
|
|
r_dbtype=${p_dbtype}
|
|
break
|
|
;;
|
|
m* )
|
|
r_dbtype=mysql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"3306"}
|
|
break
|
|
;;
|
|
o* )
|
|
r_dbtype=mongo
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"27017"}
|
|
break
|
|
;;
|
|
p* )
|
|
r_dbtype=postgresql
|
|
DEFAULT_PORT=${DEFAULT_PORT:-"5432"}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_dbuser() {
|
|
if grep -q "^DB${detected_host_num}_USER=" "${restore_vars}" ; then
|
|
detected_user_value=$(grep "^DB${detected_host_num}_USER=" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
|
|
if [ -z "${detected_user_value}" ] ; then
|
|
print_debug "Parsed DBUser Variant: 1 - No Env"
|
|
q_dbuser_variant=1
|
|
q_dbuser_menu=$(cat <<EOF
|
|
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
if [ -n "${detected_user_value}" ] ; then
|
|
print_debug "Parsed DBUser Variant: 2 - Env"
|
|
q_dbuser_variant=2
|
|
q_dbuser_menu=$(cat <<EOF
|
|
|
|
C ) Custom Entered Database User
|
|
E ) Environment Variable DB${detected_host_num}_USER: '${detected_user_value}'
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
cat << EOF
|
|
|
|
What database user will be used for restore:
|
|
${q_dbuser_menu}
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
case "${q_dbuser_variant}" in
|
|
1 )
|
|
counter=1
|
|
q_dbuser=" "
|
|
while [[ $q_dbuser = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB Usernames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB User do you wish to use:\ ${coff})" q_dbuser
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbuser=${q_dbuser}
|
|
;;
|
|
2 )
|
|
while true; do
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}C${cdgy}\) \| \(${cwh}E${cdgy}\) : ${cwh}${coff}) " q_dbuser_menu
|
|
case "${q_dbuser_menu,,}" in
|
|
c* )
|
|
counter=1
|
|
q_dbuser=" "
|
|
while [[ $q_dbuser = *" "* ]]; do
|
|
if [ $counter -gt 1 ] ; then print_error "DB Usernames can't have spaces in them, please re-enter." ; fi ;
|
|
read -e -p "$(echo -e ${clg}** ${cdgy}What DB User do you wish to use:\ ${coff})" q_dbuser
|
|
(( counter+=1 ))
|
|
done
|
|
r_dbuser=${q_dbuser}
|
|
break
|
|
;;
|
|
e* | "" )
|
|
r_dbuser=${detected_user_value}
|
|
break
|
|
;;
|
|
q* )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_filename() {
|
|
COLUMNS=12
|
|
prompt="Please select a file to restore:"
|
|
options=( $(find "${DEFAULT_FILESYSTEM_PATH}" -type f -maxdepth 2 -not -name '*.md5' -not -name '*.sha1' -not -name '*.gpg' -print0 | sort -z | xargs -0) )
|
|
PS3="$prompt "
|
|
select opt in "${options[@]}" "Custom" "Quit" ; do
|
|
if (( REPLY == 2 + ${#options[@]} )) ; then
|
|
echo "Bye!"
|
|
exit 2
|
|
elif (( REPLY == 1 + ${#options[@]} )) ; then
|
|
while [ ! -f "${opt}" ] ; do
|
|
read -p "What path and filename to restore: " opt
|
|
if [ ! -f "${opt}" ] ; then
|
|
print_error "File not found. Please retry.."
|
|
fi
|
|
done
|
|
break
|
|
elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
|
|
break
|
|
else
|
|
echo "Invalid option. Try another one."
|
|
fi
|
|
done
|
|
COLUMNS=$oldcolumns
|
|
r_filename=${opt}
|
|
}
|
|
|
|
get_ssl() {
|
|
if grep -q "^DB${detected_host_num}_MYSQL_ENABLE_TLS=" "${restore_vars}" ; then
|
|
detected_ssl_value=$(grep "^DB${detected_host_num}_MYSQL_ENABLE_TLS=" "${restore_vars}" | head -n1 | cut -d '=' -f 2)
|
|
fi
|
|
|
|
if [[ -z "${detected_ssl_value}" ]]; then
|
|
print_debug "Parsed SSL Variant: 1 - No Env Variable Found"
|
|
default_ssl="false" # Default if no env variable
|
|
q_ssl_variant=1
|
|
q_ssl_menu_opt_default="| (${cwh}N${cdgy}) * "
|
|
q_ssl_menu="" #No menu option
|
|
else
|
|
print_debug "Parsed SSL Variant: 2 - Env Variable DB${detected_host_num}_MYSQL_ENABLE_TLS = '${detected_ssl_value}'"
|
|
default_ssl="${detected_ssl_value,,}"
|
|
q_ssl_variant=2
|
|
q_ssl_menu="E ) Environment Variable DB${detected_host_num}_MYSQL_ENABLE_TLS: '${detected_ssl_value}'"
|
|
q_ssl_menu_opt_default="| (${cwh}E${cdgy}) * "
|
|
fi
|
|
|
|
cat <<EOF
|
|
|
|
Do you wish to use SSL for the connection?
|
|
${q_ssl_menu}
|
|
|
|
Y ) Yes
|
|
N ) No
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
r_ssl=""
|
|
case "${q_ssl_variant}" in
|
|
1) # No env variable, ask directly
|
|
while true; do
|
|
read -r -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}Y${cdgy}\) \| \(${cwh}N\*${cdgy}\) : ${cwh}${coff}) " q_ssl
|
|
case "${q_ssl,,}" in
|
|
y*)
|
|
r_ssl="true"
|
|
break
|
|
;;
|
|
n* | "")
|
|
r_ssl="false"
|
|
break
|
|
;;
|
|
q*)
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
2) # Env variable exists, offer it as an option
|
|
while true; do
|
|
read -r -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}E\*${cdgy}\) \| \(${cwh}Y${cdgy}\) \| \(${cwh}N${cdgy}\) : ${cwh}${coff}) " q_ssl
|
|
case "${q_ssl,,}" in
|
|
e* | "") # Default to env variable if just enter is pressed.
|
|
r_ssl="${detected_ssl_value}"
|
|
break
|
|
;;
|
|
y*)
|
|
r_ssl="true"
|
|
break
|
|
;;
|
|
n*)
|
|
r_ssl="false"
|
|
break
|
|
;;
|
|
q*)
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#### SCRIPT START
|
|
trap control_c INT
|
|
bootstrap_variables restore_init
|
|
|
|
cat << EOF
|
|
|
|
## ${IMAGE_NAME} Restore Script
|
|
## Visit ${IMAGE_REPO_URL}
|
|
## ####################################################
|
|
|
|
EOF
|
|
## Question Filename
|
|
if [ -n "${1}" ]; then
|
|
if [ ! -f "${1}" ]; then
|
|
get_filename
|
|
else
|
|
r_filename="${1}"
|
|
fi
|
|
else
|
|
get_filename
|
|
fi
|
|
|
|
print_debug "Filename to recover '${r_filename}'"
|
|
|
|
## Question Database Type
|
|
if [ -n "${2}" ]; then
|
|
r_dbtype="${2}"
|
|
else
|
|
get_dbtype
|
|
fi
|
|
print_debug "Database type '${r_dbtype}'"
|
|
|
|
## Question Database Host
|
|
if [ -n "${3}" ]; then
|
|
r_dbhost="${3}"
|
|
else
|
|
get_dbhost
|
|
fi
|
|
print_debug "Database Host '${r_dbhost}'"
|
|
|
|
## Question Database Name
|
|
if [ -n "${4}" ]; then
|
|
r_dbname="${4}"
|
|
else
|
|
get_dbname
|
|
fi
|
|
print_debug "Database Name '${r_dbname}'"
|
|
|
|
## Question Database User
|
|
if [ -n "${5}" ]; then
|
|
r_dbuser="${5}"
|
|
else
|
|
get_dbuser
|
|
fi
|
|
print_debug "Database User '${r_dbuser}'"
|
|
|
|
## Question Database Password
|
|
if [ -n "${6}" ]; then
|
|
r_dbpass="${6}"
|
|
else
|
|
get_dbpass
|
|
fi
|
|
print_debug "Database Pass '${r_dbpass}'"
|
|
|
|
## Question Database Port
|
|
if [ -n "${7}" ]; then
|
|
r_dbport="${7}"
|
|
else
|
|
get_dbport
|
|
fi
|
|
print_debug "Database Port '${r_dbport}'"
|
|
|
|
## Question SSL connection
|
|
if [[ "${r_dbtype,,}" == "mariadb" || "${r_dbtype,,}" == "mysql" ]]; then
|
|
if [ -n "${8}" ]; then
|
|
r_ssl="${8}"
|
|
else
|
|
get_ssl
|
|
fi
|
|
print_debug "SSL enable: '${r_ssl}'"
|
|
else
|
|
r_ssl="false"
|
|
print_debug "SSL disabled for ${r_dbtype}"
|
|
fi
|
|
|
|
|
|
## Parse Extension
|
|
case "${r_filename##*.}" in
|
|
bz* )
|
|
decompress_cmd='bz'
|
|
print_debug "Detected 'bzip2' compression"
|
|
;;
|
|
gz* )
|
|
decompress_cmd="z"
|
|
print_debug "Detected 'gzip' compression"
|
|
;;
|
|
xz* )
|
|
decompress_cmd="xz"
|
|
print_debug "Detected 'xzip' compression"
|
|
;;
|
|
zst* )
|
|
decompress_cmd='zstd'
|
|
print_debug "Detected 'zstd' compression"
|
|
;;
|
|
sql )
|
|
print_debug "Detected No compression"
|
|
;;
|
|
* )
|
|
print_debug "Cannot tell what the extension is for compression"
|
|
;;
|
|
esac
|
|
|
|
## Perform a restore
|
|
case "${r_dbtype}" in
|
|
mariadb | mysql )
|
|
if [[ "${r_ssl,,}" == "false" ]]; then
|
|
mysql_ssl_option="--disable-ssl"
|
|
else
|
|
mysql_ssl_option=""
|
|
fi
|
|
print_info "Restoring '${r_filename}' into '${r_dbhost}'/'${r_dbname}'"
|
|
pv ${r_filename} | ${decompress_cmd}cat | mariadb -u${r_dbuser} -p${r_dbpass} -P${r_dbport} -h${r_dbhost} ${mysql_ssl_option} ${r_dbname}
|
|
exit_code=$?
|
|
;;
|
|
pgsql | postgres* )
|
|
print_info "Restoring '${r_filename}' into '${r_dbhost}'/'${r_dbname}'"
|
|
export PGPASSWORD=${r_dbpass}
|
|
pv ${r_filename} | ${decompress_cmd}cat | psql -d ${r_dbname} -h ${r_dbhost} -p ${r_dbport} -U ${r_dbuser}
|
|
exit_code=$?
|
|
;;
|
|
mongo )
|
|
cat << EOF
|
|
|
|
Do you wish to drop any existing data before restoring?
|
|
Y ) Yes
|
|
N ) No
|
|
Q ) Quit
|
|
|
|
EOF
|
|
|
|
echo -e "${coff}"
|
|
read -p "$(echo -e ${clg}** ${cdgy}Enter Value \(${cwh}Y${cdgy}\) \| \(${cwh}N${cdgy}\) \| \(${cwh}Q${cdgy}\) : ${cwh}${coff})" q_menu_mongo_dropdb
|
|
case "${q_menu_mongo_dropdb,,}" in
|
|
"n" | "update" )
|
|
unset mongo_dropdb
|
|
;;
|
|
"q" | "exit" )
|
|
print_info "Quitting Script"
|
|
exit 1
|
|
;;
|
|
"y" | "yes" | * )
|
|
mongo_dropdb="--drop"
|
|
;;
|
|
esac
|
|
|
|
print_info "Restoring '${r_filename}' into '${r_dbhost}'/'${r_dbname}'"
|
|
if [ "${ENABLE_COMPRESSION,,}" != "none" ] && [ "${ENABLE_COMPRESSION,,}" != "false" ] ; then
|
|
mongo_compression="--gzip"
|
|
fi
|
|
if [ -n "${r_dbuser}" ] ; then
|
|
mongo_user="-u=${r_dbuser}"
|
|
fi
|
|
if [ -n "${r_dbpass}" ] ; then
|
|
mongo_pass="-p=${r_dbpass}"
|
|
fi
|
|
if [ -n "${DB_AUTH}" ] ; then
|
|
mongo_auth_database="--authenticationDatabase=${DB_AUTH}"
|
|
fi
|
|
|
|
mongorestore ${mongo_compression} -d=${r_dbname} -h=${r_dbhost} --port=${r_dbport} ${mongo_dropdb} ${mongo_user} ${mongo_pass} --archive=${r_filename} ${mongo_auth_database}
|
|
exit_code=$?
|
|
;;
|
|
* )
|
|
print_info "Unable to restore DB of type '${r_dbtype}'"
|
|
exit_code=3
|
|
;;
|
|
esac
|
|
|
|
print_debug "Exit code: ${exit_code}"
|
|
if [ "${exit_code}" = 0 ] ; then
|
|
print_info "Restore complete!"
|
|
else
|
|
print_error "Restore reported errors"
|
|
fi
|