Commit acaab61a authored by Huihui, Jonathan's avatar Huihui, Jonathan
Browse files

Merge branch 'feature/pull_bologna_update' into 'develop'

Feature/pull bologna update

See merge request nset-utilities/common-package!19
parents 92cb08d0 bc93c9f0
Loading
Loading
Loading
Loading

src/scripts/transfer

0 → 100755
+510 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash
RED=$'\e\033[0;31m'
GREEN=$'\e\033[0;32m'
YELLOW=$'\e\033[1;33m'
ORANGE=$'\e\033[0;33m'
NORM=$'\e\033[0m'
BLUE=$'\e[6;34;40m'
PUSH=0 # specify if we are pushing data or pulling data
TABLE=0 # specify if we are transfering a table or a database
RESERVED_WORDS=("push" "pull" "table" "database")
SERVER_NAME=""
SERVER_IP=""
SERVER_PORT=""
SERVER_DB_NAME=""
SERVER_USER=""
SERVER_PASS=""
SOURCE_NAME=""
CONN_FILE="./.connections"

warn()
{
    printf "%sWARNING:%s %s\n" "$ORANGE" "$NORM" "$1"
}

info()
{
    printf "%sINFO:%s %s\n" "$BLUE" "$NORM" "$1"
}

banner()
{
    echo "
    ${ORANGE}     .^!77???77!~^::.                                                          
        :7??????????????77!!~^^^:..                                                
        77777????????????????${YELLOW}YPPPP5YYJ?${ORANGE}7!^:::.........          .......            
        !!!!77777????????????${YELLOW}PPPPP555YPPJ${ORANGE}?????7777?!:.......~!:....:::~?!:         
        .~!!!!!!!777777?????${YELLOW}YPJJJY5YPJJY7${ORANGE}???????7?!         ~.        !!           
         .^~!!!!!!!!!!777777Y5?${YELLOW}P5PGPBYYY${ORANGE}?????????7.        ^.        ^!   .        
            .^~~!!!!!!!!!!!!?5?${YELLOW}555JJYJ5J7${ORANGE}????????!        :7.       .?~   .        
                ..:^~~~~~~~~!${YELLOW}Y5Y55PPPPPJ${ORANGE}!!!!!!!!!!!~~~~~~~!7!~~~~~~~!7!!!~:!!~~~^  
              ${YELLOW}:~7?JYY555YYYJJYGGPPPPPPPY!!!!!!!!!!777777777777777777!!!!!!!!!!!^.  
             ?GGGGGGGGGGGGGGGGGGGGGGGGGGGGGP5PGGGGGGGGGGGGGGGGGGGGGGPPP55YYJ?~:    
             YPP5555555555PPPPPPPPPPPPP5PP5?75PPPPPPPPPPPPPPGGGGGGGGGGGGGBBBBGP5?~ 
             .!?JJY5555555YY555555555555555PP555555555555555555555555PPPPPP555PPPGY
                  .:^~!?!:.77!!??!Y5YJ??777777????JJJJYYYYY5555Y77J777Y7!J5555555J~
                           ${NORM}~7!!7^ ^~:                  ....:::^. .7!~!7: .!!!!~^:  
                            :::.                                  .^^^.            "
    echo "$ORANGE"
    printf "                       ___                       __  __\n"
    printf "                      / _ \\ ___  ___ __ _ _ __  |  \\/  | __ _ _   _  ___ _ __\n"
    printf "                     | | | / __|/ __/ _\` | '__| | |\\/| |/ _\` | | | |/ _ \\ '__|\n"
    printf "                     | |_| \__ \ (_| (_| | |    | |  | | (_| | |_| |  __/ |\n"
    printf "                      \\___/|___/\\___\\__,_|_|    |_|  |_|\\__,_|\\__, |\\___|_|\n"
    printf "                                                              |___/\n"
    printf "                        My Bologna has a first name, it's O-S-C-A-R."
    echo "$NORM"
}


usage()
{
    printf "%susage:%s" "$RED" "$NORM"
    printf "./transfer [push | pull] <connection name> [table | database] <table/db name>\n\n"
    printf "./transfer list connections\n\tShows a list of save connections.\n\n"
    printf "Print this help message.\n"
    printf " --help | -h)\n\n"
}

