diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..2483de9144 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git/ +.tox/ +askbot.egg-info/ +dist/ +build/ + diff --git a/Dockerfile b/Dockerfile index 725d21acbf..87c9cbf248 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,3 @@ -# -# WARNING: this Docker file is not tested with the current askbot-setup script. -# most likely at least this file will need to be adapted to make it work. -# if you can help - please make explain what you want to do in the issues -# section of the repository and once your contribution is accepted - make a pull request. -# -#---------------------------------------------------- # This Dockerifle builds a simple Askbot installation # # It makes use of environment variables: @@ -17,49 +10,166 @@ # # Start with something like # -# docker run -e 'DATABASE_URL=sqlite:////askbot-site/askbot.db' -e "SECRET_KEY=$(openssl rand 14 | base64)" -e ADMIN_PASSWORD=admin -p 8080:80 askbot/askbot:latest +# docker run -e 'DATABASE_URL=sqlite:////askbot_site/askbot.sqlite' -e "SECRET_KEY=$(openssl rand 14 | base64)" -e ADMIN_PASSWORD=admin -p 8080:8000 askbot/askbot:latest # -# User uploads are stored in **/askbot_site/askbot/upfiles** . I'd recommend to make it a kubernetes volume. +# User uploads are stored in **/askbot_site/upfiles** . I'd recommend to make it a kubernetes volume. +# Static files are stored in **/askbot_site/static** . I'd recommend to make it a kubernetes volume. + +# Stage 0 +FROM tiangolo/uwsgi-nginx:python3.8-alpine + +ARG HTTP_PROXY= +ARG HTTPS_PROXY= + +ENV http_proxy $HTTP_PROXY +ENV https_proxy $HTTPS_PROXY +ENV no_proxy "" + +RUN apk add --update --no-cache git py3-cffi \ + gcc g++ git make mkinitfs kmod mtools squashfs-tools py3-cffi \ + libffi-dev linux-headers musl-dev libc-dev openssl-dev \ + python3-dev zlib-dev libxml2-dev libxslt-dev jpeg-dev \ + postgresql-dev zlib jpeg libxml2 libxslt postgresql-libs \ + hiredis \ + && python -m pip install --upgrade pip \ + && pip install psycopg2 + +COPY ${ASKBOT}/askbot/__init__.py /askbot_meta.py +WORKDIR / +RUN pip install virtualenv \ + && pip install setuptools \ + && pip install wheel \ + && python3 -c "from askbot_meta import REQUIREMENTS; _=[print(r) for r in REQUIREMENTS.values()];" >requirements.txt \ + && pip install -r requirements.txt + +COPY ${ASKBOT}/askbot /usr/local/src/askbot/askbot +COPY ${ASKBOT}/AUTHORS ${ASKBOT}/COPYING ${ASKBOT}/LICENSE ${ASKBOT}/setup.py ${ASKBOT}/ez_setup.py ${ASKBOT}/askbot_requirements.txt ${ASKBOT}/MANIFEST.in /usr/local/src/askbot/ +RUN cd /usr/local/src/askbot \ + && python3 setup.py bdist_wheel \ + && cp /usr/local/src/askbot/dist/askbot*.whl / \ + && cp /usr/local/src/askbot/askbot_requirements.txt / -FROM tiangolo/uwsgi-nginx:python3.6-alpine3.9 +RUN pip install /askbot*.whl \ + && find /root/.cache -name "*.whl" -exec cp {} / \; \ + && ls /*.whl + + +# Stage 1 +FROM tiangolo/uwsgi-nginx:python3.8-alpine ARG SITE=askbot-site +ARG APP=askbot_app ARG ASKBOT=. +ARG HTTP_PROXY= +ARG HTTPS_PROXY= +ARG CACHE_PASSWORD + ENV PYTHONUNBUFFERED 1 ENV ASKBOT_SITE /${SITE} +ENV ASKBOT_APP ${APP} +ENV ASKBOT_CACHE locmem +ENV CACHE_NODES "" +ENV NO_CRON yes +ENV ADMIN_PASSWORD admin +ENV SECRET_KEY 0123456789abcdef +ENV DATABASE_URL "sqlite:///${ASKBOT_SITE}/askbot.sqlite" +ENV DJANGO_SETTINGS_MODULE ${ASKBOT_APP}.settings +ENV http_proxy $HTTP_PROXY +ENV https_proxy $HTTPS_PROXY +ENV no_proxy "" -ENV UWSGI_INI /${SITE}/askbot_app/uwsgi.ini +ENV UWSGI_INI ${ASKBOT_SITE}/${ASKBOT_APP}/uwsgi.ini # Not recognized by uwsgi-nginx, yet. # The file doesn't exist either! #ENV PRE_START_PATH /${SITE}/prestart.sh -# TODO: changing this requires another cache backend +# using more than 1 process each requires redis or memcached as backend ENV NGINX_WORKER_PROCESSES 1 ENV UWSGI_PROCESSES 1 ENV UWSGI_CHEAPER 0 +ENV LISTEN_PORT 8000 -ADD askbot_requirements.txt / - -#RUN apt-get update && apt-get -y install cron git \ RUN apk add --update --no-cache git py3-cffi \ - gcc g++ git make unzip mkinitfs kmod mtools squashfs-tools py3-cffi \ - libffi-dev linux-headers musl-dev libc-dev openssl-dev \ - python3-dev zlib-dev libxml2-dev libxslt-dev jpeg-dev \ - postgresql-dev zlib jpeg libxml2 libxslt postgresql-libs \ - && python -m pip install --upgrade pip \ - && pip install -r /askbot_requirements.txt \ - && pip install psycopg2 + zlib jpeg libxml2 libxslt postgresql-libs \ + hiredis + +COPY ${ASKBOT}/askbot_requirements.txt / +COPY --from=0 /*.whl / + +RUN python -m pip install --upgrade pip \ + && pip install redis django-redis-cache simplejson \ + && pip install /*.whl && rm /*.whl \ + && rm -rf /root/.cache -ADD $ASKBOT /src -RUN cd /src/ && python setup.py install \ - && askbot-setup -n /${SITE} -e 1 -d postgres -u postgres -p askbotPW --db-host=postgres --db-port=5432 --logfile-name=stdout --no-secret-key --create-project container-uwsgi +# lets not use the Askbot installer for now. Let's do this instead: -RUN true \ - && cp /${SITE}/askbot_app/prestart.sh /app \ - && /usr/bin/crontab /${SITE}/askbot_app/crontab \ - && cd /${SITE} && SECRET_KEY=whatever DJANGO_SETTINGS_MODULE=askbot_app.settings python manage.py collectstatic --noinput +RUN pip install j2render dj-database-url \ + && mkdir -p ${ASKBOT_SITE}/log ${ASKBOT_SITE}/cron ${ASKBOT_SITE}/upfiles ${ASKBOT_SITE}/static ${ASKBOT_SITE}/askbot_app \ + && SRC_DIR=`python -c 'import os; from askbot import setup_templates; print(os.path.dirname(setup_templates.__file__))'` \ + && cp ${SRC_DIR}/celery_app.py ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/__init__.py ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/urls.py ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/django.wsgi ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/prestart.py ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/prestart.sh ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/cron-askbot.sh ${ASKBOT_SITE}/${ASKBOT_APP} \ + && cp ${SRC_DIR}/manage.py ${ASKBOT_SITE} \ + && ln -sf `realpath ${SRC_DIR}/../doc` ${ASKBOT_SITE}/doc \ + && echo "{\"askbot_app\": \"${ASKBOT_APP}\", \"askbot_site\": \"${SITE}\", \"database_engine\": \"\" , \"database_name\": \"\" , \"database_password\": \"\", \"database_user\": \"\" , \"settings_path\": \"${ASKBOT_APP}\", \"logfile_name\": \"stdout\"}" >/data.json \ + && j2render -o ${ASKBOT_SITE}/${ASKBOT_APP}/settings.py --source /data.json ${SRC_DIR}/settings.py.jinja2 \ + && j2render -o ${ASKBOT_SITE}/cron/crontab --source /data.json ${SRC_DIR}/crontab.jinja2 \ + && j2render -o ${ASKBOT_SITE}/${ASKBOT_APP}/uwsgi.ini --source /data.json ${SRC_DIR}/uwsgi.ini.jinja2 \ + && cat ${SRC_DIR}/../container/uwsgi.txt >> ${ASKBOT_SITE}/${ASKBOT_APP}/uwsgi.ini \ + && cat ${SRC_DIR}/../container/augment_settings.py >> ${ASKBOT_SITE}/${ASKBOT_APP}/settings.py +# adapt image to our needs (in order of appearance) +# * install wait to stall instances of this container until the database +# reachable +# * remove /etc/uwsgi/uwsgi.ini; we bring our own uwsgi.ini and tell the +# container in the env var UWSGI_INI about it +# * copy our prestart.sh into /app because that's where the entrypoint +# looks for it and this behaviour cannot (yet) be overwritten through +# env vars. +# * add Askbot tasks to cron +# * collect staticfiles +# * make nginx serve staticfiles directly without involving uwsgi/python +# this is a bit tricky as this image writes nginx.conf at startup time +# and takes env vars into account when doing so. In order to keep this +# mechanism, changing the nginx.conf actually means modifying the +# logic in /entrypoint.sh, which creates the nginx.conf +# * we keep unix domain sockets into /tmp, not /run +# * change owning group to gid 0 and make things group-writable +# (essential to OpenShift support and some Kubernetes deployments) +# * add the uwsgi user to group root(0) ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait -RUN chmod +x /wait +RUN chmod +x /wait \ + && rm /etc/uwsgi/uwsgi.ini \ + && sed -i "s%^\(\s*command\s*=.*\)--ini\s*/etc/uwsgi/uwsgi.ini\(.*\)$%\1\2%" /etc/supervisor.d/supervisord.ini \ + && cp ${ASKBOT_SITE}/${ASKBOT_APP}/prestart.sh /app \ + && /usr/bin/crontab ${ASKBOT_SITE}/cron/crontab \ + && cd ${ASKBOT_SITE} \ + && SECRET_KEY=whatever \ + ASKBOT_CACHE=locmem python manage.py collectstatic --noinput \ + && cd ${ASKBOT_SITE}/${ASKBOT_APP} \ + && STATIC_URL=`SECRET_KEY=whatever python -c 'import settings;print(settings.STATIC_URL)'` \ + && STATIC_ROOT=`SECRET_KEY=whatever python -c 'import settings;print(settings.STATIC_ROOT)'` \ + && MEDIA_URL=`SECRET_KEY=whatever python -c 'import settings;print(settings.MEDIA_URL)'` \ + && MEDIA_ROOT=`SECRET_KEY=whatever python -c 'import settings;print(settings.MEDIA_ROOT)'` \ + && sed -i "/content_server.*USE_LISTEN_PORT/a content_server=\$content_server\" location ${STATIC_URL} { alias ${STATIC_ROOT}/; }\n\"" /entrypoint.sh \ + && sed -i "/content_server.*USE_LISTEN_PORT/a content_server=\$content_server\" location ${MEDIA_URL} { alias ${MEDIA_ROOT}/; }\n\"" /entrypoint.sh \ + && sed -i 's%/run/supervisord.sock%/tmp/supervisor.sock%g' /etc/supervisord.conf \ + && for i in ${ASKBOT_SITE} /etc/nginx /var/log /var/cache /run; do\ + mkdir -p $i; chown -Rh :0 $i && chmod -R g+w $i; done \ + && sed -i '/^chown-socket/d' ${ASKBOT_SITE}/${ASKBOT_APP}/uwsgi.ini \ + && sed -i 's/^chmod-socket.*/chmod-socket = 666/' ${ASKBOT_SITE}/${ASKBOT_APP}/uwsgi.ini \ + && chmod 660 /etc/supervisord.conf \ + && sed -i 's/0:root/0:root,uwsgi/' /etc/group + +RUN apk add --update --no-cache dos2unix \ + && dos2unix ${ASKBOT_SITE}/${ASKBOT_APP}/* ${ASKBOT_SITE}/* /app/* /etc/supervisord.conf /etc/supervisor.d/* /etc/nginx/* + +USER uwsgi -WORKDIR /${SITE} +VOLUME ["${ASKBOT_SITE}/static", "${ASKBOT_SITE}/upfiles"] +EXPOSE ${LISTEN_PORT} +WORKDIR ${ASKBOT_SITE} diff --git a/askbot/container/Dockerfile.redis b/askbot/container/Dockerfile.redis deleted file mode 100644 index 07cc086ba4..0000000000 --- a/askbot/container/Dockerfile.redis +++ /dev/null @@ -1,64 +0,0 @@ -# This Dockerifle builds a simple Askbot installation -# -# It makes use of environment variables: -# 1. DATABASE_URL See https://github.com/kennethreitz/dj-database-url for details -# 2. SECRET_KEY for making hashes within Django. -# 3. ADMIN_PASSWORD used for creating a user named "admin" -# 4. NO_CRON set this to "yes" to disable the embedded cron job. -# -# Make sure to *+always* start the container with the same SECRET_KEY. -# -# Start with something like -# -# docker run -e 'DATABASE_URL=sqlite:////askbot_site/askbot.db' -e "SECRET_KEY=$(openssl rand 14 | base64)" -e ADMIN_PASSWORD=admin -p 8080:80 askbot/askbot:latest -# -# User uploads are stored in **/askbot_site/askbot/upfiles** . I'd recommend to make it a kubernetes volume. - -FROM tiangolo/uwsgi-nginx:python3.6-alpine3.9 - -ARG SITE=askbot-site -ARG ASKBOT=. -ENV PYTHONUNBUFFERED 1 -ENV ASKBOT_SITE /${SITE} - -ENV UWSGI_INI /${SITE}/askbot_app/uwsgi.ini -# Not recognized by uwsgi-nginx, yet. -# The file doesn't exist either! -#ENV PRE_START_PATH /${SITE}/prestart.sh - -# TODO: changing this requires another cache backend -ENV NGINX_WORKER_PROCESSES 4 -ENV UWSGI_PROCESSES 4 -ENV UWSGI_CHEAPER 0 - -ADD askbot_requirements.txt / - -#RUN apt-get update && apt-get -y install cron git \ -RUN apk add --update --no-cache git py3-cffi \ - gcc g++ git make unzip mkinitfs kmod mtools squashfs-tools py3-cffi \ - libffi-dev linux-headers musl-dev libc-dev openssl-dev \ - python3-dev zlib-dev libxml2-dev libxslt-dev jpeg-dev \ - postgresql-dev zlib jpeg libxml2 libxslt postgresql-libs \ - hiredis \ - && python -m pip install --upgrade pip \ - && pip install -r /askbot_requirements.txt \ - && pip install psycopg2 \ - && pip install redis django-redis-cache - -RUN pip install requests-oauthlib - -ADD $ASKBOT /src -RUN cd /src/ && python setup.py install \ - && askbot-setup -n /${SITE} --logfile-name=stdout --no-secret-key --create-project container-uwsgi \ - -e 1 -d postgres -u postgres -p askbotPW --db-host=postgres --db-port=5432 \ - --cache-engine redis --cache-node redis:6379 --cache-db 1 - -RUN true \ - && cp /${SITE}/askbot_app/prestart.sh /app \ - && /usr/bin/crontab /${SITE}/askbot_app/crontab \ - && cd /${SITE} && SECRET_KEY=whatever DJANGO_SETTINGS_MODULE=askbot_app.settings ASKBOT_CACHE=locmem python manage.py collectstatic --noinput - -ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait -RUN chmod +x /wait - -WORKDIR /${SITE} diff --git a/askbot/container/augment_settings.py b/askbot/container/augment_settings.py new file mode 100644 index 0000000000..bc39c325b5 --- /dev/null +++ b/askbot/container/augment_settings.py @@ -0,0 +1,44 @@ +# This requires the following environment variables to be set: +# * DATABASE_URL +# * SECRET_KEY +# * CACHE_NODES (,-separated list) +# The following environment variables are optional: +# * CACHE_DB (defaults to 1) +# * CACHE_PASSWORD (defaults to none) + +MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'upfiles') +TIME_ZONE = 'Europe/Berlin' + +import dj_database_url + +db_url = os.environ.get('DATABASE_URL') + +if db_url is not None and len(db_url.strip()) > 0: + DATABASES['default'] = dj_database_url.parse(db_url) + DATABASES['default'].update({ 'TEST': { + 'CHARSET': 'utf8', # Setting the character set and collation to utf-8 + }}) + +SECRET_KEY = os.environ['SECRET_KEY'] + +CACHES['locmem'] = CACHES['default'] +CACHES['redis'] = { + 'BACKEND': 'redis_cache.RedisCache', + 'LOCATION': os.environ['CACHE_NODES'].split(','), + 'OPTIONS': { + 'DB': os.environ.get('CACHE_DB', 1), + 'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool', + 'CONNECTION_POOL_CLASS_KWARGS': { + 'max_connections': 50, + 'timeout': 20, + }, + 'MAX_CONNECTIONS': 1000, + 'PICKLE_VERSION': -1, + }, +} + +cache_select = os.environ.get('ASKBOT_CACHE', 'locmem') +CACHES['default'] = CACHES[cache_select] + +if 'CACHE_PASSWORD' in os.environ and 'OPTIONS' in CACHES['default']: + CACHES['default']['OPTIONS']['PASSWORD'] = os.environ['CACHE_PASSWORD'] diff --git a/askbot/container/cron-askbot.sh b/askbot/container/cron-askbot.sh deleted file mode 100755 index cac229692c..0000000000 --- a/askbot/container/cron-askbot.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -export $(cat /cron_environ | xargs) -cd ${ASKBOT_SITE:-/askbot-site} -/usr/local/bin/python manage.py send_email_alerts > /proc/1/fd/1 2>/proc/1/fd/2 diff --git a/askbot/container/crontab b/askbot/container/crontab deleted file mode 100644 index b503a37b65..0000000000 --- a/askbot/container/crontab +++ /dev/null @@ -1 +0,0 @@ -0 * * * * /{{ askbot_site }}/{{ askbot_app }}/cron-askbot.sh diff --git a/askbot/container/prestart.py b/askbot/container/prestart.py deleted file mode 100644 index 631380b6d2..0000000000 --- a/askbot/container/prestart.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -import os -import sys - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'askbot_app.settings') - -project_dir = os.environ.get('ASKBOT_SITE') -os.chdir(project_dir) -if project_dir not in sys.path: - sys.path = [ '', project_dir ] + sys.path[1:] - -import askbot as _test_import_of_askbot - -dsn = os.environ.get('DATABASE_URL', None) -admin_to_be_id = 1 - -do_migrate = True -do_admin = True -do_make_admin = True -do_uwsgi_ini = True - -from time import sleep - -if dsn is not None and dsn.startswith('postgres'): - import psycopg2 - print(f'Waiting for database {dsn}') - for retry in range(1,10): - try: - d = psycopg2.connect(dsn) # i hope this takes its time ... - except psycopg2.OperationalError as e: # DB not ready - print(e) - print('Database connected. Peeking...') - c = d.cursor() - c.execute("SELECT * FROM information_schema.tables WHERE table_name='askbot_post';") - r = c.fetchone() - if r is not None: - print('Will not migrate') - do_migrate = False - d.rollback() - try: - c.execute("SELECT * FROM auth_user WHERE username='admin'") - r = c.fetchone() - if r is not None: - print('Will not create admin user') - do_admin = False - except psycopg2.errors.UndefinedTable: - pass - d.rollback() - try: - c.execute(f"SELECT 1 FROM auth_user WHERE id='{admin_to_be_id}' AND is_superuser='yes';") - r = c.fetchone() - if r is not None: - print('Will not make user admin superuser') - do_make_admin = False - except psycopg2.errors.UndefinedTable: - pass - c.close() - d.close() - -from django.core.management import execute_from_command_line - -if do_migrate is True : - print('Running migrate') - argv = [ 'manage.py', 'migrate', '--no-input' ] - execute_from_command_line(argv) - -if do_admin is True and os.environ.get('ADMIN_PASSWORD') is not None: - print('Adding admin user') - argv = [ 'manage.py', 'askbot_add_user', - '--user-name', 'admin', - '--email', 'admin@localhost', - '--password', os.environ.get('ADMIN_PASSWORD'), - '--status', 'd' ] - execute_from_command_line(argv) - -if do_make_admin is True: - print('Grant superuser to admin') - argv = [ 'manage.py', 'add_admin', str(admin_to_be_id), '--noinput' ] - execute_from_command_line(argv) - -if do_uwsgi_ini is True: - print('Preparing uwsgi.ini') - with open(os.path.join(project_dir,'askbot_app','uwsgi.ini'), 'a') as ini: - ini.write("\n") - for rule in [ f'pythonpath = {p}' for p in sys.path]: - ini.write(rule + "\n") - -if os.environ.get('NO_CRON') is None: - print('Preparing cron_environ') - with open('/cron_environ', 'w+') as cron_env: - for var in [ f'{name}="{os.environ.get(name)}"' - for name in [ 'PATH', 'DATABASE_URL', 'SECRET_KEY', - 'PYTHONUNBUFFERED', 'ASKBOT_SITE' ]]: - cron_env.write(var + "\n") - cron_env.write("PYTHONPATH='{}'\n".format(str.join(":", sys.argv))) diff --git a/askbot/container/prestart.sh b/askbot/container/prestart.sh deleted file mode 100644 index da16d5bc5e..0000000000 --- a/askbot/container/prestart.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -if [ -x /wait ]; then /wait; else sleep 64; fi - -python ${ASKBOT_SITE}/askbot_app/prestart.py - -if [ -z "$NO_CRON" ]; then - crond || cron -fi - diff --git a/askbot/container/uwsgi.ini b/askbot/container/uwsgi.ini deleted file mode 100644 index 36bed031e8..0000000000 --- a/askbot/container/uwsgi.ini +++ /dev/null @@ -1,4 +0,0 @@ -[uwsgi] -static-map = /m=/{{ askbot_site }}/static -env = DJANGO_SETTINGS_MODULE={{ askbot_app }}.settings -wsgi-file = /{{ askbot_site }}/{{ askbot_app }}/django.wsgi diff --git a/askbot/container/uwsgi.txt b/askbot/container/uwsgi.txt new file mode 100644 index 0000000000..e9eb35e2b2 --- /dev/null +++ b/askbot/container/uwsgi.txt @@ -0,0 +1,11 @@ + +socket = /tmp/uwsgi.sock +chown-socket = nginx:nginx +chmod-socket = 664 +# Graceful shutdown on SIGTERM, see https://github.com/unbit/uwsgi/issues/849#issuecomment-118869386 +hook-master-start = unix_signal:15 gracefully_kill_them_all +need-app = true +die-on-term = true +plugin = python3 +# For debugging and testing +show-config = true diff --git a/askbot/setup_templates/prestart.py b/askbot/setup_templates/prestart.py index 631380b6d2..d2fcc9024d 100644 --- a/askbot/setup_templates/prestart.py +++ b/askbot/setup_templates/prestart.py @@ -3,9 +3,10 @@ import os import sys -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'askbot_app.settings') - project_dir = os.environ.get('ASKBOT_SITE') +app_dir = os.environ.get('ASKBOT_APP', 'askbot_app') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', f'{app_dir}.settings') + os.chdir(project_dir) if project_dir not in sys.path: sys.path = [ '', project_dir ] + sys.path[1:] @@ -81,7 +82,7 @@ if do_uwsgi_ini is True: print('Preparing uwsgi.ini') - with open(os.path.join(project_dir,'askbot_app','uwsgi.ini'), 'a') as ini: + with open(os.path.join(project_dir, app_dir, 'uwsgi.ini'), 'a') as ini: ini.write("\n") for rule in [ f'pythonpath = {p}' for p in sys.path]: ini.write(rule + "\n") diff --git a/askbot/setup_templates/prestart.sh b/askbot/setup_templates/prestart.sh index da16d5bc5e..8f6f480fc1 100644 --- a/askbot/setup_templates/prestart.sh +++ b/askbot/setup_templates/prestart.sh @@ -2,7 +2,7 @@ if [ -x /wait ]; then /wait; else sleep 64; fi -python ${ASKBOT_SITE}/askbot_app/prestart.py +python ${ASKBOT_SITE}/${ASKBOT_APP}/prestart.py if [ -z "$NO_CRON" ]; then crond || cron diff --git a/askbot/setup_templates/settings.py.jinja2 b/askbot/setup_templates/settings.py.jinja2 index 2efa5cc0ce..42b76fa051 100644 --- a/askbot/setup_templates/settings.py.jinja2 +++ b/askbot/setup_templates/settings.py.jinja2 @@ -43,10 +43,10 @@ DATABASES = { {%- endif %} } -db_url = dj_database_url.config(default='sqlite:///db.data') +db_config_dict = dj_database_url.config(default='sqlite:///' + os.path.join(PROJECT_ROOT,"askbot.sqlite")) -if db_url: - DATABASES['default'] = db_url +if len(db_config_dict): + DATABASES['default'] = db_config_dict DATABASES['default'].update({ 'TEST': { 'CHARSET': 'utf8', # Setting the character set and collation to utf-8 }}) @@ -84,7 +84,7 @@ ASKBOT_LANGUAGE_MODE = 'single-lang' #'single-lang', 'url-lang', 'user-lang' # Absolute path to the directory that holds uploaded media # Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles') +MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'upfiles') MEDIA_URL = '/upfiles/' # url to uploaded media. This is expected to start with a / STATIC_URL = '/m/'#this must be different from MEDIA_URL USE_LOCAL_FONTS = False @@ -189,7 +189,7 @@ INSTALLED_APPS = ( 'django.contrib.sessions', 'django.contrib.sitemaps', 'django.contrib.sites', - {{ staticfiles_app }} + 'django.contrib.staticfiles', ## extra packages 'avatar', @@ -212,7 +212,6 @@ CACHES = { 'locmem': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'askbot', - 'TIMEOUT': 6000, } } @@ -224,7 +223,6 @@ CACHES['redis'] = { '{{ node }}', {% endfor %} ], - 'TIMEOUT': 6000, 'OPTIONS': { 'DB': '{{ cache_db }}', {% if cache_password %} @@ -248,7 +246,6 @@ CACHES['memcached'] = { '{{ node }}', {% endfor %} ], - 'TIMEOUT': 6000, } cache_select_default = 'memcached' {% else %} @@ -259,7 +256,7 @@ CACHES['default'] = CACHES[cache_select] # Chose a unique KEY_PREFIX to avoid clashes with other applications # using the same cache (e.g. a shared memcache instance). -CACHES['default'].update({'KEY_PREFIX': 'askbot',}) +CACHES['default'].update({'KEY_PREFIX': 'askbot', 'TIMEOUT': 6000}) #sets a special timeout for livesettings if you want to make them different LIVESETTINGS_CACHE_TIMEOUT = CACHES['default']['TIMEOUT'] diff --git a/askbot/setup_templates/urls.py b/askbot/setup_templates/urls.py new file mode 100644 index 0000000000..27761ebd90 --- /dev/null +++ b/askbot/setup_templates/urls.py @@ -0,0 +1,49 @@ +""" +main url configuration file for the askbot site +""" +from django.conf import settings +try: + from django.conf.urls import handler404 + from django.conf.urls import include, url +except ImportError: + from django.conf.urls.defaults import handler404 + from django.conf.urls.defaults import include, url + +from askbot import is_multilingual +from askbot.views.error import internal_error as handler500 +from django.conf import settings +from django.contrib import admin +from django.views import static as StaticViews + +admin.autodiscover() + +if is_multilingual(): + from django.conf.urls.i18n import i18n_patterns + urlpatterns = i18n_patterns( + url(r'%s' % settings.ASKBOT_URL, include('askbot.urls')) + ) +else: + urlpatterns = [ + url(r'%s' % settings.ASKBOT_URL, include('askbot.urls')) + ] + +urlpatterns += [ + url(r'^admin/', admin.site.urls), + #(r'^cache/', include('keyedcache.urls')), - broken views disable for now + #(r'^settings/', include('askbot.deps.livesettings.urls')), + url(r'^followit/', include('followit.urls')), + url(r'^tinymce/', include('tinymce.urls')), + url(r'^robots.txt$', include('robots.urls')), + url( # TODO: replace with django.conf.urls.static ? + r'^%s(?P.*)$' % settings.MEDIA_URL[1:], + StaticViews.serve, + {'document_root': settings.MEDIA_ROOT.replace('\\','/')}, + ) +] + +if 'rosetta' in settings.INSTALLED_APPS: + urlpatterns += [ + url(r'^rosetta/', include('rosetta.urls')), + ] + +handler500 = 'askbot.views.error.internal_error'