#!/usr/bin/env bash

# Copyright (C) 2013-2018:
# This file is part of Shinken Enterprise, all rights reserved.

# Set default umask to avoid problems when creating Shinken files
umask 0022

source /var/lib/shinken/libexec/libs/shinken_protected_fields.sh

function doexit {
    printf "\033[91m $1 \033[0m\n"
    exit 2
}

function display_help {
    printf "shinken-backup [options]\n"
    printf "This tool will make a shinken backup.\n"
    printf "Options:\n"
    printf "  -h,     --help                                : will display this help\n"
    printf "  -od,    --output-directory [dir]              : the directory where put backup\n"
    printf "  -on,    --output-name [name]                  : the name of the backup\n"
    printf "\n"
    printf "  -a,    --addons                               : backup addons data\n"
    printf "\n"
    printf "  -c,    --configuration                        : backup configuration : will contains database and all configuration files\n"
    printf "  -ca,   --configuration-anonymous              : get an anonymize backup. Will only backup the configuration\n"
    printf "\n"
    printf "  -e,    --events                               : backup event manager data\n"
    printf "\n"
    printf "  -l,    --log                                  : backup log data\n"
    printf "\n"
    printf "  -M,    --modules                              : backup all custom modules\n"
    printf "         --module-type [type]                   : backup only this type of module\n"
    printf "  -L,    --list-modules                         : list all custom modules present in database\n"
    printf "\n"
    printf "  -m,    --metrology                            : backup metrology data\n"
    printf "\n"
    printf "  -s,    --sla                                  : backup SLA data\n"
    printf "\n"
    printf "  -u,    --user                                 : backup user data(hive, etc...)\n"
}

function backup_mongo_collection {
    dest_dir="$backupDir/$1/dump-$1"
    mongodump -o "$dest_dir" -d "$2" -c "$3" >>"$logFile" 2>>"$logFile"
    if [[ $? -ne 0 ]]; then
       doexit "Mongodb database dump fail, please look at $logFile"
    fi
}

function list_modules_in_databases {
    moduleTypeAvailable=()
    bases=$(mongo --quiet --eval 'db.getMongo().getDBNames().forEach(function(db){print(db)})')

    for base in ${bases}; do
        if [[ $base == shinken_module_* ]]; then
            base=$(sed "s/shinken_module_//" <<< $base)
            moduleTypeAvailable+=("$base")
        fi
    done
}

function backup_module {
    mkdir -p "$backupDir/modules/$1"
    mongodump -o "$backupDir/modules/$1/dump-module" -d shinken_module_$1 >>"$logFile" 2>>"$logFile"
    if [[ $? -ne 0 ]]; then
       doexit "Mongodb database dump fail, please look at $logFile"
    fi
}

if [[ "$(id -u)" != "0" ]]; then
   doexit "This script must be run as root"
fi


NOW=$(date +"%Y-%m-%d__%H-%M-%S")
name=""
backupDir=""
backupModuleType=""

sla="0"
configuration="0"
metrology="0"
logs="0"
user="0"
addons="0"
anonymous="0"
events="0"
modules="0"
listModules="0"

mustBackupSla=0
mustBackupConfiguration=0
mustBackupMetrology=0
mustBackupLogs=0
mustBackupUser=0
mustBackupAddons=0
mustBackupEvents=0
mustAnonymous=0
mustBackupModules=0
mustListModules=0

selectSave=0