list_conns()
{
    # Structure: IP_ADDRESS:PORT:DB_NAME:USERNAME:PASSWORD
    conns=$(cat "$CONN_FILE" | xargs)

    while read conn; do
        name=$(echo "$conn" | cut -d' ' -f1)
        cinfo=$(echo "$conn" | cut -d' ' -f2)
        ip=$(echo "$cinfo" | cut -d':' -f1)
        port=$(echo "$cinfo" | cut -d':' -f2)
        db=$(echo "$cinfo" | cut -d':' -f3)
        user=$(echo "$cinfo" | cut -d':' -f4)
        pass=$(echo "$cinfo" | cut -d':' -f5)

        printf "%s%s%s:\n" "$GREEN" "$name" "$NORM"
        printf "\tIP Address:    %s\n" "$ip"
        printf "\tPort Number:   %s\n" "$port"
        printf "\tDatabase Name: %s\n" "$db"
        printf "\tUser Name:     %s\n" "$user"
        printf "\tPassword:      %s\n\n" "$pass"
    done < "$CONN_FILE"
}

create_source()
{
    # Structure: IP_ADDRESS:PORT:DB_NAME:USERNAME:PASSWORD
    # Name the source
    printf "Would you like to create server connection with name: '%s%s%s'?" "$GREEN" "$SERVER_NAME" "$NORM"
    read -rp "(y/n) " input
    if [ "$input" == "y" ]; then
        confirmed=0
        # Get the server ip address
        while [ "$confirmed" == 0 ]
        do
            read -rp "Enter the server's IP Address: " SERVER_IP
            read -rp "Is '$GREEN$SERVER_IP$NORM' correct? (y/n) " input
            if [ "$input" == y ]; then
                confirmed=1
            fi
        done

        # Get the server's port number
        confirmed=0
        while [ "$confirmed" == 0 ]
        do
            read -rp "Enter the server's Port number: " SERVER_PORT
            read -rp "Is '$GREEN$SERVER_PORT$NORM' correct? (y/n) " input
            if [ "$input" == y ]; then
                confirmed=1
            fi
        done

        # Check if the user supplied the correct db name
        if [ "$TABLE" == 0 ]; then # if the user supplied a db name

            read -rp "Would you like to continue using database name '$GREEN$SOURCE_NAME$NORM'?(y/n) " input
            if [ "$input" == "y" ]; then
                SERVER_DB_NAME=$SOURCE_NAME
            else
                # Get the DB name from the user
                confirmed=0
                while [ "$confirmed" == 0 ]
                do
                    read -rp "Enter the server's database name: " SERVER_DB_NAME
                    read -rp "Is '$GREEN$SERVER_DB_NAME$NORM' correct? (y/n) " input
                    if [ "$input" == y ]; then
                        confirmed=1
                    fi
                done
            fi

        else # if the user did not supply a DB name
            # Get the DB name from the user
            confirmed=0
            while [ "$confirmed" == 0 ]
            do
                read -rp "Enter the server's database name: " SERVER_DB_NAME
                read -rp "Is '$GREEN$SERVER_DB_NAME$NORM' correct? (y/n) " input
                if [ "$input" == y ]; then
                    confirmed=1
                fi
            done
        fi

        # Get the server username
        confirmed=0
        while [ "$confirmed" == 0 ]
        do
            read -rp "Enter the username for the server: " SERVER_USER
            read -rp "Is '$GREEN$SERVER_USER$NORM' correct? (y/n) " input
            if [ "$input" == y ]; then
                confirmed=1
            fi
        done

        # Get the server password
        confirmed=0
        while [ "$confirmed" == 0 ]
        do
            read -rp "Enter the password for the server: " SERVER_PASS
            read -rp "Is '$GREEN$SERVER_PASS$NORM' correct? (y/n) " input
            if [ "$input" == y ]; then
                confirmed=1
            fi
        done

        # Confirm the user's input
        # Structure: IP_ADDRESS:PORT:DB_NAME:USERNAME:PASSWORD
        confirmed=0
        while [ "$confirmed" == 0 ]
        do
            printf "Does the following information look correct:\n"
            printf "Server IP address:  %s'%s'%s\n" "$GREEN" "$SERVER_IP" "$NORM"
            printf "Server Port number: %s'%s'%s\n" "$GREEN" "$SERVER_PORT" "$NORM"
            printf "Database Name:      %s'%s'%s\n" "$GREEN" "$SERVER_DB_NAME" "$NORM"
            printf "Database User:      %s'%s'%s\n" "$GREEN" "$SERVER_USER" "$NORM"
            printf "Database Password:  %s'%s'%s\n" "$GREEN" "$SERVER_PASS" "$NORM"
            read -rp "(y/n) " input
            if [ "$input" == y ]; then
                confirmed=1
                # Append the server info to the connection file
                echo "$SERVER_NAME $SERVER_IP:$SERVER_PORT:$SERVER_DB_NAME:$SERVER_USER:$SERVER_PASS" >> $CONN_FILE
            else
                # send them back to the beginning, we tried
                create_source
            fi
        done

    else
        exit 0
    fi
}

