Source

caktus-deployment / django-template / PROJECT_NAME / fabfile.py

Full commit
glassresistor 7bce141 













































































































































































































import os

from fabric.api import *
from fabric.contrib.project import rsync_project
from fabric.contrib import files, console
from fabric import utils
from fabric.decorators import hosts


RSYNC_EXCLUDE = (
    '.DS_Store',
    '.svn',
    '*.pyc',
    '*.example',
    'media/admin',
    'media/photologue',
    'media/upload',
    'media/team_photos',
    'passwords.py',
    'local_settings.py',
    'fabfile.py',
    'bootstrap.py',
    'hudson_test_settings.py',
)
env.home = '/home/PROJECT_NAME/'
env.project = 'PROJECT_NAME'
# remove -l from env.shell, "mesg n" in ~/.profile was causing issues
# see Why do I sometimes see ``err: stdin: is not a tty``?
# http://github.com/bitprophet/fabric/blob/master/FAQ
env.shell = '/bin/bash -c'


def setup_path():
    env.code_root = os.path.join(env.root, env.project)
    env.virtualenv_root = os.path.join(env.root, 'env')
    env.db = '%s_%s' % (env.project, env.environment)
    env.settings = '%(project)s.settings_%(environment)s' % env


def staging():
    env.user = ''
    env.environment = 'staging'
    env.hosts = ['']
    env.root = os.path.join(env.home, 'www', env.environment)
    setup_path()


def production():
    env.home = ''
    env.user = ''
    env.environment = 'production'
    env.hosts = ['']
    env.root = os.path.join(env.home, env.environment)
    setup_path()


def create_virtualenv():
    args = '--clear --distribute'
    run('virtualenv %s %s' % (args, env.virtualenv_root))


def update_requirements():
    requirements = os.path.join(env.code_root, 'requirements')
    with cd(requirements):
        cmd = ['pip install']
        cmd += ['-E %(virtualenv_root)s' % env]
        cmd += ['--requirement %s' % os.path.join(requirements, 'apps.txt')]
        run(' '.join(cmd))


def deploy():
    if env.environment == 'production':
        if not console.confirm('Are you sure you want to deploy production?',
                               default=False):
            utils.abort('Production deployment aborted.')
    # run_tests()
    # defaults rsync options:
    # -pthrvz
    # -p preserve permissions
    # -t preserve times
    # -h output numbers in a human-readable format
    # -r recurse into directories
    # -v increase verbosity
    # -z compress file data during the transfer
    extra_opts = '--omit-dir-times'
    rsync_project(
        env.root,
        exclude=RSYNC_EXCLUDE,
        delete=True,
        extra_opts=extra_opts,
    )
    touch()


def run_tests():
    local('./manage.py test', capture=False)


def touch():
    apache_dir = os.path.join(env.code_root, 'apache')
    with cd(apache_dir):
        run('touch %s.wsgi' % env.environment)


def syncdb():
    with cd(env.code_root):
        activate = os.path.join(env.virtualenv_root, 'bin', 'activate')
        activate = 'source %s' % activate
        cmd = './manage.py syncdb --noinput --settings=%s' % env.settings
        run('%s && %s' % (activate, cmd))


def update_apache_conf():
    source = os.path.join('apache', '%(environment)s.conf' % env)
    dest = os.path.join(env.home, 'apache.conf.d')
    put(source, dest, mode=0755)
    apache_reload()


def configtest():
    run('apache2ctl configtest')


def apache_reload():
    run('sudo /etc/init.d/apache2 reload')


def apache_restart():
    run('sudo /etc/init.d/apache2 restart')


def mkdirs():
    run('mkdir -p %(root)s' % env)
    
    run('mkdir -p %s' % os.path.join(env.home, 'www', 'log'))


def _get_pg_password():
    password_file = os.path.join(env.home, '.pg_password')
    with settings(warn_only=True):
        if files.exists(password_file):
            password = run('cat %s' % password_file)
        else:
            run('pwgen 20 1 > %s' % password_file)
            password = run('cat %s' % password_file)
            sql = "ALTER ROLE %s WITH PASSWORD \'%s\'" % (env.project,
                                                          password)
            run('psql -c "%s"' % sql)
    return password


def symlink_django():
    admin_media = os.path.join(env.virtualenv_root,
                               'src/django/django/contrib/admin/media/')
    media = os.path.join(env.code_root, 'media/admin')
    if not files.exists(media):
        run('ln -s %s %s' % (admin_media, media))


def createdb():
    passwords_file = os.path.join(env.code_root, 'passwords.py')
    if not files.exists(passwords_file):
        data = {
            'DATABASE_PASSWORD': _get_pg_password(),
            'SECRET_KEY': run('pwgen 60 1'),
        }
        for key, val in data.iteritems():
            line = '%s = "%s"' % (key, val)
            files.append(line, passwords_file)
    with settings(warn_only=True):
        run('createdb %s' % env.db)


def bootstrap():
    mkdirs()
    create_virtualenv()
    deploy()
    update_requirements()
    if env.environment == 'staging':
        createdb()
        update_apache_conf()


def reset_local_media():
    """ Reset local media from remote host """
    require('code_root', provided_by=('production', 'staging'))
    media = os.path.join(env.code_root, 'media', 'photologue')
    local('rsync -rvaz %s@%s:%s media/' % (env.user, env.hosts[0], media))
    media = os.path.join(env.code_root, 'media', 'team_photos')
    local('rsync -rvaz %s@%s:%s media/' % (env.user, env.hosts[0], media))


def reset_local_db():
    if not console.confirm('Are you sure you want to reset your local '
                           'database with the production database?',
                           default=False):
        utils.abort('Local database reset aborted.')
    database_server = 'calliope.caktusgroup.com'
    production_db = 'PROJECT_NAME_prod'
    settings = 'local_settings.py'
    local_db = local('grep DATABASE_NAME "%s" | cut -d"\'" -f2' % settings)
    local('dropdb %s' % local_db)
    local('createdb %s' % local_db)
    cmd = 'ssh -C %s pg_dump -Ox %s | psql %s' % (database_server,
                                                  production_db,
                                                  local_db)
    local(cmd)