while :
do
    case "$1" in

    -h | --help)
        display_help
        # Call help function no shifting needed here, we're done.
        exit 0
    ;;
    -s | --sla)
        sla="sla"
        selectSave=1
        shift
    ;;
    -u | --user)
        user="user"
        selectSave=1
        shift
    ;;
    -c | --configuration)
        configuration="configuration"
        selectSave=1
        shift
    ;;
    -ca | --configuration-anonymous)
        anonymous="anonymous"
        selectSave=1
        shift
    ;;
    -m | --metrology)
        metrology="metrology"
        selectSave=1
        shift
    ;;
    -l | --log)
        logs="logs"
        selectSave=1
        shift
    ;;
    -a | --addons)
        addons="addons"
        selectSave=1
        shift
    ;;
    -e | --events)
        events="events"
        selectSave=1
        shift
    ;;
    -M | --modules)
        modules="modules"
        selectSave=1
        shift
    ;;
        --module-type)
        if [[ ${modules} == "modules" ]]; then
            backupModuleType="$2"
            if [[ -z "${backupModuleType}" ]]; then
                display_help
                doexit "Please give a module type" "no_sanatize"
            fi
        else
            display_help
            doexit "you must use -M/--modules option to use -t/--module-type option" "no_sanatize"
        fi
        shift
        shift
    ;;
    -L | --list-modules)
        listModules="listModules"
        selectSave=1
        shift
    ;;
    -on | --output-name)
        name=$(echo "__$2" | tr " " "_"| tr "\\" "_"  2>/dev/null)
        if [[ "$name" = "__" ]]; then
            display_help
            doexit "Please give a name"
        fi
        shift
        shift
    ;;
    -od | --output-directory)
        backupDir="$2"
        if [[ -z "$backupDir" ]]; then
            display_help
            doexit "Please give a directory"
        fi
        shift
        shift
    ;;
    -*)
        display_help
        doexit "Unknown option: $1"
    ;;
    *)
        if [[ ! -z $1 ]]; then
            display_help
            doexit "Unknown option: $1"
        fi
        # No more options
        break
    ;;
    esac
done

if [[ ${selectSave} -eq 1 ]]; then
    if [[ ${sla} == "sla" ]]; then
        mustBackupSla=1
    fi
    if [[ ${user} == "user" ]]; then
        mustBackupUser=1
    fi
    if [[ ${configuration} == "configuration" ]]; then
        mustBackupConfiguration=1
    fi
    if [[ ${metrology} == "metrology" ]]; then
        mustBackupMetrology=1
    fi
    if [[ ${logs} == "logs" ]]; then
        mustBackupLogs=1
    fi
    if [[ ${addons} == "addons" ]]; then
        mustBackupAddons=1
    fi
    if [[ ${events} == "events" ]]; then
        mustBackupEvents=1
    fi
    if [[ ${anonymous} == "anonymous" ]]; then
        mustAnonymous=1
	    # if Anonymous is set we need to backup the configuration also !
	    mustBackupConfiguration=1
    fi
    if [[ ${modules} == "modules" ]]; then
        mustBackupModules=1
    fi
    if [[ ${listModules} == "listModules" ]]; then
        mustListModules=1
    fi
else
    mustBackupSla=1
    mustBackupConfiguration=1
    mustBackupMetrology=1
    mustBackupLogs=1
    mustBackupUser=1
    mustBackupAddons=1
    mustBackupEvents=1
    mustBackupModules=1
fi

if [[ ${mustBackupEvents} -eq 1 ]] || [[ ${mustBackupSla} -eq 1 ]] || [[ ${mustBackupConfiguration} -eq 1 ]] || [[ ${mustBackupUser} -eq 1 ]] || [[ ${mustBackupAddons} -eq 1 ]] || [[ ${mustBackupMetrology} -eq 1 ]] || [[ ${mustBackupModules} -eq 1 ]]; then
    mongo --quiet --eval 'db.getMongo().getDBNames()' > /dev/null  2>&1
    if [[ $? -ne 0 ]]; then
       doexit "Cannot join Mongodb. Please check mongo is available."
    fi
fi

if [[ -z "$backupDir" ]]; then
    backupDir="shinken-backups/$NOW$name"
else
    backupDir="$backupDir/$NOW$name"
fi

if [[ ${mustAnonymous} -eq 1 ]]; then
    backupDir="$backupDir--anonymous"
fi

if [[ -d "$backupDir" ]]; then
    doexit "The backup folder: $backupDir already exist."
fi

function mongo_database_exists {
    mongo --quiet --eval 'db.getMongo().getDBNames()' | grep -q $1
    return $?
}

fullBackupDir=`python -c "import os;print os.path.abspath('$backupDir');"`
if [[ ${fullBackupDir} == /etc/shinken* ]]; then
    doexit "You cannot backup shinken in /etc/shinken.\n Please select another folder where the backup will be saved using --output-directory option."
fi

if [[ ${fullBackupDir} == /etc/shinken-user* ]]; then
    doexit "You cannot backup shinken in /etc/shinken-user.\n Please select another folder where the backup will be saved using --output-directory option."
fi

