mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
a55f276965
Run gunicorn with the native asgi worker against config.asgi so SSE streams are parked on the event loop instead of holding a sync worker per open connection; sync CRUD views keep running in the thread-sensitive executor. Disable preload under DEBUG so dev reload picks up edited code, and point the dev and prod entrypoints at the ASGI application.
109 lines
3.2 KiB
Bash
Executable File
109 lines
3.2 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
|
|
apply_migrations() {
|
|
echo "Applying database migrations..."
|
|
|
|
# Fix Inconsistent migration history after adding sites app
|
|
uv run python manage.py check_and_fix_socialaccount_sites_migration --database admin
|
|
|
|
uv run python manage.py migrate --database admin
|
|
}
|
|
|
|
apply_fixtures() {
|
|
echo "Applying Django fixtures..."
|
|
for fixture in api/fixtures/dev/*.json; do
|
|
if [ -f "$fixture" ]; then
|
|
echo "Loading $fixture"
|
|
uv run python manage.py loaddata "$fixture" --database admin
|
|
fi
|
|
done
|
|
}
|
|
|
|
start_dev_server() {
|
|
echo "Starting the development server (Gunicorn ASGI, debug + reload)..."
|
|
# Same server/worker as prod (config.asgi via the native `asgi` worker), so
|
|
# SSE streams run on the event loop exactly as they do in production. DEBUG is
|
|
# on so guniconf's `reload = DEBUG` hot-reloads edited code (and flips
|
|
# `preload_app` off so reload actually takes).
|
|
export DJANGO_DEBUG="${DJANGO_DEBUG:-True}"
|
|
export DJANGO_BIND_ADDRESS="${DJANGO_BIND_ADDRESS:-0.0.0.0}"
|
|
exec uv run gunicorn -c config/guniconf.py config.asgi:application
|
|
}
|
|
|
|
start_prod_server() {
|
|
echo "Starting the Gunicorn server..."
|
|
exec uv run gunicorn -c config/guniconf.py config.asgi:application
|
|
}
|
|
|
|
resolve_worker_hostname() {
|
|
TASK_ID=""
|
|
|
|
if [ -n "$ECS_CONTAINER_METADATA_URI_V4" ]; then
|
|
TASK_ID=$(wget -qO- --timeout=2 "${ECS_CONTAINER_METADATA_URI_V4}/task" | \
|
|
python3 -c "import sys,json; print(json.load(sys.stdin)['TaskARN'].split('/')[-1])" 2>/dev/null)
|
|
fi
|
|
|
|
if [ -z "$TASK_ID" ]; then
|
|
TASK_ID=$(python3 -c "import uuid; print(uuid.uuid4().hex)")
|
|
fi
|
|
|
|
echo "${TASK_ID}@$(hostname)"
|
|
}
|
|
|
|
start_worker() {
|
|
echo "Starting the worker..."
|
|
exec uv run python -m celery -A config.celery worker \
|
|
-n "$(resolve_worker_hostname)" \
|
|
-l "${DJANGO_LOGGING_LEVEL:-info}" \
|
|
-Q celery,scans,scan-reports,deletion,backfill,overview,integrations,compliance,attack-paths-scans \
|
|
-E --max-tasks-per-child 1
|
|
}
|
|
|
|
start_worker_beat() {
|
|
echo "Starting the worker-beat..."
|
|
exec uv run python -m celery -A config.celery beat -l "${DJANGO_LOGGING_LEVEL:-info}" --scheduler django_celery_beat.schedulers:DatabaseScheduler
|
|
}
|
|
|
|
manage_db_partitions() {
|
|
if [ "${DJANGO_MANAGE_DB_PARTITIONS}" = "True" ]; then
|
|
echo "Managing DB partitions..."
|
|
# For now we skip the deletion of partitions until we define the data retention policy
|
|
# --yes auto approves the operation without the need of an interactive terminal
|
|
uv run python manage.py pgpartition --using admin --skip-delete --yes
|
|
fi
|
|
}
|
|
|
|
# Identify this process to Postgres (application_name=<component>:<alias>) so
|
|
# connections are attributable by component in pg_stat_activity. Web tiers
|
|
# report "api"; everything else uses the launch subcommand.
|
|
case "$1" in
|
|
prod|dev) DJANGO_APP_COMPONENT="api" ;;
|
|
*) DJANGO_APP_COMPONENT="$1" ;;
|
|
esac
|
|
export DJANGO_APP_COMPONENT
|
|
|
|
case "$1" in
|
|
dev)
|
|
apply_migrations
|
|
apply_fixtures
|
|
manage_db_partitions
|
|
start_dev_server
|
|
;;
|
|
prod)
|
|
apply_migrations
|
|
manage_db_partitions
|
|
start_prod_server
|
|
;;
|
|
worker)
|
|
start_worker
|
|
;;
|
|
beat)
|
|
start_worker_beat
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {dev|prod|worker|beat}"
|
|
exit 1
|
|
;;
|
|
esac
|