#!/usr/bin/bash
#
# MySQL Initialisation
#
# Usage: $0 [--force] [ExecStartPost] [--force]
#

# Must be run as root as we are using auth_socket for the root user to execute mysql commands
if [ "$EUID" -ne 0 ]; then
        echo "(basename $0): This script must be run as root"
        exit 1
fi

FORCE=
if [ "$1" == "--force" ]; then
        FORCE="$1"
        shift
fi

CALLER="$1"
shift

# Check again in case  the --force was after CALLER instead of before
if [ "$1" == "--force" ]; then
        FORCE="$1"
        shift
fi

# Basic database setup including "common" schemas and root auth via socket
if [[ -n "$FORCE" || ! -f /root/.my.cnf  ]] || ! grep -Pq '^\s*password\s*=' /root/.my.cnf; then

        if ! mysqladmin ping >&/dev/null; then
                systemctl start mysqld
                systemctl --quiet enable mysqld
        fi

	MYSQL_LOG_FILE=$(my_print_defaults mysqld | sed -nre 's/--log-error=(.*)$/\1/p')
	[[ -z "$MYSQL_LOG_FILE" ]] && echo "$(basename "$0"): Unable to determine mysql error log file from 'my_print_defaults mysqld' output" && exit 1

	TEMP_PASSWORD=$(grep 'A temporary password is generated for root@localhost:' "$MYSQL_LOG_FILE" | sed -e 's/.*: //')
	[[ -z "$TEMP_PASSWORD" ]] && echo "$(basename "$0"): Unable to parse root users temporary password from $MYSQL_LOG_FILE" && exit 1

	# Set socket auth instead of storing temporary password in my.cnf
	mysql --user=root --password="$TEMP_PASSWORD" --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket"
	# Redact temporary password from log file
	sed -i "$MYSQL_LOG_FILE" -re "s/(A temporary password is generated for root@localhost:) .*$/\1 <redacted by $(basename "$0")>/g"

	# Set a repeatable passowrd in root's my.cnf
	# NOTE: This is not used for local connections over the socket, which use socket_auth, but is used for cross-node cluster tcp connections (e.g.the ng-reload-mysql-replica-from-source script)
	ROOTPASS=$(ng-mk-auth-token -f /etc/sysconfig/authseed mysql:root@localhost 16)
	MYSQL_SOCKET_FILE=$(my_print_defaults mysqld | sed -nre 's/--socket=(.*)$/\1/p')
	augtool --noautoload --autosave <<-EOD
		set /augeas/load/MySQL/lens "MySQL.lns"
		set /augeas/load/MySQL/incl "/root/.my.cnf"
		load
		set /files/root/.my.cnf/target[.='client'] 'client'
		set /files/root/.my.cnf/target[.='client']/password '$ROOTPASS'
		set /files/root/.my.cnf/target[.='client']/socket '$MYSQL_SOCKET_FILE'
	EOD

	# The "local" database is ignored for replication (but still binlogged)
	mysql -NB -e 'CREATE DATABASE IF NOT EXISTS local;'
	# The "unlogged" database is not binlogged (and therefore not replicated)
	mysql -NB -e 'CREATE DATABASE IF NOT EXISTS unlogged;'
elif [[ "$CALLER" != "ExecStartPost" ]]; then
	echo "$(basename "$0"): Skipping MySQL root password setup as it appears to already be configured, specify --force to override" >&2
fi


if mysqladmin ping >&/dev/null; then

        # These are repeated from above since they are idempotent and this section runs every time
        # The "local" database is ignored for replication (but still binlogged)
        mysql -NB -e 'CREATE DATABASE IF NOT EXISTS local;'
        # The "unlogged" database is not binlogged (and therefore not replicated)
        mysql -NB -e 'CREATE DATABASE IF NOT EXISTS unlogged;'

        # Create healthcheck user with auth_socket authentication
        mysql -NB -e "CREATE USER 'healthcheck'@'localhost' IDENTIFIED WITH auth_socket;"

        # Drop the test database, remove anonymous users, remove remote root logins
        mysql -NB -e "DROP DATABASE IF EXISTS test;"
        mysql -NB -e "DELETE FROM mysql.user WHERE (User = '') OR (User = 'root' AND Host <> 'localhost' AND authentication_string = '');"


        # Load the timezone data if the table is empty
        if [ "0" == "$( mysql -NB -e "SELECT COUNT(*) FROM mysql.time_zone_name" 2>/dev/null)" ]; then
                CMD_LOADTZDATA=$(command -v mysql_tzinfo_to_sql 2>/dev/null)
                DIR_ZONEINFO=/usr/share/zoneinfo/posix
                $CMD_LOADTZDATA $DIR_ZONEINFO | mysql mysql
        fi

        # Don't do replication setup from ExecStartPost, since we'll trigger a restart of mysqld
        [ "$CALLER" == "ExecStartPost" ] && exit 0;


        # Configure the cluster if details are provided AND replication hasn't already been configured
        # TODO: We should split this up so that 
        # TODO : Appears to be broken for newer versionf of MySQL, 'SHOW SLAVE STATUS' returns nothing
        if [[ -f /etc/sysconfig/ng-kickstart ]]; then
                if [[ -z "$FORCE" ]] && mysql -BEe 'SHOW SLAVE STATUS' | grep -qP 'Source_Host:\s*\S'; then
                        echo "$(basename "$0"): Skipping MySQL replication setup as Source_Host: appears to be already set, specify --force to override" >&2
                else
                        source /etc/sysconfig/ng-kickstart
                        if [[ -n "$clustersoa" && -n "$clusterhosts" ]]; then
                                env HOME=/root /usr/libexec/ng-server-config/init-mysql-cluster "$FORCE" \
                                        "${clustersoa}${clusterdomain:+.$clusterdomain}" \
                                        "${clusterhosts%%,*}${clustersoa:+.$clustersoa}${clusterdomain:+.$clusterdomain}" \
                                        "${clusterhosts##*,}${clustersoa:+.$clustersoa}${clusterdomain:+.$clusterdomain}"

                                env HOME=/root /usr/libexec/ng-server-config/join-mysql-cluster "$FORCE" \
                                        "$HOME/mysql-cluster/X.509/${clustersoa}${clusterdomain:+.$clusterdomain}"
                        else
                                echo "$(basename "$0"): Skipping MySQL replication setup as clustersoa and/or clusterdomain are not defined in /etc/sysconfig/ng-kickstart" >&2
                        fi
                fi
        else
                echo "$(basename "$0"): Skipping MySQL replication setup as /etc/sysconfig/ng-kickstart does not exist" >&2
        fi

fi

