From 1b9851cb636865054db3c5c7ffd1756e47b1857d Mon Sep 17 00:00:00 2001 From: gyurix Date: Thu, 28 Aug 2025 13:27:09 +0200 Subject: [PATCH] Add backup script for database services with Kubernetes and Docker support --- backup.sh | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 backup.sh diff --git a/backup.sh b/backup.sh new file mode 100644 index 0000000..81586ad --- /dev/null +++ b/backup.sh @@ -0,0 +1,153 @@ +#!/bin/sh + +BACKUP=$BACKUP; +BACKUP_LOG=$BACKUP_LOG; +SERVICE_FILES_DIRECTORIES=$SERVICE_FILES_DIRECTORIES; +SECRET_DIRECTORY=$SECRET_DIRECTORY; + +BACKUP_PERIOD=$BACKUP_PERIOD; + +if [ "$SECRET_DIRECTORY" == "" ]; then + SECRET_DIRECTORY=$SERVICE_FILES_DIRECTORIES; +else + SECRET_DIRECTORY=""; +fi + + +mkdir -p $BACKUP_LOG; + +# Kubernetes elements +KUBERNETES=$KUBERNETES + +db_backup() { + + if [ "$BACKUP_PERIOD" == "infinite" ]; then + DATE=$(date +"%Y-%m-%d_%H_%M"); + else + DATE=$(date +%w); + fi + + DBTYPE=""; + + if [ "$KUBERNETES" == "true" ]; then + + if [ "$(echo $ROLE | grep -o 'postgres-db')" != "" ] ; then + + # Define database pod name + CONTAINER_NAME=$(echo $CONTAINER_NAME | sed s/_/-/g); + CONTAINER_NAME=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" -n $NAMESPACE | grep $CONTAINER_NAME |grep '\-0'); + + if [ "$USER" == "" ]; then + USER=postgres + fi + + kubectl exec $CONTAINER_NAME -n $NAMESPACE -- pg_dumpall -U "$USER" > $BACKUPS/$CONTAINER_NAME'_'$DATE.sql ; + gzip $BACKUPS/$CONTAINER_NAME'_'$DATE.sql; + echo `date` "$CONTAINER_NAME service $BACKUPS/$CONTAINER_NAME.$DATE.sql.gz backup created" >> $BACKUPS_LOG/$DATE.txt; + + elif [ "$(echo $ROLE | grep -o 'mysql-db')" != "" ] ; then + + # Define database pod name + CONTAINER_NAME=$(echo $CONTAINER_NAME | sed s/_/-/g); + CONTAINER_NAME=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" -n $NAMESPACE | grep $CONTAINER_NAME |grep '\-0'); + + kubectl exec $CONTAINER_NAME -n $NAMESPACE -- sh -c "mysqldump -uroot -p'$PASSWD' --all-databases" > $BACKUPS/$CONTAINER_NAME'_'$DATE.sql ; + echo `date` "$CONTAINER_NAME service $BACKUPS/$CONTAINER_NAME.$DATE.sql backup created" >> $BACKUPS_LOG/$DATE.txt; + + #else + #CONTAINER_NAME=$(echo $CONTAINER_NAME | sed s/_/-/g); + #CONTAINER_NAME=$CONTAINER_NAME"-pp-0"; + + #kubectl exec $CONTAINER_NAME -n $NAMESPACE -- bash -c 'pg_dumpall -U postgres' | gzip > $BACKUPS/$CONTAINER_NAME'_'$DATE.sql.gz ; + #echo `date` "$CONTAINER_NAME service $BACKUPS/$CONTAINER_NAME.$DATE.sql.gz backup created" >> $BACKUPS_LOG/$DATE.txt; + fi + + else + + if [ "$(echo $ROLE | grep 'mysql-db')" != "" ] ; then + docker exec $CONTAINER_NAME mysqldump -u root -p$PASSWD --all-databases | cat > $BACKUPS/$CONTAINER_NAME.$DATE.sql ; + echo `date` "$CONTAINER_NAME service $BACKUPS/$CONTAINER_NAME.$DATE.sql backup created" >> $BACKUPS_LOG/$DATE.txt; + elif [ "$(echo $ROLE | grep 'postgres-db')" != "" ] ; then + docker exec $CONTAINER_NAME pg_dumpall -U $USER | gzip > $BACKUPS/$CONTAINER_NAME.$DATE.sql.gz ; + echo `date` "$CONTAINER_NAME service $BACKUPS/$CONTAINER_NAME.$DATE.sql.gz backup created" >> $BACKUPS_LOG/$DATE.txt; + else + echo `date` "$CONTAINER_NAME service: unknown database type in ROLES field: $ROLE" >> $BACKUPS_LOG/$DATE.txt; + fi + fi +} + +DIR=$SERVICE_FILES_DIRECTORIES; + +if [ "$DIR" == "" ]; then + + if [ "$COMMUNITY_URL" == "" ]; then + echo "No COMMUNITY URL added, exiting backup"; + exit; + fi + + FILES=$(find $COMMUNITY_URL -name 'service-*.json' -exec grep -l 'ROLES' {} \;) ; +else + FILES=$(grep -rl 'ROLES' $DIR/*.json); +fi + + +for F in `echo $FILES`; do + FILE=$(grep -l '\-db' $F) + if [ "$FILE" != "" ]; then + echo $FILE; + + if [ "$BACKUP" == "" ]; then + + ID=$(echo $F | sed s#$COMMUNITY_URL##g | cut -d '/' -f2); + BACKUPS="$COMMUNITY_URL/$ID/backups"; + mkdir -p $BACKUPS + + BACKUPS_LOG="$COMMUNITY_URL/$ID/backups"; + else + BACKUPS=$BACKUP + BACKUPS_LOG=$BACKUP_LOG + fi + + if [ "$KUBERNETES" == "true" ]; then + NAMESPACE=$(jq -r .main.SERVICE_NAME $FILE); + fi + + ROLES=$(jq -r .containers[].ROLES $FILE | grep -oE 'mysql-db|postgres-db'); + for ROLE in `echo $ROLES`; do + CONTAINER=$(jq -r --arg ROLE "$ROLE" '.containers[] | select(.ROLES | contains($ROLE))' $FILE) + CONTAINER_NAME=$(echo $CONTAINER | jq -r .NAME); + echo "CONTAINER NAME: "$CONTAINER_NAME; + + ENV_FILES=$(echo $CONTAINER | jq -r '.ENV_FILES | join(" ")'); + USER=$(echo $CONTAINER |jq -r '.ENVS[].POSTGRES_USER | select(.!=null)'); + + if [[ "$USER" != "" && "$USER" != "null" ]]; then + db_backup; + + elif [ -n "$ENV_FILES" ]; then + for ENV_FILE in `echo $ENV_FILES`; do + if [ -f "$SECRET_DIRECTORY/$ENV_FILE" ]; then + SERVICE_NAME=$(echo $CONTAINER_NAME | cut -d '-' -f1); + SECRET=$(jq -r .$SERVICE_NAME $SECRET_DIRECTORY/$ENV_FILE); + + if [ "$SECRET" != "null" ]; then + if [ "$(echo $ROLE | grep 'mysql-db')" != "" ] ; then + PASSWD=$(jq -r .$SERVICE_NAME.MYSQL_ROOT_PASSWORD $SECRET_DIRECTORY/$ENV_FILE); + elif [ "$(echo $ROLE | grep 'postgres-db')" != "" ] ; then + USER=""; + USER=$(jq -r .$SERVICE_NAME.POSTGRES_USER $SECRET_DIRECTORY/$ENV_FILE ); + fi + db_backup; + else + echo "SERVICE NOT FOUND IN SECRET FILE: $SERVICE_NAME"; + fi; + else + echo "FILE NOT FOUND: $ENV_FILE"; + fi; + done; + else + echo "Neither $ENV_FILE nor ENVS values found, exiting"; + fi + done; + fi; +done;