summaryrefslogtreecommitdiffstats
path: root/kubernetes/portal/charts/portal-mariadb/resources/config/mariadb/docker-entrypoint.sh
blob: f00bf8b71dc94023f75ed4476137e5df214e6b3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
set -eo pipefail
shopt -s nullglob

# if command starts with an option, prepend mysqld
if [ "${1:0:1}" = '-' ]; then
        set -- mysqld "$@"
fi

# skip setup if they want an option that stops mysqld
wantHelp=
for arg; do
        case "$arg" in
                -'?'|--help|--print-defaults|-V|--version)
                        wantHelp=1
                        break
                        ;;
        esac
done

# usage: file_env VAR [DEFAULT]
#    ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
#  "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
        local var="$1"
        local fileVar="${var}_FILE"
        local def="${2:-}"
        if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
                echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
                exit 1
        fi
        local val="$def"
        if [ "${!var:-}" ]; then
                val="${!var}"
        elif [ "${!fileVar:-}" ]; then
                val="$(< "${!fileVar}")"
        fi
        export "$var"="$val"
        unset "$fileVar"
}

_check_config() {
        toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
        if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
                cat >&2	<<-EOM

				ERROR: mysqld failed while attempting to check config
				command was: "${toRun[*]}"

				$errors
				EOM
                exit 1
        fi
}

# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
_get_config() {
        local conf="$1"; shift
        "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null | awk '$1 == "'"$conf"'" { print $2; exit }'
}

# allow the container to be started with `--user`
if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
        _check_config "$@"
        DATADIR="$(_get_config 'datadir' "$@")"
        mkdir -p "$DATADIR"
        find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
        exec gosu mysql "$BASH_SOURCE" "$@"
fi

if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
        # still need to check config, container may have started with --user
        _check_config "$@"
        # Get config
        DATADIR="$(_get_config 'datadir' "$@")"

        if [ ! -d "$DATADIR/mysql" ]; then
                file_env 'MYSQL_ROOT_PASSWORD'
                if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
                        echo >&2 'error: database is uninitialized and password option is not specified '
                        echo >&2 '  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
                        exit 1
                fi

                mkdir -p "$DATADIR"

                echo 'Initializing database'
                # "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
                mysql_install_db --datadir="$DATADIR" --rpm "${@:2}"
                echo 'Database initialized'

                SOCKET="$(_get_config 'socket' "$@")"
                "$@" --skip-networking --socket="${SOCKET}" &
                pid="$!"

                mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )

                for i in {60..0}; do
                        if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
                                break
                        fi
                        echo 'MySQL init process in progress...'
                        sleep 1
                done
                if [ "$i" = 0 ]; then
                        echo >&2 'MySQL init process failed.'
                        exit 1
                fi

                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
                fi

                if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
                        export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
                        echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
                fi

                rootCreate=
                # default root to listen for connections from anywhere
                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;

						DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
						SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
						GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
						${rootCreate}
						DROP DATABASE IF EXISTS test ;
						FLUSH PRIVILEGES ;
					EOSQL

                if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
                        mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
                fi

                file_env 'MYSQL_DATABASE'
                if [ "$MYSQL_DATABASE" ]; then
                        echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
                        mysql+=( "$MYSQL_DATABASE" )
                fi

                file_env 'MYSQL_USER'
                file_env 'MYSQL_PASSWORD'
                if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
                        echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"

                        if [ "$MYSQL_DATABASE" ]; then
                                echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
                        fi
                fi

                echo
                for f in /docker-entrypoint-initdb.d/*; do
                        case "$f" in
                                *.sh)     echo "$0: running $f"; . "$f" ;;
                                *.sql)    echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
                                *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
                                *)        echo "$0: ignoring $f" ;;
                        esac
                        echo
                done

                if ! kill -s TERM "$pid" || ! wait "$pid"; then
                        echo >&2 'MySQL init process failed.'
                        exit 1
                fi

                echo
                echo 'MySQL init process done. Ready for start up.'
                echo
        fi
fi

exec "$@"