# globals PROMPT_USER="" PROMPT_PASS="" function dbasm_waitMysqlConn() { DBHOST="$1" DBPORT="$2" COUNT=0 while ! mysqladmin ping -h"$DBHOST" --port="$DBPORT" --silent; do ((COUNT++)) if [ $COUNT -gt $DBASM_WAIT_RETRIES ]; then echo "DBASM Timeout: Cannot ping mysql!" 1>&2 exit 64 fi echo "Cannot ping mysql on $DBHOST:$DBPORT, retry in $DBASM_WAIT_TIMEOUT seconds (remaining: $COUNT/$DBASM_WAIT_RETRIES)..." sleep $DBASM_WAIT_TIMEOUT done } # use in a subshell function dbasm_resetExitCode() { exit 0 } function dbasm_mysqlExec() { confs=$1 command=$2 options=$3 # MYSQL_PORT needs to be reseted as the next eval might not overwite the current value causing the commands to use wrong port MYSQL_PORT=3306 eval $confs if [[ ! -z "${PROMPT_USER// }" ]]; then MYSQL_USER=$PROMPT_USER MYSQL_PASS=$PROMPT_PASS fi dbasm_waitMysqlConn $MYSQL_HOST $MYSQL_PORT export MYSQL_PWD=$MYSQL_PASS retval=$("$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$MYSQL_USER" -P "$MYSQL_PORT" $options -e "$command") if [[ $? -ne 0 ]]; then err=$("$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$MYSQL_USER" -P "$MYSQL_PORT" $options -e "$command" 2>&1 ) if [[ "$err" == *"Access denied"* ]]; then read -p "Insert mysql user:" PROMPT_USER read -p "Insert mysql pass:" -s PROMPT_PASS export MYSQL_PWD=$PROMPT_PASS retval=$("$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" -P "$MYSQL_PORT" $options -e "$command") if [[ $? -ne 0 ]]; then err=$("$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" -P "$MYSQL_PORT" $options -e "$command" 2>&1 ) # it happens on new mysql 5.7 installations # since mysql_native_password is explicit now if [[ "$err" == *"Access denied"* ]]; then echo "Setting mysql_native_password and for $PROMPT_USER ..." sudo -h "$MYSQL_HOST" "$DB_MYSQL_EXEC" -P "$MYSQL_PORT" -e "UPDATE mysql.user SET authentication_string=PASSWORD('${PROMPT_PASS}'), plugin='mysql_native_password' WHERE User='${PROMPT_USER}'; FLUSH PRIVILEGES;" fi fi # create configured account if not exists "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" $options -P "$MYSQL_PORT" -e "CREATE USER IF NOT EXISTS '${MYSQL_USER}'@'${MYSQL_HOST}' IDENTIFIED BY '${MYSQL_PASS}' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0;" "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" $options -P "$MYSQL_PORT" -e "GRANT CREATE ON *.* TO '${MYSQL_USER}'@'${MYSQL_HOST}' WITH GRANT OPTION;" for db in ${DATABASES[@]} do local _uc=${db^^} local _name="DB_"$_uc"_CONF" local _confs=${!_name} local _name="DB_"$_uc"_NAME" local _dbname=${!_name} eval $_confs echo "Grant permissions for ${MYSQL_USER}'@'${MYSQL_HOST} to ${_dbname}" "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" $options -P "$MYSQL_PORT" -e "GRANT ALL PRIVILEGES ON ${_dbname}.* TO '${MYSQL_USER}'@'${MYSQL_HOST}' WITH GRANT OPTION; FLUSH PRIVILEGES;" done else exit fi fi } function dbasm_isNotEmpty() { dbname=$1 conf=$2 dbasm_mysqlExec "$conf" "SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_schema = '${dbname}'" "--skip-column-names" if (( $retval > 0 )); then true else false fi } function dbasm_dbExists() { dbname=$1 conf=$2 dbasm_mysqlExec "$conf" "SHOW DATABASES LIKE '${dbname}'" "--skip-column-names" if [ "$retval" == "${dbname}" ]; then true else false fi } function dbasm_createDB() { database=${1,,} uc=${database^^} name="DB_"$uc"_CONF" confs=${!name} name="DB_"$uc"_NAME" dbname=${!name} eval $confs CONF_USER=$MYSQL_USER CONF_PASS=$MYSQL_PASS if dbasm_dbExists $dbname "$confs"; then echo "$dbname database exists" else echo "Creating DB ${dbname} ..." dbasm_mysqlExec "$confs" "CREATE DATABASE \`${dbname}\`;" "" echo "Creating User ${CONF_USER}@${MYSQL_HOST} identified by ${CONF_PASS}..." dbasm_mysqlExec "$confs" "CREATE USER IF NOT EXISTS '${CONF_USER}'@'${MYSQL_HOST}' IDENTIFIED BY '${CONF_PASS}';" echo "Granting user privileges on: ${dbname} ..." dbasm_mysqlExec "$confs" "GRANT ALL PRIVILEGES ON \`${dbname}\`.* TO '${CONF_USER}'@'${MYSQL_HOST}'" echo "Flush privileges" dbasm_mysqlExec "$confs" "FLUSH PRIVILEGES;" fi } function dbasm_assemble() { # to lowercase database=${1,,} start_sql=$2 with_base=$3 with_updates=$4 with_custom=$5 uc=${database^^} name="DB_"$uc"_PATHS" v="$name[@]" base=("${!v}") name="DB_"$uc"_UPDATES_PATHS" v="$name[@]" updates=("${!v}") name='DB_'$uc'_CUSTOM_PATHS' v="$name[@]" custom=("${!v}") suffix_base="_base" suffix_upd="_updates" suffix_custom="_custom" curTime=`date +%Y_%m_%d_%H_%M_%S` # ALLOW FOR RECURSION WITH "**" shopt -s globstar if [ $with_base = true ]; then echo "" > "$OUTPUT_FOLDER$database$suffix_base.sql" if [ ! ${#base[@]} -eq 0 ]; then echo "Generating $OUTPUT_FOLDER$database$suffix_base ..." for d in "${base[@]}" do echo "Searching on $d ..." if [ ! -z "$d" ]; then for entry in "$d"/**/*.sql do if [[ -e $entry ]]; then cat "$entry" >> "$OUTPUT_FOLDER$database$suffix_base.sql" fi done fi done fi fi if [ $with_updates = true ]; then updFile="$OUTPUT_FOLDER$database$suffix_upd.sql" echo "" > "$updFile" if [ ! ${#updates[@]} -eq 0 ]; then echo "Generating $OUTPUT_FOLDER$database$suffix_upd ..." for d in "${updates[@]}" do echo "Searching on $d ..." if [ ! -z "$d" ]; then for entry in "$d"/**/*.sql do if [[ ! -e $entry ]]; then continue fi echo "-- $file" >> "$updFile" cat "$entry" >> "$updFile" done fi done fi fi if [ $with_custom = true ]; then custFile="$OUTPUT_FOLDER$database$suffix_custom.sql" echo "" > "$custFile" if [ ! ${#custom[@]} -eq 0 ]; then echo "Generating $OUTPUT_FOLDER$database$suffix_custom ..." for d in "${custom[@]}" do echo "Searching on $d ..." if [ ! -z "$d" ]; then for entry in "$d"/**/*.sql do if [[ ! -e $entry ]]; then continue fi echo "-- $file" >> "$custFile" cat "$entry" >> "$custFile" done fi done fi fi } function dbasm_run() { echo "===== STARTING ASSEMBLY PROCESS =====" mkdir -p "$OUTPUT_FOLDER" for db in ${DATABASES[@]} do dbasm_assemble "$db" $version".sql" $1 $2 $3 done echo "===== DONE =====" } function dbasm_db_backup() { echo "backing up $1" database=${1,,} uc=${database^^} name="DB_"$uc"_CONF" confs=${!name} name="DB_"$uc"_NAME" dbname=${!name} # MYSQL_PORT needs to be reseted as the next eval might not overwite the current value causing the commands to use wrong port MYSQL_PORT=3306 eval $confs; if [[ ! -z "${PROMPT_USER// }" ]]; then MYSQL_USER=$PROMPT_USER MYSQL_PASS=$PROMPT_PASS fi export MYSQL_PWD=$MYSQL_PASS now=`date +%s` "$DB_MYSQL_DUMP_EXEC" --opt --user="$MYSQL_USER" --host="$MYSQL_HOST" --port="$MYSQL_PORT" "$dbname" > "${BACKUP_FOLDER}${database}_backup_${now}.sql" && echo "done" if [[ $? -ne 0 ]]; then err=$("$DB_MYSQL_DUMP_EXEC" --opt --user="$MYSQL_USER" --host="$MYSQL_HOST" --port="$MYSQL_PORT" "$dbname" 2>&1 ) if [[ "$err" == *"Access denied"* ]]; then read -p "Insert mysql user:" PROMPT_USER read -p "Insert mysql pass:" -s PROMPT_PASS export MYSQL_PWD=$PROMPT_PASS "$DB_MYSQL_DUMP_EXEC" --opt --user="$PROMPT_USER" --host="$MYSQL_HOST" --port="$MYSQL_PORT" "$dbname" > "${BACKUP_FOLDER}${database}_backup_${now}.sql" && echo "done" else exit fi fi } function dbasm_db_import() { database=${1,,} type=$2 uc=${database^^} name="DB_"$uc"_CONF" confs=${!name} name="DB_"$uc"_NAME" dbname=${!name} if [[ $type = "base" && $DB_SKIP_BASE_IMPORT_IF_EXISTS = true ]]; then if dbasm_isNotEmpty $dbname "$confs"; then echo "$dbname is not empty, base importing skipped" return else echo "$dbname seems empty" fi fi echo "importing $1 - $2 ..." # MYSQL_PORT needs to be reseted as the next eval might not overwite the current value causing the commands to use wrong port MYSQL_PORT=3306 eval $confs; if [[ ! -z "${PROMPT_USER// }" ]]; then MYSQL_USER=$PROMPT_USER MYSQL_PASS=$PROMPT_PASS fi dbasm_waitMysqlConn $MYSQL_HOST $MYSQL_PORT export MYSQL_PWD=$MYSQL_PASS # TODO: remove this line after we squash our DB updates "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$MYSQL_USER" --port="$MYSQL_PORT" -e "SET GLOBAL max_allowed_packet=128*1024*1024;" "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$MYSQL_USER" --port="$MYSQL_PORT" --default-character-set=utf8 "$dbname" < "${OUTPUT_FOLDER}${database}_${type}.sql" if [[ $? -ne 0 ]]; then err=$("$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$MYSQL_USER" -P "$MYSQL_PORT" "$dbname" 2>&1 ) if [[ "$err" == *"Access denied"* ]]; then read -p "Insert mysql user:" PROMPT_USER read -p "Insert mysql pass:" -s PROMPT_PASS export MYSQL_PWD=$PROMPT_PASS "$DB_MYSQL_EXEC" -h "$MYSQL_HOST" -u "$PROMPT_USER" -P "$MYSQL_PORT" "$dbname" < "${OUTPUT_FOLDER}${database}_${type}.sql" else exit fi fi } function dbasm_import() { dbasm_run $1 $2 $3 with_base=$1 with_updates=$2 with_custom=$3 echo "===== CHECKING DBs =====" for db in ${DATABASES[@]} do dbasm_createDB "$db" done echo "===== DONE =====" # # BACKUP # if [ $BACKUP_ENABLE = true ]; then echo "===== STARTING BACKUP PROCESS =====" mkdir -p "$BACKUP_FOLDER" for db in ${DATABASES[@]} do dbasm_db_backup "$db" done echo "===== DONE =====" fi echo "===== STARTING IMPORTING PROCESS =====" # # IMPORT # if [ $with_base = true ]; then for db in ${DATABASES[@]} do dbasm_db_import "$db" "base" done fi if [ $with_updates = true ]; then for db in ${DATABASES[@]} do dbasm_db_import "$db" "updates" done fi if [ $with_custom = true ]; then for db in ${DATABASES[@]} do dbasm_db_import "$db" "custom" done fi echo "===== DONE =====" }