Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=password
DATABASE_NAME=specify

# This allows for a destructive reset of the database if it is not empty but contains no legacy Specify schema.
# For production environments, it is recommended to set this to false to prevent accidental data loss.
ALLOW_DB_RESET=false
Comment thread
grantfitzsimmons marked this conversation as resolved.

# The following are database users with specific roles and privileges.
# If the migrator and app user are not defined, the system will use the master user credentials.
# See documenation https://discourse.specifysoftware.org/t/new-blank-database-creation-database-user-levels/3023
Expand Down
3 changes: 0 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ services:
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${DATABASE_NAME}
- MYSQL_USER=${MASTER_NAME}
- MYSQL_PASSWORD=${MASTER_PASSWORD}

specify7:
container_name: specify7
Expand All @@ -35,7 +33,6 @@ services:
target: run-development
command: ve/bin/python manage.py runserver 0.0.0.0:8000
init: true
restart: unless-stopped
depends_on:
# It seems like there was a race condition on the the
# webpack-output volume. I suspect if this container mounts it
Expand Down
14 changes: 8 additions & 6 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ if [ "$1" = 've/bin/gunicorn' ] || [ "$1" = 've/bin/python' ]; then
rsync -a --delete specifyweb/frontend/static/ /volumes/static-files/frontend-static
cd /opt/specify7
echo "Applying Django migrations."
set +e
./sp7_db_setup_check.sh # Setup db users and run mirgations
# ve/bin/python manage.py base_specify_migration
# ve/bin/python manage.py migrate
ve/bin/python manage.py run_key_migration_functions # Uncomment if you want the key migration functions to run on startup.
set -e
if ./sp7_db_setup_check.sh; then
# sp7_db_setup_check.sh intentionally runs manage.py base_specify_migration and manage.py migrate;
# only manage.py run_key_migration_functions is invoked here afterward.
ve/bin/python manage.py run_key_migration_functions # Runs after sp7_db_setup_check.sh succeeds.
else
echo "Database setup failed; skipping startup migrations."
exit 1
Comment thread
grantfitzsimmons marked this conversation as resolved.
fi
fi
exec "$@"
45 changes: 43 additions & 2 deletions sp7_db_setup_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ fi
DB_EXISTS=$(mariadb -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \
-sse "SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = '$DB_NAME';")

LEGACY_SCHEMA_EXISTS=0
if [[ "$DB_EXISTS" -ne 0 ]]; then
LEGACY_SCHEMA_EXISTS=$(mariadb -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \
-sse "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME' AND table_name = 'specifyuser';")
fi
Comment thread
grantfitzsimmons marked this conversation as resolved.
Comment thread
grantfitzsimmons marked this conversation as resolved.

if [[ "$DB_EXISTS" -eq 0 ]]; then
echo "Creating database '$DB_NAME'..."
echo "Executing: mariadb -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"<hidden>\" -e \"CREATE DATABASE \`$DB_NAME\`;\""
Expand All @@ -134,6 +140,41 @@ if [[ "$DB_EXISTS" -eq 0 ]]; then
echo "Error: Failed to create database."
exit 1
fi
elif [[ "$LEGACY_SCHEMA_EXISTS" -eq 0 ]]; then
echo "Database '$DB_NAME' exists but does not contain a Specify schema."

# Check whether the database is truly empty. If it is empty, proceed with initial setup.
# If it's non-empty, require explicit opt-in via ALLOW_DB_RESET=true to perform a destructive reset.
if ! DB_TABLE_COUNT=$(mariadb -N -B -h "$DB_HOST" -P "$DB_PORT" \
-u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \
-sse "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';"); then
echo "Error: Failed to count tables in '$DB_NAME'."
exit 1
fi
if [[ -z "$DB_TABLE_COUNT" ]]; then
echo "Error: Empty response when counting tables in '$DB_NAME'."
exit 1
fi

if [[ "$DB_TABLE_COUNT" -eq 0 ]]; then
echo "Database '$DB_NAME' is empty; proceeding with initial setup."
NEW_DATABASE_CREATED=1
else
if [[ "${ALLOW_DB_RESET:-}" == "true" ]]; then
echo "Resetting non-empty database '$DB_NAME' because ALLOW_DB_RESET=true was set."
if ! mariadb -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \
-e "DROP DATABASE \`$DB_NAME\`; CREATE DATABASE \`$DB_NAME\`;"; then
echo "Error: Failed to reset database."
exit 1
fi
NEW_DATABASE_CREATED=1
else
echo "Error: Database '$DB_NAME' exists but lacks the Specify schema and is not empty."
echo "If you want to allow a destructive reset, set ALLOW_DB_RESET=true in your environment before starting."
echo "Otherwise restore a proper Specify database or delete the database entirely to start fresh."
exit 1
fi
fi
else
echo "Database '$DB_NAME' already exists."
fi
Expand Down Expand Up @@ -423,11 +464,11 @@ echo "New app user created: $([[ "$NEW_APP_USER_CREATED" -eq 1 ]] && echo True |
echo "--------------------------------------------------"

# Run the base_specify_migration script
if [[ "$NEW_DATABASE_CREATED" -eq 0 ]]; then
if [[ "$LEGACY_SCHEMA_EXISTS" -eq 1 ]]; then
echo "Existing database detected."
ve/bin/python manage.py base_specify_migration --use-override --database=${MIGRATION_DB_ALIAS}
else
echo "New database detected."
echo "Blank or newly created database detected."
ve/bin/python manage.py base_specify_migration --database=${MIGRATION_DB_ALIAS}
fi

Expand Down
Loading