+++ /dev/null
-*.pyc
-*.pyo
-*.db
-.DS_Store
-.coverage
-/static
+++ /dev/null
-# Example mezzanine project
-
-Trivial example of a [Mezzanine][1] project.
-
-Generated by doing:
-
-```bash
-$ mezzanine-project mezzanine_example
-$ chmod +x mezzanine_example/manage.py
-```
-
-[1]: http://mezzanine.jupo.org
+++ /dev/null
-# Poll Twitter every 5 minutes
-# Comment-out if you don't use Mezzanine's Twitter app
-*/5 * * * * %(user)s %(manage)s poll_twitter
+++ /dev/null
-from __future__ import unicode_literals
-import multiprocessing
-
-bind = "unix:%(proj_path)s/gunicorn.sock"
-workers = %(num_workers)s
-errorlog = "/home/%(user)s/logs/%(proj_name)s_error.log"
-loglevel = "error"
-proc_name = "%(proj_name)s"
+++ /dev/null
-from __future__ import unicode_literals
-
-SECRET_KEY = "%(secret_key)s"
-NEVERCACHE_KEY = "%(nevercache_key)s"
-ALLOWED_HOSTS = [%(domains_python)s]
-
-DATABASES = {
- "default": {
- # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
- "ENGINE": "django.db.backends.postgresql_psycopg2",
- # DB name or path to database file if using sqlite3.
- "NAME": "%(proj_name)s",
- # Not used with sqlite3.
- "USER": "%(proj_name)s",
- # Not used with sqlite3.
- "PASSWORD": "%(db_pass)s",
- # Set to empty string for localhost. Not used with sqlite3.
- "HOST": "127.0.0.1",
- # Set to empty string for default. Not used with sqlite3.
- "PORT": "",
- }
-}
-
-SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTOCOL", "https")
-
-CACHE_MIDDLEWARE_SECONDS = 60
-
-CACHE_MIDDLEWARE_KEY_PREFIX = "%(proj_name)s"
-
-CACHES = {
- "default": {
- "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
- "LOCATION": "127.0.0.1:11211",
- }
-}
-
-SESSION_ENGINE = "django.contrib.sessions.backends.cache"
+++ /dev/null
-
-upstream %(proj_name)s {
- server unix:%(proj_path)s/gunicorn.sock fail_timeout=0;
-}
-
-server {
-
- listen 80;
- %(ssl_disabled)s listen 443 ssl;
- server_name %(domains_nginx)s;
- client_max_body_size 10M;
- keepalive_timeout 15;
- error_log /home/%(user)s/logs/%(proj_name)s_error_nginx.log info;
-
- %(ssl_disabled)s ssl_certificate conf/%(proj_name)s.crt;
- %(ssl_disabled)s ssl_certificate_key conf/%(proj_name)s.key;
- %(ssl_disabled)s ssl_session_cache shared:SSL:10m;
- %(ssl_disabled)s ssl_session_timeout 10m;
- %(ssl_disabled)s ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
- %(ssl_disabled)s ssl_prefer_server_ciphers on;
- %(ssl_disabled)s ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
-
- # Deny illegal Host headers
- if ($host !~* ^(%(domains_regex)s)$) {
- return 444;
- }
-
- location / {
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Protocol $scheme;
- proxy_pass http://%(proj_name)s;
- }
-
- location /static/ {
- root %(proj_path)s;
- access_log off;
- log_not_found off;
- expires 30d;
- }
-
- location /robots.txt {
- root %(proj_path)s/static;
- access_log off;
- log_not_found off;
- }
-
- location /favicon.ico {
- root %(proj_path)s/static/img;
- access_log off;
- log_not_found off;
- }
-
-}
+++ /dev/null
-[program:gunicorn_%(proj_name)s]
-command=%(venv_path)s/bin/gunicorn -c gunicorn.conf.py -p gunicorn.pid %(proj_app)s.wsgi:application
-directory=%(proj_path)s
-user=%(user)s
-autostart=true
-stdout_logfile = /home/%(user)s/logs/%(proj_name)s_supervisor
-autorestart=true
-redirect_stderr=true
-environment=LANG="%(locale)s",LC_ALL="%(locale)s",LC_LANG="%(locale)s"
+++ /dev/null
-from __future__ import print_function, unicode_literals
-from future.builtins import open
-
-import os
-import re
-import sys
-from contextlib import contextmanager
-from functools import wraps
-from getpass import getpass, getuser
-from glob import glob
-from importlib import import_module
-from posixpath import join
-
-from mezzanine.utils.conf import real_project_name
-
-from fabric.api import abort, env, cd, prefix, sudo as _sudo, run as _run, \
- hide, task, local
-from fabric.context_managers import settings as fab_settings
-from fabric.contrib.console import confirm
-from fabric.contrib.files import exists, upload_template
-from fabric.contrib.project import rsync_project
-from fabric.colors import yellow, green, blue, red
-from fabric.decorators import hosts
-
-
-################
-# Config setup #
-################
-
-env.proj_app = real_project_name("mezzanine_example")
-
-conf = {}
-if sys.argv[0].split(os.sep)[-1] in ("fab", "fab-script.py"):
- # Ensure we import settings from the current dir
- try:
- conf = import_module("%s.settings" % env.proj_app).FABRIC
- try:
- conf["HOSTS"][0]
- except (KeyError, ValueError):
- raise ImportError
- except (ImportError, AttributeError):
- print("Aborting, no hosts defined.")
- exit()
-
-env.db_pass = conf.get("DB_PASS", None)
-env.admin_pass = conf.get("ADMIN_PASS", None)
-env.user = conf.get("SSH_USER", getuser())
-env.password = conf.get("SSH_PASS", None)
-env.key_filename = conf.get("SSH_KEY_PATH", None)
-env.hosts = conf.get("HOSTS", [""])
-
-env.proj_name = conf.get("PROJECT_NAME", env.proj_app)
-env.venv_home = conf.get("VIRTUALENV_HOME", "/home/%s/.virtualenvs" % env.user)
-env.venv_path = join(env.venv_home, env.proj_name)
-env.proj_path = "/home/%s/mezzanine/%s" % (env.user, env.proj_name)
-env.manage = "%s/bin/python %s/manage.py" % (env.venv_path, env.proj_path)
-env.domains = conf.get("DOMAINS", [conf.get("LIVE_HOSTNAME", env.hosts[0])])
-env.domains_nginx = " ".join(env.domains)
-env.domains_regex = "|".join(env.domains)
-env.domains_python = ", ".join(["'%s'" % s for s in env.domains])
-env.ssl_disabled = "#" if len(env.domains) > 1 else ""
-env.vcs_tools = ["git", "hg"]
-env.deploy_tool = conf.get("DEPLOY_TOOL", "rsync")
-env.reqs_path = conf.get("REQUIREMENTS_PATH", None)
-env.locale = conf.get("LOCALE", "en_US.UTF-8")
-env.num_workers = conf.get("NUM_WORKERS",
- "multiprocessing.cpu_count() * 2 + 1")
-
-env.secret_key = conf.get("SECRET_KEY", "")
-env.nevercache_key = conf.get("NEVERCACHE_KEY", "")
-
-# Remote git repos need to be "bare" and reside separated from the project
-if env.deploy_tool == "git":
- env.repo_path = "/home/%s/git/%s.git" % (env.user, env.proj_name)
-else:
- env.repo_path = env.proj_path
-
-
-##################
-# Template setup #
-##################
-
-# Each template gets uploaded at deploy time, only if their
-# contents has changed, in which case, the reload command is
-# also run.
-
-templates = {
- "nginx": {
- "local_path": "deploy/nginx.conf.template",
- "remote_path": "/etc/nginx/sites-enabled/%(proj_name)s.conf",
- "reload_command": "service nginx restart",
- },
- "supervisor": {
- "local_path": "deploy/supervisor.conf.template",
- "remote_path": "/etc/supervisor/conf.d/%(proj_name)s.conf",
- "reload_command": "supervisorctl update gunicorn_%(proj_name)s",
- },
- "cron": {
- "local_path": "deploy/crontab.template",
- "remote_path": "/etc/cron.d/%(proj_name)s",
- "owner": "root",
- "mode": "600",
- },
- "gunicorn": {
- "local_path": "deploy/gunicorn.conf.py.template",
- "remote_path": "%(proj_path)s/gunicorn.conf.py",
- },
- "settings": {
- "local_path": "deploy/local_settings.py.template",
- "remote_path": "%(proj_path)s/%(proj_app)s/local_settings.py",
- },
-}
-
-
-######################################
-# Context for virtualenv and project #
-######################################
-
-@contextmanager
-def virtualenv():
- """
- Runs commands within the project's virtualenv.
- """
- with cd(env.venv_path):
- with prefix("source %s/bin/activate" % env.venv_path):
- yield
-
-
-@contextmanager
-def project():
- """
- Runs commands within the project's directory.
- """
- with virtualenv():
- with cd(env.proj_path):
- yield
-
-
-@contextmanager
-def update_changed_requirements():
- """
- Checks for changes in the requirements file across an update,
- and gets new requirements if changes have occurred.
- """
- reqs_path = join(env.proj_path, env.reqs_path)
- get_reqs = lambda: run("cat %s" % reqs_path, show=False)
- old_reqs = get_reqs() if env.reqs_path else ""
- yield
- if old_reqs:
- new_reqs = get_reqs()
- if old_reqs == new_reqs:
- # Unpinned requirements should always be checked.
- for req in new_reqs.split("\n"):
- if req.startswith("-e"):
- if "@" not in req:
- # Editable requirement without pinned commit.
- break
- elif req.strip() and not req.startswith("#"):
- if not set(">=<") & set(req):
- # PyPI requirement without version.
- break
- else:
- # All requirements are pinned.
- return
- pip("-r %s/%s" % (env.proj_path, env.reqs_path))
-
-
-###########################################
-# Utils and wrappers for various commands #
-###########################################
-
-def _print(output):
- print()
- print(output)
- print()
-
-
-def print_command(command):
- _print(blue("$ ", bold=True) +
- yellow(command, bold=True) +
- red(" ->", bold=True))
-
-
-@task
-def run(command, show=True, *args, **kwargs):
- """
- Runs a shell comand on the remote server.
- """
- if show:
- print_command(command)
- with hide("running"):
- return _run(command, *args, **kwargs)
-
-
-@task
-def sudo(command, show=True, *args, **kwargs):
- """
- Runs a command as sudo on the remote server.
- """
- if show:
- print_command(command)
- with hide("running"):
- return _sudo(command, *args, **kwargs)
-
-
-def log_call(func):
- @wraps(func)
- def logged(*args, **kawrgs):
- header = "-" * len(func.__name__)
- _print(green("\n".join([header, func.__name__, header]), bold=True))
- return func(*args, **kawrgs)
- return logged
-
-
-def get_templates():
- """
- Returns each of the templates with env vars injected.
- """
- injected = {}
- for name, data in templates.items():
- injected[name] = dict([(k, v % env) for k, v in data.items()])
- return injected
-
-
-def upload_template_and_reload(name):
- """
- Uploads a template only if it has changed, and if so, reload the
- related service.
- """
- template = get_templates()[name]
- local_path = template["local_path"]
- if not os.path.exists(local_path):
- project_root = os.path.dirname(os.path.abspath(__file__))
- local_path = os.path.join(project_root, local_path)
- remote_path = template["remote_path"]
- reload_command = template.get("reload_command")
- owner = template.get("owner")
- mode = template.get("mode")
- remote_data = ""
- if exists(remote_path):
- with hide("stdout"):
- remote_data = sudo("cat %s" % remote_path, show=False)
- with open(local_path, "r") as f:
- local_data = f.read()
- # Escape all non-string-formatting-placeholder occurrences of '%':
- local_data = re.sub(r"%(?!\(\w+\)s)", "%%", local_data)
- if "%(db_pass)s" in local_data:
- env.db_pass = db_pass()
- local_data %= env
- clean = lambda s: s.replace("\n", "").replace("\r", "").strip()
- if clean(remote_data) == clean(local_data):
- return
- upload_template(local_path, remote_path, env, use_sudo=True, backup=False)
- if owner:
- sudo("chown %s %s" % (owner, remote_path))
- if mode:
- sudo("chmod %s %s" % (mode, remote_path))
- if reload_command:
- sudo(reload_command)
-
-
-def rsync_upload():
- """
- Uploads the project with rsync excluding some files and folders.
- """
- excludes = ["*.pyc", "*.pyo", "*.db", ".DS_Store", ".coverage",
- "local_settings.py", "/static", "/.git", "/.hg"]
- local_dir = os.getcwd() + os.sep
- return rsync_project(remote_dir=env.proj_path, local_dir=local_dir,
- exclude=excludes)
-
-
-def vcs_upload():
- """
- Uploads the project with the selected VCS tool.
- """
- if env.deploy_tool == "git":
- remote_path = "ssh://%s@%s%s" % (env.user, env.host_string,
- env.repo_path)
- if not exists(env.repo_path):
- run("mkdir -p %s" % env.repo_path)
- with cd(env.repo_path):
- run("git init --bare")
- local("git push -f %s master" % remote_path)
- with cd(env.repo_path):
- run("GIT_WORK_TREE=%s git checkout -f master" % env.proj_path)
- run("GIT_WORK_TREE=%s git reset --hard" % env.proj_path)
- elif env.deploy_tool == "hg":
- remote_path = "ssh://%s@%s/%s" % (env.user, env.host_string,
- env.repo_path)
- with cd(env.repo_path):
- if not exists("%s/.hg" % env.repo_path):
- run("hg init")
- print(env.repo_path)
- with fab_settings(warn_only=True):
- push = local("hg push -f %s" % remote_path)
- if push.return_code == 255:
- abort()
- run("hg update")
-
-
-def db_pass():
- """
- Prompts for the database password if unknown.
- """
- if not env.db_pass:
- env.db_pass = getpass("Enter the database password: ")
- return env.db_pass
-
-
-@task
-def apt(packages):
- """
- Installs one or more system packages via apt.
- """
- return sudo("apt-get install -y -q " + packages)
-
-
-@task
-def pip(packages):
- """
- Installs one or more Python packages within the virtual environment.
- """
- with virtualenv():
- return run("pip install %s" % packages)
-
-
-def postgres(command):
- """
- Runs the given command as the postgres user.
- """
- show = not command.startswith("psql")
- return sudo(command, show=show, user="postgres")
-
-
-@task
-def psql(sql, show=True):
- """
- Runs SQL against the project's database.
- """
- out = postgres('psql -c "%s"' % sql)
- if show:
- print_command(sql)
- return out
-
-
-@task
-def backup(filename):
- """
- Backs up the project database.
- """
- tmp_file = "/tmp/%s" % filename
- # We dump to /tmp because user "postgres" can't write to other user folders
- # We cd to / because user "postgres" might not have read permissions
- # elsewhere.
- with cd("/"):
- postgres("pg_dump -Fc %s > %s" % (env.proj_name, tmp_file))
- run("cp %s ." % tmp_file)
- sudo("rm -f %s" % tmp_file)
-
-
-@task
-def restore(filename):
- """
- Restores the project database from a previous backup.
- """
- return postgres("pg_restore -c -d %s %s" % (env.proj_name, filename))
-
-
-@task
-def python(code, show=True):
- """
- Runs Python code in the project's virtual environment, with Django loaded.
- """
- setup = "import os;" \
- "os.environ[\'DJANGO_SETTINGS_MODULE\']=\'%s.settings\';" \
- "import django;" \
- "django.setup();" % env.proj_app
- full_code = 'python -c "%s%s"' % (setup, code.replace("`", "\\\`"))
- with project():
- if show:
- print_command(code)
- result = run(full_code, show=False)
- return result
-
-
-def static():
- """
- Returns the live STATIC_ROOT directory.
- """
- return python("from django.conf import settings;"
- "print(settings.STATIC_ROOT)", show=False).split("\n")[-1]
-
-
-@task
-def manage(command):
- """
- Runs a Django management command.
- """
- return run("%s %s" % (env.manage, command))
-
-
-###########################
-# Security best practices #
-###########################
-
-@task
-@log_call
-@hosts(["root@%s" % host for host in env.hosts])
-def secure(new_user=env.user):
- """
- Minimal security steps for brand new servers.
- Installs system updates, creates new user (with sudo privileges) for future
- usage, and disables root login via SSH.
- """
- run("apt-get update -q")
- run("apt-get upgrade -y -q")
- run("adduser --gecos '' %s" % new_user)
- run("usermod -G sudo %s" % new_user)
- run("sed -i 's:RootLogin yes:RootLogin no:' /etc/ssh/sshd_config")
- run("service ssh restart")
- print(green("Security steps completed. Log in to the server as '%s' from "
- "now on." % new_user, bold=True))
-
-
-#########################
-# Install and configure #
-#########################
-
-@task
-@log_call
-def install():
- """
- Installs the base system and Python requirements for the entire server.
- """
- # Install system requirements
- sudo("apt-get update -y -q")
- apt("nginx libjpeg-dev python-dev python-setuptools git-core "
- "postgresql libpq-dev memcached supervisor python-pip")
- run("mkdir -p /home/%s/logs" % env.user)
-
- # Install Python requirements
- sudo("pip install -U pip virtualenv virtualenvwrapper mercurial")
-
- # Set up virtualenv
- run("mkdir -p %s" % env.venv_home)
- run("echo 'export WORKON_HOME=%s' >> /home/%s/.bashrc" % (env.venv_home,
- env.user))
- run("echo 'source /usr/local/bin/virtualenvwrapper.sh' >> "
- "/home/%s/.bashrc" % env.user)
- print(green("Successfully set up git, mercurial, pip, virtualenv, "
- "supervisor, memcached.", bold=True))
-
-
-@task
-@log_call
-def create():
- """
- Creates the environment needed to host the project.
- The environment consists of: system locales, virtualenv, database, project
- files, SSL certificate, and project-specific Python requirements.
- """
- # Generate project locale
- locale = env.locale.replace("UTF-8", "utf8")
- with hide("stdout"):
- if locale not in run("locale -a"):
- sudo("locale-gen %s" % env.locale)
- sudo("update-locale %s" % env.locale)
- sudo("service postgresql restart")
- run("exit")
-
- # Create project path
- run("mkdir -p %s" % env.proj_path)
-
- # Set up virtual env
- run("mkdir -p %s" % env.venv_home)
- with cd(env.venv_home):
- if exists(env.proj_name):
- if confirm("Virtualenv already exists in host server: %s"
- "\nWould you like to replace it?" % env.proj_name):
- run("rm -rf %s" % env.proj_name)
- else:
- abort()
- run("virtualenv %s" % env.proj_name)
-
- # Upload project files
- if env.deploy_tool in env.vcs_tools:
- vcs_upload()
- else:
- rsync_upload()
-
- # Create DB and DB user
- pw = db_pass()
- user_sql_args = (env.proj_name, pw.replace("'", "\'"))
- user_sql = "CREATE USER %s WITH ENCRYPTED PASSWORD '%s';" % user_sql_args
- psql(user_sql, show=False)
- shadowed = "*" * len(pw)
- print_command(user_sql.replace("'%s'" % pw, "'%s'" % shadowed))
- psql("CREATE DATABASE %s WITH OWNER %s ENCODING = 'UTF8' "
- "LC_CTYPE = '%s' LC_COLLATE = '%s' TEMPLATE template0;" %
- (env.proj_name, env.proj_name, env.locale, env.locale))
-
- # Set up SSL certificate
- if not env.ssl_disabled:
- conf_path = "/etc/nginx/conf"
- if not exists(conf_path):
- sudo("mkdir %s" % conf_path)
- with cd(conf_path):
- crt_file = env.proj_name + ".crt"
- key_file = env.proj_name + ".key"
- if not exists(crt_file) and not exists(key_file):
- try:
- crt_local, = glob(join("deploy", "*.crt"))
- key_local, = glob(join("deploy", "*.key"))
- except ValueError:
- parts = (crt_file, key_file, env.domains[0])
- sudo("openssl req -new -x509 -nodes -out %s -keyout %s "
- "-subj '/CN=%s' -days 3650" % parts)
- else:
- upload_template(crt_local, crt_file, use_sudo=True)
- upload_template(key_local, key_file, use_sudo=True)
-
- # Install project-specific requirements
- upload_template_and_reload("settings")
- with project():
- if env.reqs_path:
- pip("-r %s/%s" % (env.proj_path, env.reqs_path))
- pip("gunicorn setproctitle psycopg2 "
- "django-compressor python-memcached")
- # Bootstrap the DB
- manage("createdb --noinput --nodata")
- python("from django.conf import settings;"
- "from django.contrib.sites.models import Site;"
- "Site.objects.filter(id=settings.SITE_ID).update(domain='%s');"
- % env.domains[0])
- for domain in env.domains:
- python("from django.contrib.sites.models import Site;"
- "Site.objects.get_or_create(domain='%s');" % domain)
- if env.admin_pass:
- pw = env.admin_pass
- user_py = ("from django.contrib.auth import get_user_model;"
- "User = get_user_model();"
- "u, _ = User.objects.get_or_create(username='admin');"
- "u.is_staff = u.is_superuser = True;"
- "u.set_password('%s');"
- "u.save();" % pw)
- python(user_py, show=False)
- shadowed = "*" * len(pw)
- print_command(user_py.replace("'%s'" % pw, "'%s'" % shadowed))
-
- return True
-
-
-@task
-@log_call
-def remove():
- """
- Blow away the current project.
- """
- if exists(env.venv_path):
- run("rm -rf %s" % env.venv_path)
- if exists(env.proj_path):
- run("rm -rf %s" % env.proj_path)
- for template in get_templates().values():
- remote_path = template["remote_path"]
- if exists(remote_path):
- sudo("rm %s" % remote_path)
- if exists(env.repo_path):
- run("rm -rf %s" % env.repo_path)
- sudo("supervisorctl update")
- psql("DROP DATABASE IF EXISTS %s;" % env.proj_name)
- psql("DROP USER IF EXISTS %s;" % env.proj_name)
-
-
-##############
-# Deployment #
-##############
-
-@task
-@log_call
-def restart():
- """
- Restart gunicorn worker processes for the project.
- If the processes are not running, they will be started.
- """
- pid_path = "%s/gunicorn.pid" % env.proj_path
- if exists(pid_path):
- run("kill -HUP `cat %s`" % pid_path)
- else:
- sudo("supervisorctl update")
-
-
-@task
-@log_call
-def deploy():
- """
- Deploy latest version of the project.
- Backup current version of the project, push latest version of the project
- via version control or rsync, install new requirements, sync and migrate
- the database, collect any new static assets, and restart gunicorn's worker
- processes for the project.
- """
- if not exists(env.proj_path):
- if confirm("Project does not exist in host server: %s"
- "\nWould you like to create it?" % env.proj_name):
- create()
- else:
- abort()
-
- # Backup current version of the project
- with cd(env.proj_path):
- backup("last.db")
- if env.deploy_tool in env.vcs_tools:
- with cd(env.repo_path):
- if env.deploy_tool == "git":
- run("git rev-parse HEAD > %s/last.commit" % env.proj_path)
- elif env.deploy_tool == "hg":
- run("hg id -i > last.commit")
- with project():
- static_dir = static()
- if exists(static_dir):
- run("tar -cf static.tar --exclude='*.thumbnails' %s" %
- static_dir)
- else:
- with cd(join(env.proj_path, "..")):
- excludes = ["*.pyc", "*.pio", "*.thumbnails"]
- exclude_arg = " ".join("--exclude='%s'" % e for e in excludes)
- run("tar -cf {0}.tar {1} {0}".format(env.proj_name, exclude_arg))
-
- # Deploy latest version of the project
- with update_changed_requirements():
- if env.deploy_tool in env.vcs_tools:
- vcs_upload()
- else:
- rsync_upload()
- with project():
- manage("collectstatic -v 0 --noinput")
- manage("migrate --noinput")
- for name in get_templates():
- upload_template_and_reload(name)
- restart()
- return True
-
-
-@task
-@log_call
-def rollback():
- """
- Reverts project state to the last deploy.
- When a deploy is performed, the current state of the project is
- backed up. This includes the project files, the database, and all static
- files. Calling rollback will revert all of these to their state prior to
- the last deploy.
- """
- with update_changed_requirements():
- if env.deploy_tool in env.vcs_tools:
- with cd(env.repo_path):
- if env.deploy_tool == "git":
- run("GIT_WORK_TREE={0} git checkout -f "
- "`cat {0}/last.commit`".format(env.proj_path))
- elif env.deploy_tool == "hg":
- run("hg update -C `cat last.commit`")
- with project():
- with cd(join(static(), "..")):
- run("tar -xf %s/static.tar" % env.proj_path)
- else:
- with cd(env.proj_path.rsplit("/", 1)[0]):
- run("rm -rf %s" % env.proj_name)
- run("tar -xf %s.tar" % env.proj_name)
- with cd(env.proj_path):
- restore("last.db")
- restart()
-
-
-@task
-@log_call
-def all():
- """
- Installs everything required on a new system and deploy.
- From the base software, up to the deployed project.
- """
- install()
- if create():
- deploy()
+++ /dev/null
-#!/usr/bin/env python
-import os
-import sys
-
-if __name__ == "__main__":
-
- from mezzanine.utils.conf import real_project_name
-
- settings_module = "%s.settings" % real_project_name("mezzanine_example")
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module)
-
- from django.core.management import execute_from_command_line
-
- execute_from_command_line(sys.argv)
+++ /dev/null
-from __future__ import unicode_literals
-import os
-
-SECRET_KEY = os.environ.get("SECRET_KEY", "")
-NEVERCACHE_KEY = os.environ.get("NEVERCACHE_KEY", "")
-ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "['*']")
-
-DATABASES = {
- "default": {
- # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
- "ENGINE": "django.db.backends.postgresql_psycopg2",
- # DB name or path to database file if using sqlite3.
- "NAME": os.environ.get("DATABASE_NAME", ""),
- # Not used with sqlite3.
- "USER": os.environ.get("DATABASE_USER", ""),
- # Not used with sqlite3.
- "PASSWORD": os.environ.get("DATABASE_PASSWORD", ""),
- # Set to empty string for localhost. Not used with sqlite3.
- "HOST": os.environ.get("DATABASE_HOST", "postgres"),
- # Set to empty string for default. Not used with sqlite3.
- "PORT": os.environ.get("DATABASE_PORT", "5432")
- }
-}
-
-SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTOCOL", "https")
-
-CACHE_MIDDLEWARE_SECONDS = 60
-
-CACHE_MIDDLEWARE_KEY_PREFIX = "mezzanine_example"
-
-CACHES = {
- "default": {
- "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
- "LOCATION": os.environ.get("MEMCACHED_LOCATION", "memcached:11211"),
- }
-}
-
-SESSION_ENGINE = "django.contrib.sessions.backends.cache"
-
-TWITTER_ACCESS_TOKEN_KEY = os.environ.get("TWITTER_ACCESS_TOKEN_KEY ", "")
-TWITTER_ACCESS_TOKEN_SECRET = os.environ.get("TWITTER_ACCESS_TOKEN_SECRET ", "")
-TWITTER_CONSUMER_KEY = os.environ.get("TWITTER_CONSUMER_KEY ", "")
-TWITTER_CONSUMER_SERCRET = os.environ.get("TWITTER_CONSUMER_SERCRET ", "")
-TWITTER_DEFAULT_QUERY = "from:ansiblebook"
+++ /dev/null
-
-from __future__ import absolute_import, unicode_literals
-import os
-
-from django import VERSION as DJANGO_VERSION
-from django.utils.translation import ugettext_lazy as _
-
-
-######################
-# MEZZANINE SETTINGS #
-######################
-
-# The following settings are already defined with default values in
-# the ``defaults.py`` module within each of Mezzanine's apps, but are
-# common enough to be put here, commented out, for conveniently
-# overriding. Please consult the settings documentation for a full list
-# of settings Mezzanine implements:
-# http://mezzanine.jupo.org/docs/configuration.html#default-settings
-
-# Controls the ordering and grouping of the admin menu.
-#
-# ADMIN_MENU_ORDER = (
-# ("Content", ("pages.Page", "blog.BlogPost",
-# "generic.ThreadedComment", (_("Media Library"), "media-library"),)),
-# ("Site", ("sites.Site", "redirects.Redirect", "conf.Setting")),
-# ("Users", ("auth.User", "auth.Group",)),
-# )
-
-# A three item sequence, each containing a sequence of template tags
-# used to render the admin dashboard.
-#
-# DASHBOARD_TAGS = (
-# ("blog_tags.quick_blog", "mezzanine_tags.app_list"),
-# ("comment_tags.recent_comments",),
-# ("mezzanine_tags.recent_actions",),
-# )
-
-# A sequence of templates used by the ``page_menu`` template tag. Each
-# item in the sequence is a three item sequence, containing a unique ID
-# for the template, a label for the template, and the template path.
-# These templates are then available for selection when editing which
-# menus a page should appear in. Note that if a menu template is used
-# that doesn't appear in this setting, all pages will appear in it.
-
-# PAGE_MENU_TEMPLATES = (
-# (1, _("Top navigation bar"), "pages/menus/dropdown.html"),
-# (2, _("Left-hand tree"), "pages/menus/tree.html"),
-# (3, _("Footer"), "pages/menus/footer.html"),
-# )
-
-# A sequence of fields that will be injected into Mezzanine's (or any
-# library's) models. Each item in the sequence is a four item sequence.
-# The first two items are the dotted path to the model and its field
-# name to be added, and the dotted path to the field class to use for
-# the field. The third and fourth items are a sequence of positional
-# args and a dictionary of keyword args, to use when creating the
-# field instance. When specifying the field class, the path
-# ``django.models.db.`` can be omitted for regular Django model fields.
-#
-# EXTRA_MODEL_FIELDS = (
-# (
-# # Dotted path to field.
-# "mezzanine.blog.models.BlogPost.image",
-# # Dotted path to field class.
-# "somelib.fields.ImageField",
-# # Positional args for field class.
-# (_("Image"),),
-# # Keyword args for field class.
-# {"blank": True, "upload_to": "blog"},
-# ),
-# # Example of adding a field to *all* of Mezzanine's content types:
-# (
-# "mezzanine.pages.models.Page.another_field",
-# "IntegerField", # 'django.db.models.' is implied if path is omitted.
-# (_("Another name"),),
-# {"blank": True, "default": 1},
-# ),
-# )
-
-# Setting to turn on featured images for blog posts. Defaults to False.
-#
-# BLOG_USE_FEATURED_IMAGE = True
-
-# If True, the django-modeltranslation will be added to the
-# INSTALLED_APPS setting.
-USE_MODELTRANSLATION = False
-
-
-########################
-# MAIN DJANGO SETTINGS #
-########################
-
-# Hosts/domain names that are valid for this site; required if DEBUG is False
-# See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
-ALLOWED_HOSTS = []
-
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# On Unix systems, a value of None will cause Django to use the same
-# timezone as the operating system.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'UTC'
-
-# If you set this to True, Django will use timezone-aware datetimes.
-USE_TZ = True
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = "en"
-
-# Supported languages
-LANGUAGES = (
- ('en', _('English')),
-)
-
-# A boolean that turns on/off debug mode. When set to ``True``, stack traces
-# are displayed for error pages. Should always be set to ``False`` in
-# production. Best set to ``True`` in local_settings.py
-DEBUG = False
-
-# Whether a user's session cookie expires when the Web browser is closed.
-SESSION_EXPIRE_AT_BROWSER_CLOSE = True
-
-SITE_ID = 1
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = False
-
-AUTHENTICATION_BACKENDS = ("mezzanine.core.auth_backends.MezzanineBackend",)
-
-# The numeric mode to set newly-uploaded files to. The value should be
-# a mode you'd pass directly to os.chmod.
-FILE_UPLOAD_PERMISSIONS = 0o644
-
-
-#############
-# DATABASES #
-#############
-
-DATABASES = {
- "default": {
- # Add "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
- "ENGINE": "django.db.backends.",
- # DB name or path to database file if using sqlite3.
- "NAME": "",
- # Not used with sqlite3.
- "USER": "",
- # Not used with sqlite3.
- "PASSWORD": "",
- # Set to empty string for localhost. Not used with sqlite3.
- "HOST": "",
- # Set to empty string for default. Not used with sqlite3.
- "PORT": "",
- }
-}
-
-
-#########
-# PATHS #
-#########
-
-# Full filesystem path to the project.
-PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
-PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
-PROJECT_ROOT = BASE_DIR = os.path.dirname(PROJECT_APP_PATH)
-
-# Every cache key will get prefixed with this value - here we set it to
-# the name of the directory the project is in to try and use something
-# project specific.
-CACHE_MIDDLEWARE_KEY_PREFIX = PROJECT_APP
-
-# URL prefix for static files.
-# Example: "http://media.lawrence.com/static/"
-STATIC_URL = "/static/"
-
-# Absolute path to the directory static files should be collected to.
-# Don't put anything in this directory yourself; store your static files
-# in apps' "static/" subdirectories and in STATICFILES_DIRS.
-# Example: "/home/media/media.lawrence.com/static/"
-STATIC_ROOT = os.path.join(PROJECT_ROOT, STATIC_URL.strip("/"))
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash.
-# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
-MEDIA_URL = STATIC_URL + "media/"
-
-# Absolute filesystem path to the directory that will hold user-uploaded files.
-# Example: "/home/media/media.lawrence.com/media/"
-MEDIA_ROOT = os.path.join(PROJECT_ROOT, *MEDIA_URL.strip("/").split("/"))
-
-# Package/module name to import the root urlpatterns from for the project.
-ROOT_URLCONF = "%s.urls" % PROJECT_APP
-
-TEMPLATES = [
- {
- "BACKEND": "django.template.backends.django.DjangoTemplates",
- "DIRS": [
- os.path.join(PROJECT_ROOT, "templates")
- ],
- "APP_DIRS": True,
- "OPTIONS": {
- "context_processors": [
- "django.contrib.auth.context_processors.auth",
- "django.contrib.messages.context_processors.messages",
- "django.template.context_processors.debug",
- "django.template.context_processors.i18n",
- "django.template.context_processors.static",
- "django.template.context_processors.media",
- "django.template.context_processors.request",
- "django.template.context_processors.tz",
- "mezzanine.conf.context_processors.settings",
- "mezzanine.pages.context_processors.page",
- ],
- "builtins": [
- "mezzanine.template.loader_tags",
- ],
- },
- },
-]
-
-if DJANGO_VERSION < (1, 9):
- del TEMPLATES[0]["OPTIONS"]["builtins"]
-
-
-################
-# APPLICATIONS #
-################
-
-INSTALLED_APPS = (
- "django.contrib.admin",
- "django.contrib.auth",
- "django.contrib.contenttypes",
- "django.contrib.redirects",
- "django.contrib.sessions",
- "django.contrib.sites",
- "django.contrib.sitemaps",
- "django.contrib.staticfiles",
- "mezzanine.boot",
- "mezzanine.conf",
- "mezzanine.core",
- "mezzanine.generic",
- "mezzanine.pages",
- "mezzanine.blog",
- "mezzanine.forms",
- "mezzanine.galleries",
- "mezzanine.twitter",
- # "mezzanine.accounts",
- # "mezzanine.mobile",
-)
-
-# List of middleware classes to use. Order is important; in the request phase,
-# these middleware classes will be applied in the order given, and in the
-# response phase the middleware will be applied in reverse order.
-MIDDLEWARE_CLASSES = (
- "mezzanine.core.middleware.UpdateCacheMiddleware",
-
- 'django.contrib.sessions.middleware.SessionMiddleware',
- # Uncomment if using internationalisation or localisation
- # 'django.middleware.locale.LocaleMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-
- "mezzanine.core.request.CurrentRequestMiddleware",
- "mezzanine.core.middleware.RedirectFallbackMiddleware",
- "mezzanine.core.middleware.TemplateForDeviceMiddleware",
- "mezzanine.core.middleware.TemplateForHostMiddleware",
- "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
- "mezzanine.core.middleware.SitePermissionMiddleware",
- "mezzanine.pages.middleware.PageMiddleware",
- "mezzanine.core.middleware.FetchFromCacheMiddleware",
-)
-
-# Store these package names here as they may change in the future since
-# at the moment we are using custom forks of them.
-PACKAGE_NAME_FILEBROWSER = "filebrowser_safe"
-PACKAGE_NAME_GRAPPELLI = "grappelli_safe"
-
-#########################
-# OPTIONAL APPLICATIONS #
-#########################
-
-# These will be added to ``INSTALLED_APPS``, only if available.
-OPTIONAL_APPS = (
- "debug_toolbar",
- "django_extensions",
- "compressor",
- PACKAGE_NAME_FILEBROWSER,
- PACKAGE_NAME_GRAPPELLI,
-)
-
-##################
-# LOCAL SETTINGS #
-##################
-
-# Allow any settings to be defined in local_settings.py which should be
-# ignored in your version control system allowing for settings to be
-# defined per machine.
-
-# Instead of doing "from .local_settings import *", we use exec so that
-# local_settings has full access to everything defined in this module.
-# Also force into sys.modules so it's visible to Django's autoreload.
-
-f = os.path.join(PROJECT_APP_PATH, "local_settings.py")
-if os.path.exists(f):
- import sys
- import imp
- module_name = "%s.local_settings" % PROJECT_APP
- module = imp.new_module(module_name)
- module.__file__ = f
- sys.modules[module_name] = module
- exec(open(f, "rb").read())
-
-
-####################
-# DYNAMIC SETTINGS #
-####################
-
-# set_dynamic_settings() will rewrite globals based on what has been
-# defined so far, in order to provide some better defaults where
-# applicable. We also allow this settings module to be imported
-# without Mezzanine installed, as the case may be when using the
-# fabfile, where setting the dynamic settings below isn't strictly
-# required.
-try:
- from mezzanine.utils.conf import set_dynamic_settings
-except ImportError:
- pass
-else:
- set_dynamic_settings(globals())
+++ /dev/null
-from __future__ import unicode_literals
-
-from django.conf.urls import include, url
-from django.conf.urls.i18n import i18n_patterns
-from django.contrib import admin
-from django.views.i18n import set_language
-
-from mezzanine.core.views import direct_to_template
-from mezzanine.conf import settings
-
-
-admin.autodiscover()
-
-# Add the urlpatterns for any custom Django applications here.
-# You can also change the ``home`` view to add your own functionality
-# to the project's homepage.
-
-urlpatterns = i18n_patterns(
- # Change the admin prefix here to use an alternate URL for the
- # admin interface, which would be marginally more secure.
- url("^admin/", include(admin.site.urls)),
-)
-
-if settings.USE_MODELTRANSLATION:
- urlpatterns += [
- url('^i18n/$', set_language, name='set_language'),
- ]
-
-urlpatterns += [
- # We don't want to presume how your homepage works, so here are a
- # few patterns you can use to set it up.
-
- # HOMEPAGE AS STATIC TEMPLATE
- # ---------------------------
- # This pattern simply loads the index.html template. It isn't
- # commented out like the others, so it's the default. You only need
- # one homepage pattern, so if you use a different one, comment this
- # one out.
-
- url("^$", direct_to_template, {"template": "index.html"}, name="home"),
-
- # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
- # ---------------------------------------------
- # This pattern gives us a normal ``Page`` object, so that your
- # homepage can be managed via the page tree in the admin. If you
- # use this pattern, you'll need to create a page in the page tree,
- # and specify its URL (in the Meta Data section) as "/", which
- # is the value used below in the ``{"slug": "/"}`` part.
- # Also note that the normal rule of adding a custom
- # template per page with the template name using the page's slug
- # doesn't apply here, since we can't have a template called
- # "/.html" - so for this case, the template "pages/index.html"
- # should be used if you want to customize the homepage's template.
- # NOTE: Don't forget to import the view function too!
-
- # url("^$", mezzanine.pages.views.page, {"slug": "/"}, name="home"),
-
- # HOMEPAGE FOR A BLOG-ONLY SITE
- # -----------------------------
- # This pattern points the homepage to the blog post listing page,
- # and is useful for sites that are primarily blogs. If you use this
- # pattern, you'll also need to set BLOG_SLUG = "" in your
- # ``settings.py`` module, and delete the blog page object from the
- # page tree in the admin if it was installed.
- # NOTE: Don't forget to import the view function too!
-
- # url("^$", mezzanine.blog.views.blog_post_list, name="home"),
-
- # MEZZANINE'S URLS
- # ----------------
- # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
- # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
- # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
- # WILL NEVER BE MATCHED!
-
- # If you'd like more granular control over the patterns in
- # ``mezzanine.urls``, go right ahead and take the parts you want
- # from it, and use them directly below instead of using
- # ``mezzanine.urls``.
- url("^", include("mezzanine.urls")),
-
- # MOUNTING MEZZANINE UNDER A PREFIX
- # ---------------------------------
- # You can also mount all of Mezzanine's urlpatterns under a
- # URL prefix if desired. When doing this, you need to define the
- # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
- # SITE_PREFIX = "my/site/prefix"
- # For convenience, and to avoid repeating the prefix, use the
- # commented out pattern below (commenting out the one above of course)
- # which will make use of the ``SITE_PREFIX`` setting. Make sure to
- # add the import ``from django.conf import settings`` to the top
- # of this file as well.
- # Note that for any of the various homepage patterns above, you'll
- # need to use the ``SITE_PREFIX`` setting as well.
-
- # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
-
-]
-
-# Adds ``STATIC_URL`` to the context of error pages, so that error
-# pages can use JS, CSS and images.
-handler404 = "mezzanine.core.views.page_not_found"
-handler500 = "mezzanine.core.views.server_error"
+++ /dev/null
-"""
-WSGI config for mezzanine_example project.
-
-It exposes the WSGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
-"""
-
-import os
-
-from django.core.wsgi import get_wsgi_application
-from mezzanine.utils.conf import real_project_name
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE",
- "%s.settings" % real_project_name("mezzanine_example"))
-
-application = get_wsgi_application()
+++ /dev/null
-Mezzanine==4.2.2