From 97a7a5617560b8c1d280a610735fae5c880da4f1 Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Fri, 5 Jun 2015 23:35:22 +0200 Subject: [PATCH] New assemble and run scripts with Django support --- .sti/bin/assemble | 87 ++++++++++++++++++--------------- .sti/bin/run | 119 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 144 insertions(+), 62 deletions(-) diff --git a/.sti/bin/assemble b/.sti/bin/assemble index c50bdab7..a2f06e7c 100755 --- a/.sti/bin/assemble +++ b/.sti/bin/assemble @@ -1,52 +1,63 @@ #!/bin/bash -# For SCL enablement -source .bashrc +# This script uses these environment variables: +# +# DISABLE_COLLECTSTATIC: if not empty, inhibits execution of 'manage.py collectstatic'. -set -e +function assemble() { + # For SCL enablement + source .bashrc -echo "---> Copying application source ..." -cp -Rf /tmp/src/* ./ + set -e -if [ -f setup.py ]; then - echo "---> Installing application ..." - python setup.py install --user -elif [ -f requirements.txt ]; then - echo "---> Installing dependencies ..." - pip install --user -r requirements.txt -fi + echo "---> Copying application source ..." + cp -Rf /tmp/src/* ./ -# set permissions for any installed artifacts -chmod -R og+rwx /opt/openshift + if [ -f setup.py ]; then + echo "---> Installing application ..." + python setup.py install --user + elif [ -f requirements.txt ]; then + echo "---> Installing dependencies ..." + pip install --user -r requirements.txt + fi + + # set permissions for any installed artifacts + chmod -R og+rwx /opt/openshift + set +e + django_collectstatic + set -e -# Support for Django + # remove pip temporary directory + rm -rf /tmp/pip_build_default +} -# Take shallowest manage.py script -MANAGE_FILE=$(find . -maxdepth 3 -type f -name 'manage.py' -printf '%d\t%P\n' | sort -nk1 | cut -f2 | head -1) +function django_collectstatic() { + [ -n "$DISABLE_COLLECTSTATIC" ] && return + ! pip show -q django && return -if pip show -q django && [ -f "$MANAGE_FILE" ]; then - set +e + # Find shallowest manage.py script, either ./manage.py or /manage.py + local MANAGE_FILE=$(find . -maxdepth 2 -type f -name 'manage.py' -printf '%d\t%P\n' | sort -nk1 | cut -f2 | head -1) - # Check if collectstatic can be run. - python $MANAGE_FILE collectstatic --dry-run --noinput &> /dev/null && RUN_COLLECTSTATIC=true - - # Collect assets if settings seems okay. - if [ "$RUN_COLLECTSTATIC" ]; then - echo "---> Collecting static assets ..." - python $MANAGE_FILE collectstatic --noinput 2>&1 | sed '/^Copying/d;/^$/d;/^ /d' - - [ $? -ne 0 ] && { - echo "ERROR: 'manage.py collectstatic' failed. See the build logs for more info." - exit 1 - } || true - else - echo "WARNING: 'manage.py collectstatic' ignored. To debug, run:" - echo " $ python $MANAGE_FILE collectstatic --noinput" - echo "Ignore this warning if you're not serving static files with Django." + if [ ! -f "$MANAGE_FILE" ]; then + echo "WARNING: seems that you're using Django, but we could not find a 'manage.py' file." + echo "'manage.py collectstatic' ignored." + return fi -fi + echo "---> Collecting Django static files ..." + if ! python $MANAGE_FILE collectstatic --dry-run --noinput &> /dev/null; then + echo "WARNING: could not run 'manage.py collectstatic'. To debug, run:" + echo " $ python $MANAGE_FILE collectstatic --noinput" + echo "Ignore this warning if you're not serving static files with Django." + return + fi + + if ! python $MANAGE_FILE collectstatic --noinput 2>&1 | sed '/^Copying/d;/^$/d;/^ /d'; then + local status=$? + echo "ERROR: 'manage.py collectstatic' failed." + return $status + fi +} -# remove pip temporary directory -rm -rf /tmp/pip_build_default +assemble diff --git a/.sti/bin/run b/.sti/bin/run index 88a2c415..960a3f08 100755 --- a/.sti/bin/run +++ b/.sti/bin/run @@ -1,38 +1,109 @@ #!/bin/bash -function is_gunicorn_installed() { - pip show gunicorn +# This script uses these environment variables: +# +# APP_MODULE: Python dotted path to your WSGI application. +# If not provided, tries to find the Python path to a 'wsgi.py' file +# in the source tree. +# That file is present in Django projects by default. +# APP_CONFIG: Optional configuration file for gunicorn. +# APP_FILE: Optional path to Python script to run your application. +# Defaults to 'app.py' if it exists. +# +# DISABLE_MIGRATE: if not empty, inhibits execution of 'manage.py migrate'. + +BIND_ADDR="0.0.0.0:8080" + +function run() { + # For SCL enablement + source .bashrc + + set -e + + # Try to run application with the strategies below, in precedence order. + # The first successful strategy takes over this script's process via exec. + # If no strategy succeed, report an error message and terminate. + run_django + run_gunicorn "$APP_MODULE" + run_python_script "${APP_FILE:-app.py}" + + echo "ERROR: don't know how to run your application." + echo "Please set either APP_MODULE or APP_FILE environment variables," + echo "or create a file 'app.py' to launch your application." + return 1 } -# For SCL enablement -source .bashrc +function run_django() { + ! pip show -q django && return -set -e + # Find shallowest manage.py script, either ./manage.py or /manage.py + local MANAGE_FILE=$(find . -maxdepth 2 -type f -name 'manage.py' -printf '%d\t%P\n' | sort -nk1 | cut -f2 | head -1) + django_migrate "$MANAGE_FILE" -# Support for Django + # try to use gunicorn + run_gunicorn "$APP_MODULE" + # or fallback to Django's development server + django_runserver "$MANAGE_FILE" +} -# Take shallowest manage.py script -MANAGE_FILE=$(find . -maxdepth 3 -type f -name 'manage.py' -printf '%d\t%P\n' | sort -nk1 | cut -f2 | head -1) +function django_migrate() { + [ -n "$DISABLE_MIGRATE" ] && return + echo "---> Migrating database ..." + django_manage_cmd "$1" migrate --noinput +} -if pip show -q django && [ -f "$MANAGE_FILE" ]; then - set -x - python $MANAGE_FILE migrate --noinput - set +x -fi +function django_runserver() { + echo "---> Serving application with 'manage.py runserver' ..." + echo "---> WARNING: this is NOT a recommended way to run you application in production!" + django_manage_cmd "$1" runserver "$BIND_ADDR" +} +function django_manage_cmd() { + local MANAGE_FILE="$1" + local CMD="${@:2}" -export APP_FILE=${APP_FILE:-"app.py"} + if [ ! -f "$MANAGE_FILE" ]; then + echo "WARNING: seems that you're using Django, but we could not find a 'manage.py' file." + echo "'manage.py $CMD' ignored." + return + fi + + if [[ "$CMD" =~ ^runserver ]]; then + exec python "$MANAGE_FILE" $CMD + else + python "$MANAGE_FILE" $CMD + fi +} -if [[ ! -v APP_MODULE && -f setup.py ]]; then - APP_MODULE=`python setup.py --name`":application" -fi +function run_gunicorn() { + ! pip show -q gunicorn && return + + local APP_MODULE="$1" + + if [ -z "$APP_MODULE" ]; then + # Find shallowest wsgi.py file, one of ./wsgi.py, /wsgi.py or //wsgi.py, + # replace "/" with "." and remove ".py" suffix + APP_MODULE=$(find . -maxdepth 3 -type f -name 'wsgi.py' -printf '%d\t%P\n' | sort -nk1 | cut -f2 | head -1 | sed 's:/:.:;s:.py$::') + fi + + if [ -z "$APP_MODULE" ]; then + echo "WARNING: seems that you're trying to use gunicorn, but no WSGI application module was specified." + return + fi + + echo "---> Serving application with gunicorn ..." + exec gunicorn "$APP_MODULE" --bind="$BIND_ADDR" --access-logfile=- --config "$APP_CONFIG" +} + +function run_python_script() { + local APP_FILE="$1" + + [ ! -f "$APP_FILE" ] && return + + echo "---> Running application from Python script ..." + exec python -u "$APP_FILE" +} -if is_gunicorn_installed && [[ -v APP_MODULE ]]; then - if [[ -v APP_CONFIG ]]; then - export CONFIG="--config ${APP_CONFIG}" - fi - exec gunicorn ${APP_MODULE} --bind=:8080 ${CONFIG} -fi -exec python -u ${APP_FILE} +run