Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
make_db 6.31 KiB
#!/bin/bash

# ** header v3.0
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2019, 2020 Daniel Hornung <d.hornung@indiscale.com>
# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
# Copyright (C) 2020 Henrik tom Wörden <h.tomwoerden@indiscale.com>
# Copyright (C) 2020 IndiScale <info@indiscale.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# ** end header

set -e

INSTALL_SQL_FILE="db_2_0.sql"

if [ -z "$UTILSPATH" ]; then
    UTILSPATH="$(realpath $(dirname $0))"
    export UTILSPATH
fi

source $UTILSPATH/load_settings.sh
source $UTILSPATH/helpers.sh

UNITTEST_DATABASE=${UNITTEST_DATABASE-_caosdb_schema_unit_tests}

# optional parameter: [--fresh] for installing a fresh data base. Otherwise an existing one would be reused.
function runtests() {
    DATABASE_NAME=$UNITTEST_DATABASE
    _setup_mytap

    _install_unit_test_database $@

    _execute_tests || ( failure )
    echo "[PASS]"
}

function _execute_tests () {
    pushd tests
    TESTS="./test*.sql"

    rm -f .TEST_RESULTS
    for tfile in $TESTS ; do
        echo "Running $tfile"
        echo "----- $tfile -----" >> .TEST_RESULTS
        cat $tfile | $MYSQL_CMD $(get_db_args_nodb) --disable-pager --batch --raw --skip-column-names --unbuffered >> .TEST_RESULTS
    done;

    popd
    cat tests/.TEST_RESULTS
    grep -c -i "failed" tests/.TEST_RESULTS > /dev/null && return 1
    return 0
}

# install/reset database for unit tests.
# optional parameter: [--fresh] for installing a fresh data base. Otherwise an existing one would be reused.
function _install_unit_test_database () {
    DATABASE_NAME=$UNITTEST_DATABASE
    if _db_exists "$DATABASE_NAME"; then
        if [[ "$1" == "--fresh" ]] ; then
            drop "$DATABASE_NAME" ;
        else
            return 0;
        fi
    fi

    sed "s/db_2_0/$DATABASE_NAME/g" "$INSTALL_SQL_FILE" | $MYSQL_CMD $(get_mysql_args_nodb)

    # create test user
    grant

    echo "DATABASE_NAME=\"$UNITTEST_DATABASE\"" >> .test_config
    pushd patches > /dev/null
    export ENV_FILE=$(realpath ../.test_config)
    ./applyPatches.sh
    unset ENV_FILE
    popd > /dev/null
    rm .test_config
}

# install test framework MyTAP if not installed
function _setup_mytap() {
    if _db_exists "tap" ; then
        echo MyTAB framework is already installed [OK]
        return 0
    fi
    echo -n "Installing MyTAP framework ... "
    pushd libs > /dev/null
    unzip -u mytap*.zip > /dev/null
    pushd mytap*/ > /dev/null
    $MYSQL_CMD $(get_mysql_args_nodb) < mytap.sql > /dev/null || exit 1
    popd > /dev/null
    rm -r mytap*/
    popd > /dev/null
    echo "[DONE]"
}

function install_db() {
    if _db_exists ; then
        echo -e "\n
A database with with the name '$DATABASE_NAME' exists already.
Call 'make drop-$DATABASE_NAME' to delete that database or reconfigure with
'./configure'."
        exit 0
    fi

    sed "s/db_2_0/$DATABASE_NAME/g" "$INSTALL_SQL_FILE" | $MYSQL_CMD $(get_mysql_args_nodb)
}

# Inserts the dump (arg 1) into the database
function restore_db() {
    SQL_FILE="$1"
    $MYSQL_CMD $(get_mysql_args) < "$SQL_FILE"
}

function test-connection() {
    $MYSQL_CMD $(get_mysql_args_nodb) -e "select 0;"
}

# Creates a user and grants it sufficient rights.
# If called with --strict, the user is not allowed to exist previously.
function grant() {
    if [ -z "$DATABASE_USER_PW" ] ; then
        while true; do
            read -p "Please enter the password for ${DATABASE_USER}: " \
                 -s password
            echo
            read -p "Please repeat the password: " -s password2
            echo
            [[ "$password" == "$password2" ]] && {
                DATABASE_USER_PW="$password"
                break
            }
            echo -e "\nThe passwords didn't match. Try again."
        done
    fi

    if [[ "$1" == "--strict" ]] ; then
        for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
            CMD="SELECT COUNT(*) FROM mysql.user WHERE user='${DATABASE_USER}' AND host='${host}';"
            [[ $($MYSQL_CMD $(get_mysql_args_nodb) -s -N -e "$CMD") == 0 ]] || {
                echo "The user '${DATABASE_USER}@${host}' is already in the database."
                echo "Please use another user or delete it, e.g. with"
                echo "'mysql -u ${MYSQL_USER} -p -e \"DROP USER ${DATABASE_USER}@${host};\"'"
                exit 1
            }
        done
    fi

    for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
        echo "Granting admin privileges to '$DATABASE_USER'@'$host'"
        $MYSQL_CMD $(get_mysql_args_nodb) <<EOF
CREATE USER IF NOT EXISTS
    '$DATABASE_USER'@'$host' identified by '$DATABASE_USER_PW';
GRANT USAGE ON *.* TO '$DATABASE_USER'@'$host';
GRANT ALL PRIVILEGES ON *.* TO '$DATABASE_USER'@'$host' WITH GRANT OPTION;
GRANT EXECUTE ON *.* TO '$DATABASE_USER'@'$host';
EOF
    done
}

# Drops the caosdb user plus a given database from all listed database hosts.
# The first argument to this function is the database that shal be dropped.
function drop() {
    DROPDB="$1"
    for host in ${DATABASE_USER_HOST_LIST//,/ } ; do
        $MYSQL_CMD $(get_mysql_args_nodb) -e "DROP USER '${DATABASE_USER}'@'${host}';" || true
    done
    "$MYSQLADMIN_CMD" $(get_mysql_args_nodb) -f drop "$DROPDB"
}


# Returns 0 or non-zero, depending on whether the database exists already.
# Optional parameter: [DATABASE_NAME], else $DATABASE_NAME is used.
function _db_exists() {
    $MYSQL_CMD $(get_mysql_args_nodb) -D "${1-${DATABASE_NAME}}" -e "show tables;" > /dev/null 2>&1 \
        && return 0 || return 1
}


case $1 in
    "drop") drop $2 ;;
    "grant") grant $2 ;;
    "test") shift ; runtests $@ ;;
    "test-connection") test-connection ;;
    "install_db") install_db ;;
    "restore_db") restore_db $2 ;;
    # "prep_sql") prepare_sql ;;
    *) echo "Unknown action: $1"
esac