extract_conn()
{
    # Expects SERVER_NAME to be set...
    if grep -q "$SERVER_NAME" "$CONN_FILE"; then
        if [ "$(grep -c "$SERVER_NAME" "$CONN_FILE")" == 1 ]; then
            conn=$(grep "$SERVER_NAME" "$CONN_FILE" | cut -d' ' -f2)
            # Structure: IP_ADDRESS:PORT:DB_NAME:USERNAME:PASSWORD
            SERVER_IP=$(echo "$conn" | cut -d':' -f1)
            if [ "$SERVER_IP" == "localhost" ] || [ "$SERVER_IP" == "127.0.0.1" ] || [ "$SERVER_IP" == "0.0.0.0" ]; then
                SERVER_IP="host.docker.internal"
            fi
            SERVER_PORT=$(echo "$conn" | cut -d':' -f2)
            SERVER_DB_NAME=$(echo "$conn" | cut -d':' -f3)
            SERVER_USER=$(echo "$conn" | cut -d':' -f4)
            SERVER_PASS=$(echo "$conn" | cut -d':' -f5)
        else
            warn "Found too many matches for '$SERVER_NAME' in connection file. Refine name and try again.."
            exit 2
        fi
    fi
}

verify_source()
{
    if test -f "$CONN_FILE"; then
        info "Connection file found!"
    else
        if touch "$CONN_FILE"; then
            info "Connection file created!"
            create_source
        else
            warn "Failed to create connection file. Check permissions. Exiting with code $?"
            exit $?
        fi
    fi

    info "Searching connection file for '$SERVER_NAME'"
    if grep -q "$SERVER_NAME" "$CONN_FILE"; then
        extract_conn
        info "Source '$SERVER_NAME' successfully identified."
        printf "Would you like to proceed with with the following information:\n"
        printf "Server IP address:  '%s%s%s'" "$GREEN" "$SERVER_IP" "$NORM"
        if [ "$SERVER_IP" == "host.docker.internal" ]; then
            printf " %s(Please note, this script uses docker! host.docker.internal is in reference to your machine.)%s\n" "$RED" "$NORM"
        else
            printf "\n"
        fi
        printf "Server Port number: '%s%s%s'\n" "$GREEN" "$SERVER_PORT" "$NORM"
        printf "Database Name:      '%s%s%s'\n" "$GREEN" "$SERVER_DB_NAME" "$NORM"
        printf "Database User:      '%s%s%s'\n" "$GREEN" "$SERVER_USER" "$NORM"
        printf "Database Password:  '%s%s%s'\n" "$GREEN" "$SERVER_PASS" "$NORM"
        read -rp "(y/n) " input
        if [ "$input" == y ]; then
            confirmed=1
        else
            warn "If the server information is incorrect, you can edit it in the following file: '$CONN_FILE'."
            warn "Exiting.."
            exit 0
        fi
    else
        warn "Failed to find source: '$SERVER_NAME'"
        create_source
        verify_source
    fi
}

parse_args()
{
    ARGS=()
    while test $# -gt 0
    do
        case "$1" in
            --help | -h)
                usage
                exit 0
                ;;

            push | pull)
                if [ "$1" == 'push' ]; then
                    PUSH=1
                else
                    PUSH=0
                fi
                shift 1

                # Check for server name (if next arg is a reserved word)
                if [[ " ${RESERVED_WORDS[*]} " =~ $1  ]] || [ "$#" == 0 ]; then
                    if [ "$PUSH" == 1 ]; then
                        warn "Failed to supply server name after keyword 'push'"
                    else
                        warn "Failed to supply server name after keyword 'pull'"
                    fi
                    exit 1
                else
                    SERVER_NAME="$1"
                fi
                shift 1
                ;;

            table | database)
                if [ "$1" == 'table' ]; then
                    TABLE=1
                else
                    TABLE=0
                fi

                shift 1 # we extracted the arg..

                # Check for source name (if next arg is a reserved word
                if [[ " ${RESERVED_WORDS[*]} " =~ $1  ]] || [ "$#" == 0 ]; then
                    if [ "$TABLE" == 1 ]; then
                        warn "Failed to supply table name after keyword 'table'"
                    else
                        warn "Failed to supply database name after keyword 'database'"
                    fi
                    exit 1
                else
                    SOURCE_NAME="$1"
                fi
                shift 1
                ;;

            connections)
                list_conns
                exit 0
                ;;

            *)
                warn "Unknown argument '$RED$1$NORM' exiting."
                exit 1
                ;;
        esac
    done
    go
}

