From: Lorin Hochstein Date: Sun, 5 Feb 2017 01:14:45 +0000 (-0800) Subject: remove mezz example X-Git-Url: https://git.halfball.org/?a=commitdiff_plain;h=93460a884239bd534caaad02d1804d3f0fc2df1c;p=ansiblebook.git remove mezz example --- diff --git a/ch13/mezzanine_example/.gitignore b/ch13/mezzanine_example/.gitignore deleted file mode 100644 index 5ca6aa0..0000000 --- a/ch13/mezzanine_example/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.pyc -*.pyo -*.db -.DS_Store -.coverage -/static diff --git a/ch13/mezzanine_example/README.md b/ch13/mezzanine_example/README.md deleted file mode 100644 index 741834d..0000000 --- a/ch13/mezzanine_example/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# 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 diff --git a/ch13/mezzanine_example/__init__.py b/ch13/mezzanine_example/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ch13/mezzanine_example/deploy/crontab.template b/ch13/mezzanine_example/deploy/crontab.template deleted file mode 100644 index c4af8cf..0000000 --- a/ch13/mezzanine_example/deploy/crontab.template +++ /dev/null @@ -1,3 +0,0 @@ -# Poll Twitter every 5 minutes -# Comment-out if you don't use Mezzanine's Twitter app -*/5 * * * * %(user)s %(manage)s poll_twitter diff --git a/ch13/mezzanine_example/deploy/gunicorn.conf.py.template b/ch13/mezzanine_example/deploy/gunicorn.conf.py.template deleted file mode 100644 index 257bb97..0000000 --- a/ch13/mezzanine_example/deploy/gunicorn.conf.py.template +++ /dev/null @@ -1,8 +0,0 @@ -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" diff --git a/ch13/mezzanine_example/deploy/local_settings.py.template b/ch13/mezzanine_example/deploy/local_settings.py.template deleted file mode 100644 index d8dc9a0..0000000 --- a/ch13/mezzanine_example/deploy/local_settings.py.template +++ /dev/null @@ -1,37 +0,0 @@ -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" diff --git a/ch13/mezzanine_example/deploy/nginx.conf.template b/ch13/mezzanine_example/deploy/nginx.conf.template deleted file mode 100644 index a304711..0000000 --- a/ch13/mezzanine_example/deploy/nginx.conf.template +++ /dev/null @@ -1,56 +0,0 @@ - -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; - } - -} diff --git a/ch13/mezzanine_example/deploy/supervisor.conf.template b/ch13/mezzanine_example/deploy/supervisor.conf.template deleted file mode 100644 index 5f48e9b..0000000 --- a/ch13/mezzanine_example/deploy/supervisor.conf.template +++ /dev/null @@ -1,9 +0,0 @@ -[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" diff --git a/ch13/mezzanine_example/fabfile.py b/ch13/mezzanine_example/fabfile.py deleted file mode 100644 index f2e1609..0000000 --- a/ch13/mezzanine_example/fabfile.py +++ /dev/null @@ -1,684 +0,0 @@ -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() diff --git a/ch13/mezzanine_example/manage.py b/ch13/mezzanine_example/manage.py deleted file mode 100755 index baa1ed6..0000000 --- a/ch13/mezzanine_example/manage.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/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) diff --git a/ch13/mezzanine_example/mezzanine_example/__init__.py b/ch13/mezzanine_example/mezzanine_example/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ch13/mezzanine_example/mezzanine_example/local_settings.py b/ch13/mezzanine_example/mezzanine_example/local_settings.py deleted file mode 100644 index 43b64a2..0000000 --- a/ch13/mezzanine_example/mezzanine_example/local_settings.py +++ /dev/null @@ -1,44 +0,0 @@ -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" diff --git a/ch13/mezzanine_example/mezzanine_example/settings.py b/ch13/mezzanine_example/mezzanine_example/settings.py deleted file mode 100644 index b1f6150..0000000 --- a/ch13/mezzanine_example/mezzanine_example/settings.py +++ /dev/null @@ -1,336 +0,0 @@ - -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()) diff --git a/ch13/mezzanine_example/mezzanine_example/urls.py b/ch13/mezzanine_example/mezzanine_example/urls.py deleted file mode 100644 index c67fd17..0000000 --- a/ch13/mezzanine_example/mezzanine_example/urls.py +++ /dev/null @@ -1,103 +0,0 @@ -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" diff --git a/ch13/mezzanine_example/mezzanine_example/wsgi.py b/ch13/mezzanine_example/mezzanine_example/wsgi.py deleted file mode 100644 index 7fc9c58..0000000 --- a/ch13/mezzanine_example/mezzanine_example/wsgi.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -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() diff --git a/ch13/mezzanine_example/requirements.txt b/ch13/mezzanine_example/requirements.txt deleted file mode 100644 index bda228b..0000000 --- a/ch13/mezzanine_example/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Mezzanine==4.2.2