--- a +++ b/tests/support/mssql/entrypoint.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -euo pipefail + +if [ "$1" = '/opt/mssql/bin/sqlservr' ]; then + # If this is the container's first run, initialize the application + # database + if [ ! -f /tmp/app-initialized ]; then + # Initialize the application database asynchronously in a + # background process. This allows a) the SQL Server process to be + # the main process in the container, which allows graceful + # shutdown and other goodies, and b) us to only start the SQL + # Server process once, as opposed to starting, stopping, then + # starting it again. + function initialize_app_database() { + timeout=20 + limit="$((SECONDS + timeout))" + + # MSSQL doesn't apply the default collation specified in the + # MSSQL_COLLATION environment variable immediately on startup. So we + # need to wait for this to be applied before we create our application + # databases, otherwise we have a race-condition. We check the collation + # of "tempdb" as that's the system database whose collation affects us. + until [[ "$(get_tempdb_collation)" == "$MSSQL_COLLATION" ]]; do + sleep 1s + if [[ "${SECONDS}" -gt "${limit}" ]]; then + echo >&2 "Failed to connect to MSSQL and confirm collation setting after ${timeout} seconds" + echo >&2 "Expected collation: $MSSQL_COLLATION" + echo >&2 "Got: $(get_tempdb_collation)" + exit 1 + fi + done + + # Run the setup script to create the DB and the schema in the DB + _sqlcmd -i /mssql/setup.sql + + # Note that the container has been initialized so future + # starts won't wipe changes to the data + touch /tmp/app-initialized + } + + function get_tempdb_collation() { + # We need to set NOCOUNT so we don't get a "Rows affected" count in the output + _sqlcmd -Q "SET NOCOUNT ON; SELECT DATABASEPROPERTYEX('tempdb', 'Collation');" + } + + function _sqlcmd() { + # Extra arguments: + # -C : trust server certificate + # -b : exit with 1 on error rather than 0 + # -h -1 : no headers in output + # -W : trim trailing whitespace + /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -d master \ + -C -b -h -1 -W \ + "$@" + } + + initialize_app_database & + fi +fi + +# The Docker library we're using hides stdout from us if the container exits with an error, so send everything to +# stderr. +exec "$@" 1>&2