From 94616c4269fda0bfac15894be34d2fb6215b4404 Mon Sep 17 00:00:00 2001 From: Lars Tangvald Date: Thu, 18 Oct 2018 09:46:33 +0200 Subject: [PATCH] entrypoint: Move more logic into functions Almost all logic in the entrypoint script is now separated into various functions --- .template.Debian/docker-entrypoint.sh | 253 ++++++++++++++++---------- update.sh | 8 +- 2 files changed, 162 insertions(+), 99 deletions(-) diff --git a/.template.Debian/docker-entrypoint.sh b/.template.Debian/docker-entrypoint.sh index 5ba91bc96..f4d5a5f68 100755 --- a/.template.Debian/docker-entrypoint.sh +++ b/.template.Debian/docker-entrypoint.sh @@ -90,8 +90,8 @@ docker_get_config() { # match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)" } +# Do a temporary startup of the MySQL server, for init purposes docker_start_server() { - local socket=$1; shift result=0 %%SERVERSTARTUP%% if [ ! "$result" = "0" ];then @@ -99,6 +99,8 @@ docker_start_server() { fi } +# Wait for the temporary server to be ready for connections. +# It is only used for versions older than 5.7 docker_wait_for_server() { local mysql=( "$@" ) for i in {30..0}; do @@ -112,123 +114,188 @@ docker_wait_for_server() { fi } +# Stop the server. When using a local socket file mysqladmin will block until +# the shutdown is complete. docker_stop_server() { - local passfile=$1 - local socket=$2 result=0 - mysqladmin --defaults-extra-file="${passfile}" shutdown -uroot --socket="${socket}" || result=$? + mysqladmin --defaults-extra-file="${PASSFILE}" shutdown -uroot --socket="${SOCKET}" || result=$? if [ ! "$result" = "0" ]; then docker_error "Unable to shut down server. Status code $result." fi } + +# Verify that the minimally required password settings are set for new databases. +docker_verify_env() { + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + docker_error "Database is uninitialized and password option is not specified \n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD" + fi +} + +# Creates and initializes the database directory +docker_init_database_dir() { + mkdir -p "$DATADIR" + + docker_note "Initializing database files" + %%DATABASEINIT%% + docker_note "Database files initialized" + + if command -v mysql_ssl_rsa_setup > /dev/null && [ ! -e "$DATADIR/server-key.pem" ]; then + # https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/packaging/deb-in/extra/mysql-systemd-start#L81-L84 + docker_note "Initializing certificates" + mysql_ssl_rsa_setup --datadir="$DATADIR" + docker_note "Certificates initialized" + fi +} + +# Loads various settings that are used elsewhere in the script +docker_init_env() { + # Get config + DATADIR="$(docker_get_config 'datadir' "$@")" + SOCKET="$(docker_get_config 'socket' "$@")" + + # We create a file to store the root password in so we don''t use it on the command line + TMPDIR="$(mktemp -d)" + PASSFILE="$(mktemp ${TMPDIR}/XXXXXXXXXX)" + + # Initialize values that might be stored in a file + docker_file_env 'MYSQL_ROOT_HOST' '%' + docker_file_env 'MYSQL_DATABASE' + docker_file_env 'MYSQL_USER' + docker_file_env 'MYSQL_PASSWORD' + docker_file_env 'MYSQL_ROOT_PASSWORD' +} + +# Define the client command that's used in various places +docker_init_client_command() { + mysql=( mysql --defaults-file="${PASSFILE}" --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" ) +} + +# Store root password in a file for use with the client command +docker_write_password_file() { + # Write the password to the file the client uses + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + cat >"${PASSFILE}" < /dev/null && [ ! -e "$DATADIR/server-key.pem" ]; then - # https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/packaging/deb-in/extra/mysql-systemd-start#L81-L84 - docker_note "Initializing certificates" - mysql_ssl_rsa_setup --datadir="$DATADIR" - docker_note "Certificates initialized" - fi - - SOCKET="$(docker_get_config 'socket' "$@")" - # We create a file to store the root password in so we don''t use it on the command line - TMPDIR="$(mktemp -d)" - PASSFILE="$(mktemp ${TMPDIR}/XXXXXXXXXX)" + docker_verify_env + docker_init_database_dir "$@" + docker_init_client_command - mysql=( mysql --defaults-file="${PASSFILE}" --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" ) - docker_note "Starting server" - docker_start_server "${SOCKET}" "$@" + docker_note "Starting temporary server" + docker_start_server "$@" + # For 5.7+ the server is ready for use as soon as startup command unblocks if [ "${MYSQL_MAJOR}" = "5.5" ] || [ "${MYSQL_MAJOR}" = "5.6" ]; then docker_note "Waiting for server startup" docker_wait_for_server "${mysql[@]}" fi - docker_note "Server started." + docker_note "Temporary server started." if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then - # sed is for https://bugs.mysql.com/bug.php?id=20545 - mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql + docker_load_tzinfo fi if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then - export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" - docker_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" - fi - - rootCreate= - # default root to listen for connections from anywhere - docker_file_env 'MYSQL_ROOT_HOST' '%' - if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then - # no, we don't care if read finds a terminating character in this heredoc - # https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151 - read -r -d '' rootCreate <<-EOSQL || true - CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; - GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; - EOSQL - fi - - "${mysql[@]}" <<-EOSQL - -- What's done in this file shouldn't be replicated - -- or products like mysql-fabric won't work - SET @@SESSION.SQL_LOG_BIN=0; - - %%PASSWORDSET%% - GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ; - ${rootCreate} - DROP DATABASE IF EXISTS test ; - FLUSH PRIVILEGES ; - EOSQL - - # Write the password to the file the client uses - if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then - cat >"${PASSFILE}" <