if [[ ${mustListModules} -eq 1 ]]; then
    # only list modules databases and exit. Do not create backupdir or print it's sucessful !
    list_modules_in_databases
    if [[ ${#moduleTypeAvailable[@]} == 0 ]]; then
        printf "\033[91m \nThere is no custom modules in database to backup. \033[0m\n"
    else
        printf "\nCustom module type available for backup are :\n"
        for module in "${moduleTypeAvailable[@]}"; do
            printf " - ${module}\n"
        done
        printf "\nTo backup one of theses custom modules, do shinken-backup -M --module-type <module_type>\n"
    fi
    exit 0
fi


# make backup dir
mkdir -p "$backupDir" 2>/dev/null

# now get full path from here
backupDir=`readlink -e "$backupDir"`


currentVersion=`sed -ne "s/.*\?\"current_version\" *: *\"\([^\"]*\)\".*/\1/p" /var/lib/shinken/context.json`
echo ${currentVersion} > "$backupDir"/saveVersion


## ----------- events start -----------
if [[ ${mustBackupEvents} -eq 1 ]]; then
    printf "\033[92mSaving Events\033[0m\n"
    mkdir -p "$backupDir"/events/
    logFile="$backupDir"/events/backup-events.log

    if ! mongo_database_exists event_container; then
        echo "Events : No events data" >> $logFile
        printf "\033[93m  No event database to save\n"
    else
        backup_mongo_collection events event_container ec_datas
        backup_mongo_collection events event_container ec_state_cache
        backup_mongo_collection events event_container ec_info
        backup_mongo_collection events event_container ec_acknowledge
        backup_mongo_collection events event_container ec_downtime

        size=`du -sh "$backupDir"/events | awk '{print $1}' `
        printf "\033[92m  Events save size: $size \033[0m\n"
    fi
fi
## ----------- events end -----------

## ----------- sla start -----------
if [[ ${mustBackupSla} -eq 1 ]]; then
    printf "\033[92mSaving Sla\033[0m\n"
    mkdir -p "$backupDir"/sla/
    logFile="$backupDir"/sla/backup-sla.log

    if ! mongo_database_exists shinken; then
        echo "SLA : No SLA data" >> $logFile
        printf "\033[93m  No Sla to save\n"
    else

        backup_mongo_collection sla shinken acknowledge
        backup_mongo_collection sla shinken downtime
        backup_mongo_collection sla shinken sla
        backup_mongo_collection sla shinken sla_archive
        backup_mongo_collection sla shinken sla_info
        backup_mongo_collection sla shinken sla_future_states

        ## dump sla not archives
        collection=`mongo shinken  --quiet --eval "db.getCollectionNames()"`
        IFS=',' read -ra ADDR <<< "$collection"
        for i in "${ADDR[@]}"; do
            if [[ $i =~ ^[0-9]+_[1-2][0-9]{3}$ ]]; then
                backup_mongo_collection sla shinken $i
            fi
        done

        size=`du -sh "$backupDir"/sla | awk '{print $1}' `
        printf "\033[92m  Sla save size: $size \033[0m\n"
    fi
fi
## ----------- sla end -----------

## ----------- user start -----------
if [[ ${mustBackupUser} -eq 1 ]]; then
    printf "\033[92mSaving User\033[0m\n"
    mkdir -p "$backupDir/user/"
    logFile="$backupDir/user/backup-user.log"

    if ! mongo_database_exists shinken ; then
        echo "User : No user data" >> $logFile
        printf "\033[93m  No User to save\n"
    else
        backup_mongo_collection user shinken dashboard
        backup_mongo_collection user shinken hive
        backup_mongo_collection user shinken list
        backup_mongo_collection user shinken share
        backup_mongo_collection user shinken user
        backup_mongo_collection user shinken ui_user_preferences
        backup_mongo_collection user shinken tiles



        size=`du -sh "$backupDir/user" | awk '{print $1}' `
        printf "\033[92m  User save size: $size \033[0m\n"
    fi
fi
## ----------- user end -----------

## ----------- configuration start -----------
if [[ ${mustBackupConfiguration} -eq 1 ]]; then
    printf "\033[92mSaving Configuration\033[0m\n"
    spf_check_mongo_connexion "synchronizer"
    spf_check_consistency_config_db
    if [[ $? -ne 0 ]]; then
        db_activated=$(spf_get_key_activated_from_db)

        if [[ "$db_activated" != "true" ]]; then
            printf "$(show_important_info "There are consistency problems between the Synchronizer configuration file and the database.")\n"
            printf "\n$(show_info "Since the DB encryption is not activated this does not present any issue so the backup will proceed.")\n\n"
        else
            printf "\n\n$(show_critical_info "Consistency check failed.")\n\n"
            printf "\n$(show_info "Here are some hints to solve this problem :")\n"
            printf "\n\t * If you have an export of the key from the database, you can use the command $(show_command "shinken-protected-fields-keyfile-restore" "")\n"
            printf "\n\t * If you don't have an export, but you have a backup made after the encryption, you can use the command and follow its instructions :\n"
            printf "\n\t\t$(show_command "/var/lib/shinken/libexec/tools/shinken-protected-fields-keyfile-rescue-from-backup" "<your backup directory>")\n"
            printf "\n"
            exit 1
        fi
    fi

    mkdir -p "$backupDir/configuration/"
    logFile="$backupDir/configuration/backup-configuration.log"

    if [[ ${mustAnonymous} -eq 1 ]]; then
        mkdir -p "$backupDir/configuration/dump-configuration/"
		python /usr/sbin/shinken-anonymous-backup --db synchronizer --directory "$backupDir/configuration/dump-configuration/" 2>>"$logFile"
	    if [[ $? -ne 0 ]]; then
	       doexit "Mongodb database dump fail, please look at $logFile"
	    fi
    else
	    mongodump -o "$backupDir/configuration/dump-configuration" -d synchronizer >>"$logFile" 2>>"$logFile"
	    if [[ $? -ne 0 ]]; then
	       doexit "Mongodb database dump fail, please look at $logFile"
	    fi
    fi


    # Save global configuration except protected field keyfile
    keyfile="$(spf_get_keyfile_name_from_synchronizer_cfg)"
    is_cfg_encrypted=$(spf_get_activated_from_synchronizer_cfg)

    is_saved=$(spf_get_key_extracted_from_db)
    is_db_encrypted=$(spf_get_key_activated_from_db)

    if [[ "$is_cfg_encrypted" != "$is_db_encrypted" ]]; then
        printf "$(show_failure " The database encrypting activation is different from the cfg file encrypting activation.")\n"
        doexit "Please make sure the configuration is coherent by restarting the Synchronizer or you may lose your data\n"
    fi

    if [[ ! -z "$keyfile" ]]  && [[ -f "$keyfile" ]]; then
        tmp_keyfile=$(mktemp)
        spf_backup_key_from_key_file "$keyfile" > $tmp_keyfile
        # encrypt the keyfile and put it in the /etc/shinken/keyfile.enc
        encrypted_keyfile_name="$(basename ${keyfile}.enc)"
        encrypted_keyfile_path="/etc/shinken/${encrypted_keyfile_name}"
        openssl rsautl -pubin -keyform der -inkey /var/lib/shinken/mongo-recovery/public.der -encrypt -in ${tmp_keyfile} -out ${encrypted_keyfile_path}
        ssl_result=$?
        rm -f ${tmp_keyfile}
        if [[ ${ssl_result} -ne 0 ]]; then
            doexit "Unable to process your keyfile : $keyfile ; check if it is correct."
        fi

        keyfile_opt="--exclude=$keyfile"
    else
        keyfile_opt=""
    fi
    # NOTE: h: follow symbolic links, because /etc/shinken as link is interesting in a HA arbiter setup with drbd
    tar chvfz "$backupDir/configuration/shinken-etc.tar.gz" ${keyfile_opt} /etc/shinken/ >>"$logFile" 2>>"$logFile"
    if [[ $? -ne 0 ]]; then
       doexit "Shinken Enterprise configuration backup fail. Please look at $logFile"
    else
        if [[ -f "$keyfile" ]]; then
            if [[  "$is_saved" != "true" ]] && [[ "$is_db_encrypted" = "true" ]]; then
                printf "\n$(show_important_info "For security reasons,") $(show_critical_info "you are responsible") $(show_important_info "for saving and storing the Protected fields key separately.")\n"
                printf "$(show_important_info "Please run the following command to export the key so you can save the result in a secure location :")\n"
                printf "$(show_command shinken-protected-fields-keyfile-export "")\n\n"
                printf "$(show_important_info "Failure to do so this will result in the loss of your database when you restore your backup")\n\n"
            fi
        fi
    fi

    if [[ ${mustAnonymous} -eq 1 ]]; then
        # If it's an anonymous backup, we need to change the synchronizer.cfg file to set not encrypted
		tar xf "$backupDir/configuration/shinken-etc.tar.gz" -C "$backupDir/configuration/"
		rm -f "$backupDir/configuration/shinken-etc.tar.gz"
		sed -i -e "s/protect_fields__activate_encryption=1/protect_fields__activate_encryption=0/" "$backupDir/configuration/etc/shinken/synchronizer.cfg"
        sed -i -e "s/protect_fields__activate_database_encryption=1/protect_fields__activate_database_encryption=0/" "$backupDir/configuration/etc/shinken/synchronizer.cfg"
        sed -i -e "s/protect_fields__activate_interface_encryption=1/protect_fields__activate_interface_encryption=0/" "$backupDir/configuration/etc/shinken/synchronizer.cfg"
		tar cvfz "$backupDir/configuration/shinken-etc.tar.gz" ${keyfile_opt} -C "$backupDir/configuration" etc >>"$logFile" 2>>"$logFile"
		rm -rf "$backupDir/configuration/etc"
    fi

    rm -f ${encrypted_keyfile_path}
    # And also user specific one but only if exists
    if [[ -d /etc/shinken-user ]]; then
       # NOTE: h: follow symbolic links, because /etc/shinken-user as link is interesting in a HA arbiter setup with drbd
       tar chvfz "$backupDir/configuration/shinken-user.tar.gz" /etc/shinken-user/ >>"$logFile" 2>>"$logFile"
       if [[ $? -ne 0 ]]; then
           doexit "Shinken Enterprise configuration backup fail for the user directory. Please look at $logFile"
       fi
    fi
    if [[ -d /var/lib/shinken-user/libexec ]]; then
       # NOTE: h: follow symbolic links, because /etc/shinken-user as link is interesting in a HA arbiter setup with drbd
       tar chvfz "$backupDir/configuration/var-lib-shinken-user-libexec.tar.gz" /var/lib/shinken-user/libexec/ >>"$logFile" 2>>"$logFile"
       if [[ $? -ne 0 ]]; then
           doexit "Shinken Enterprise configuration backup fail for the user directory. Please look at $logFile"
       fi
    fi


    cp /var/lib/shinken/arbiter-retention*.json "$backupDir/configuration/" >> /dev/null

    # context.json "daemon" and "addons" objects
    mkdir -p "$backupDir/context/"
    contextFile=/var/lib/shinken/context.json
    if [[ -e ${contextFile} ]]; then
        cat ${contextFile} | python -c 'import json,sys;js=json.load(sys.stdin);print json.dumps(js["daemons"])' > "$backupDir/context/context.json.daemons"

        grep "addons" ${contextFile} > /dev/null 2>&1
        addons_present=$?
        if [[ ${addons_present} -eq 0 ]]; then
            cat ${contextFile} | python -c 'import json,sys;js=json.load(sys.stdin);print json.dumps(js["addons"])' > "$backupDir/context/context.json.addons"
        fi

        grep "local_instances" $contextFile > /dev/null 2>&1
        local_instances_present=$?
        if [[ ${local_instances_present} -eq 0 ]]; then
          cat $contextFile | python -c 'import json,sys;js=json.load(sys.stdin);print json.dumps(js["local_instances"])' > "$backupDir/context/context.json.localinstances"
        fi

        # Since 2.5.0, we are backuping the whole context.json so we will have an easy access to the installation & data history
        cp "$contextFile" "$backupDir/context/context.json"
    fi

    size=`du -sh "$backupDir/configuration" | awk '{print $1}' `
    printf "\033[92m  Configuration save size: $size \033[0m\n"

fi
## ----------- configuration end -----------


## ----------- metrology start -----------
if [[ ${mustBackupMetrology} -eq 1 ]]; then
    printf "\033[92mSaving Metrology\033[0m\n"
    mkdir -p "$backupDir/metrology/"
    logFile="$backupDir/metrology/backup-metrology.log"

    cd /opt/graphite/storage/
    # NOTE: h: follow symbolic links, because whisper as link is interesting in a HA arbiter setup with drbd
    LC_ALL=C tar chvfz "$backupDir/metrology/whisper.tar.gz" whisper >>"$logFile" 2>>"$logFile"
    cd "$backupDir"

    if [[ $? -eq 1 ]]; then
       # maybe it's just that the file did changed during backups
       grep 'file changed as we read it' "$logFile" >/dev/null
       # if not found, was a real error
       if [[ $? -eq 1 ]]; then
           doexit "Metrology save fail, please look at $logFile"
       fi
    fi

    if  ! mongo_database_exists shinken ; then
        echo "Metrology : No trending data" >> $logFile
        printf "\033[93m  No trending database to save\n"
    else
        backup_mongo_collection metrology shinken trending
        # if dump directory exist, we move it to backupDir/metrology/dump
        if [ -e dump ]
        then
          mv dump "$backupDir/metrology/dump"
        fi
        mv "$backupDir/metrology/dump-metrology" "$backupDir/metrology/dump-trending"
    fi

    size=`du -sh "$backupDir/metrology" | awk '{print $1}' `
    printf "\033[92m  Metrology save size: $size \033[0m\n"
fi
## ----------- metrology end -----------

## ----------- logs start -----------
if [[ ${mustBackupLogs} -eq 1 ]]; then
    printf "\033[92mSaving Logs\033[0m\n"
    mkdir -p "$backupDir/logs/"
    logFile="$backupDir/logs/backup-logs.log"

    cd /var/log
    # NOTE: h: follow symbolic links, because the logs as link is interesting in a HA arbiter setup with drbd
    LC_ALL=C tar chvfz "$backupDir/logs/logs.tar.gz" shinken >>"$logFile" 2>>"$logFile"
    if [[ $? -eq 1 ]]; then
       # maybe it's just that the file did changed during backups
       grep 'file changed as we read it' "$logFile" >/dev/null
       # if not found, was a real error
       if [[ $? -eq 1 ]]; then
           doexit "Logs save fail, please look at $logFile"
       fi
    fi

    size=`du -sh "$backupDir/logs" | awk '{print $1}' `
    printf "\033[92m  Logs save size: $size \033[0m\n"
fi
## ----------- logs end -----------

## ----------- addons start -----------
if [[ ${mustBackupAddons} -eq 1 ]]; then
    printf "\033[92mSaving addons data\033[0m\n"
    mkdir -p "$backupDir/addons/"
    logFile="$backupDir/addons/backup-addons.log"

    # Create associative array containing the following data:
    #     key: addon name
    #     value: string containing addon_nagvis_install_path:nagvis_apache_cfg_file_path
    declare -A addonsConfigurationFiles=( ["nagvis-shinken-architecture"]="/var/lib/shinken-nagvis/:/etc/httpd/conf.d/nagvis_etc.conf*" ["nagvis"]="/opt/nagvis/:/etc/httpd/conf.d/nagvis_opt.conf*" )

    for addon in "${!addonsConfigurationFiles[@]}"; do
        nagvis_folder="${addonsConfigurationFiles[$addon]%%:*}"
        apache_cfg_file="${addonsConfigurationFiles[$addon]##*:}"
        mkdir -p "$backupDir/addons/$addon/"

        # SEF-6166 : if $apache_cfg_file contains have more than one path file
        for file in $apache_cfg_file
        do
          cp $file "$backupDir/addons/$addon/$(basename $file)"
        done

        tar chvfz "$backupDir/addons/$addon/addon.tar.gz" -C $nagvis_folder . >>"$logFile" 2>>"$logFile"
        if [[ $? -ne 0 ]]; then
           doexit "Could not save $addon files. Please look at $logFile"
        fi
    done

    size=`du -sh "$backupDir/addons" | awk '{print $1}' `
    printf "\033[92m  Addons save size: $size \033[0m\n"
fi
## ----------- addons end -----------

## ----------- Modules start -----------
if [[ $mustBackupModules -eq 1 ]]; then
    printf "\033[92mSaving custom modules data\033[0m\n"
    mkdir -p "$backupDir/modules/"
    logFile="$backupDir/modules/backup-modules.log"

    list_modules_in_databases

    if [[ ${#moduleTypeAvailable[@]} == 0 ]]; then
        printf "\033[91m There is no custom modules in database to backup. \033[0m\n"
    else

        for fullModuleType in "${moduleTypeAvailable[@]}"; do
            if [[ ${backupModuleType} == "" ]] || [[ $fullModuleType == ${backupModuleType} ]]; then
                backup_module $fullModuleType
            fi
        done

        if [[ -n ${backupModuleType} ]] && [[ ! -e ${backupDir}/modules/${backupModuleType} ]]; then
            doexit "Module ${backupModuleType} is not available for backup."
        fi

        size=`du -sh "$backupDir/modules" | awk '{print $1}' `
        printf "\033[92m  Custom modules save size: $size \033[0m\n"
    fi
fi
## ----------- Modules end -----------

printf "\n\033[92mDone : your backup directory is $backupDir\033[0m\n"