go()
{
    # Verify source
    verify_source "$SERVER_NAME"
    # Determine if we are living in a docker container or if we are on hardware..
    #!/bin/bash
    if [ ! -f /.dockerenv ]; then
        DOCKER=0
        info "Detected non-docker run."
    else
        DOCKER=1
        info "Detected docker-based run."
    fi
    # Verify we have everything we need to move forward
    if [ "$SERVER_NAME" == "" ]; then
        warn "Failed to supply server name!"
        exit 1
    elif [ "$SOURCE_NAME" == "" ]; then
        if [ "$TABLE" == 1 ]; then
            warn "Failed to supply table name!"
        else
            warn "Failed to supply database name!"
        fi
        exit 1
    fi


    # Tell the user what we are going to do..
    MSG="Preparing to"
    if [ "$PUSH" == 1 ]; then
        if [ "$TABLE" == 1 ]; then
            MSG="$MSG push table '$SOURCE_NAME' to $SERVER_NAME."
        else
            MSG="$MSG push database '$SOURCE_NAME' to $SERVER_NAME."
        fi
    else
        if [ "$TABLE" == 1 ]; then
            MSG="$MSG pull table '$SOURCE_NAME' from $SERVER_NAME."
        else
            MSG="$MSG pull database '$SOURCE_NAME' from $SERVER_NAME."
        fi
    fi
    info "$MSG"

    # psql -h "$DST_HOST" -p "$DST_PORT"\
    # -U "$DST_USR" -d "$DST_DB" -f "$SRC_TABLE".sql

    if [ "$PUSH" == 0 ]  && [ "$TABLE" == 1 ]; then # if we are pulling a table
        echo "pg_dump --host $SERVER_IP --port $SERVER_PORT -U $SERVER_USER -d $SERVER_DB_NAME --verbose --table $SOURCE_NAME -Fp > $SOURCE_NAME.sql"

        if [ "$DOCKER" == 0 ]; then # If we aren't in a docker container
            docker run -i -e PGPASSWORD="$SERVER_PASS" postgres:alpine \
                pg_dump --host "$SERVER_IP" --port "$SERVER_PORT" -U "$SERVER_USER" -d "$SERVER_DB_NAME"\
                --verbose --table "$SOURCE_NAME" -Fp > "$SOURCE_NAME".sql
        else # If we are in a docker container
            export PGPASSWORD="$SERVER_PASS"
            pg_dump --host "$SERVER_IP" --port "$SERVER_PORT"\
                -U "$SERVER_USER" -d "$SERVER_DB_NAME"\
                --verbose --table "$SOURCE_NAME" -Fp > "$SOURCE_NAME".sql
        fi

        if [ "$?" == 0 ]; then
            info "Successfully retrieved table dump for '$GREEN$SOURCE_NAME$NORM'"
        else
            warn "Failed to retrieve table dump for '$RED$SOURCE_NAME$NORM'"
            rm "$SOURCE_NAME".sql
        fi
    fi


    if [ "$PUSH" == 0 ]  && [ "$TABLE" == 0 ]; then # if we are pulling a database
        echo "pg_dump --create --host $SERVER_IP --port $SERVER_PORT -U $SERVER_USER -d $SOURCE_NAME --verbose --format=custom > $SOURCE_NAME$(date +%F).backup"

        if [ "$DOCKER" == 0 ]; then # If we aren't in a docker container
            docker run -i -e PGPASSWORD="$SERVER_PASS" postgres:alpine \
                pg_dump --create --host "$SERVER_IP" --port "$SERVER_PORT" -U "$SERVER_USER" -d "$SOURCE_NAME"\
                --verbose --format=custom > "$SOURCE_NAME"_"$(date +%F)".backup
        else
            export PGPASSWORD="$SERVER_PASS"
            pg_dump --create --host "$SERVER_IP" --port \
                "$SERVER_PORT" -U "$SERVER_USER" -d "$SOURCE_NAME"\
                --verbose --format=custom > "$SOURCE_NAME"_"$(date +%F)".backup
        fi

        if [ "$?" == 0 ]; then
            info "Successfully retrieved database dump for '$GREEN$SOURCE_NAME$NORM'"
        else
            warn "Failed to retrieve database dump for '$RED$SOURCE_NAME$NORM'"
            rm "$SOURCE_NAME$(date +%F)".backup
        fi
    fi


    if [ "$PUSH" == 1 ]  && [ "$TABLE" == 0 ]; then # if we are pushing a database

        # Ensure we are using the correct file...
        file=$(ls -la ./"$SOURCE_NAME"*.*)
        printf "Would you continue the database restoration with the following file:\n%s%s%s\n" "$GREEN" "$file" "$NORM"
        read -rp "(y/n) " input
        if [ "$input" != "y" ]; then
            exit 0
        fi

        file=$(ls ./"$SOURCE_NAME"*.*)

        echo "pg_restore --create --host $SERVER_IP --port $SERVER_PORT -U $SERVER_USER -d $SERVER_DB_NAME --verbose --clean --if-exists $file"
        if [ "$DOCKER" == 0 ]; then # If we aren't in a docker container
            docker run -i -e PGPASSWORD="$SERVER_PASS" --mount type=bind,source="$(pwd)"/"$file",target=/"$file" postgres:alpine \
                pg_restore --create --host $SERVER_IP --port "$SERVER_PORT" -U "$SERVER_USER" -d "$SERVER_DB_NAME"\
                --verbose --clean --if-exists "$file"
        else
            export PGPASSWORD="$SERVER_PASS"
            pg_restore --create --host $SERVER_IP --port \
                "$SERVER_PORT" -U "$SERVER_USER" -d "$SERVER_DB_NAME"\
                --verbose --clean --if-exists "$file"
        fi

        if [ "$?" == 0 ]; then
            info "Successfully pushed database dump for '$GREEN$SOURCE_NAME$NORM'"
        else
            warn "Failed to push database dump for '$RED$SOURCE_NAME$NORM'"
        fi
    fi

    if [ "$PUSH" == 1 ]  && [ "$TABLE" == 1 ]; then # if we are pushing a table

        # Ensure we are using the correct file...
        file=$(ls -la ./"$SOURCE_NAME"*.*)
        printf "Would you continue the table restoration with the following file:\n%s%s%s\n" "$GREEN" "$file" "$NORM"
        read -rp "(y/n) " input
        if [ "$input" != "y" ]; then
            exit 0
        fi

        file=$(ls ./"$SOURCE_NAME"*.*)

        echo "pg_restore --host $SERVER_IP --port $SERVER_PORT -U $SERVER_USER -d $SERVER_DB_NAME --verbose --clean --if-exists $file"

        if [ "$DOCKER" == 0 ]; then # If we aren't in a docker container
            docker run -i -e PGPASSWORD="$SERVER_PASS" --mount type=bind,source="$(pwd)"/"$file",target=/"$file" postgres:alpine \
                psql --host $SERVER_IP --port "$SERVER_PORT" -U "$SERVER_USER" -d "$SERVER_DB_NAME"\
                -f "$file"
        else
            export PGPASSWORD="$SERVER_PASS"
            psql --host $SERVER_IP \
                --port "$SERVER_PORT" -U "$SERVER_USER" \
                -d "$SERVER_DB_NAME" -f "$file"
        fi


        if [ "$?" == 0 ]; then
            info "Successfully pushed table '$GREEN$SOURCE_NAME$NORM'"
        else
            warn "Failed to push table '$RED$SOURCE_NAME$NORM'"
        fi
    fi
}

banner
# Check for dependencies
if ! pg_restore --version &> /dev/null; then
    warn "'pg_restore' is not installed. Please install pg_restore and try again."
    exit 3
fi
if ! pg_dump --version &> /dev/null; then
    warn "'pg_dump' is not installed. Please install pg_dump and try again."
    exit 3
fi
if ! psql --version &> /dev/null; then
    warn "'psql' is not installed. Please install psql and try again."
    exit 3
fi
parse_args "$@"