Basic fabric file

Download this as a file

Language: Python  -   Created: 5th Feb, 2010
import os
from iangeorge import settings_live
from fabric.api import *

REPO_LOCATION = 'svn://xxxx/xxxxx/x'

SERVER_DEPENDENCIES = (
    'python-setuptools', 
    'libapache2-mod-wsgi',
    )

APACHE_CONFIG = """
<VirtualHost *:80>
    ServerAdmin %(email)s
    ServerName %(url)s
    DocumentRoot %(siteroot)s/%(app)s

    WSGIScriptAlias / %(siteroot)s/bin/django.wsgi
    WSGIDaemonProcess %(domain)s  processes=1 threads=10
    WSGIProcessGroup %(domain)s

    Alias /robots.txt /%(mediaroot)s/text/robots.txt
    Alias /favicon.ico /%(mediaroot)s/images/icons/favicon.ico


    Alias /media %(mediaroot)s/
    <Location "/media">
        SetHandler None
    </Location>

    Alias /admin_media %(siteroot)s/parts/django/django/contrib/admin/media/
    <Location "/admin_media">
        SetHandler None
    </Location>
</VirtualHost>
"""

def production():
    """Stub function, doesn't do anything but must be called before
    anything else to set up the environment"""
    env.hosts = ['xxxx.xxxxxx.xxx']
    env.user = 'xxxx'
    env.password = 'xxxxx'
    env.app_name = settings_live.APP_NAME
    env.repo = {'url': REPO_LOCATION, 'username':'xxxxxx', 'password':'xxxxxxxx'}
    env.email = settings_live.ADMINS[0][1]

    env.deploy_to = settings_live.PROJECT_PATH
    env.deploy_url = settings_live.SITE_URL
    env.deploy_media_to = settings_live.MEDIA_ROOT
    env.deploy_media_url = settings_live.MEDIA_URL
    env.release = current_version()

def check_env():
    """Not really intended for use from the command line, checks if
    any env data is set"""
    if not 'repo' in env:
        raise Exception("No environment set, call production (or another env setting command) before this. e.g.
$fab production deploy")

def current_version():
    """Gets the latest tagged relase number from the svn repository"""
    check_env()
    cur_vers = local('svn ls --no-auth-cache --username %(u)s --password %(p)s %(repo)s/releases/' % {
        'u': env.repo['username'], 
        'p':env.repo['password'],  
        'repo':env.repo['url']
        }).split('
')
    #nasty :( but it works. Removes the trailing slash, splits into int,
    #fraction and sorts by int, then fraction and then reverses the
    #list.
    cur_vers = [v.strip('/').split('.') for v in cur_vers if len(v) > 0]
    cur_vers.sort(lambda x, y: cmp(int(x[1]),int(y[1])))
    cur_vers.sort(lambda x, y: cmp(int(x[0]),int(y[0])))
    cur_vers.reverse()
    return ".".join(cur_vers[0])

def tag_release(major_inc=0, minor_inc=1):
    """
    Tags the /dev branch as a release using the latest
    /release/[version] as a starting point
    Args:
    maj:amount to increment the major version by, defaults to 0
    min:amount to increment the minor version by, defaults to 1
    """
    check_env()
    print "Current version: %s" % env.release
    next_ver = [0]
    if '.' in str(env.release):
        next_ver = [int(v) for v in env.release.split('.')]
    if len(next_ver) < 2:
        next_ver.append(0)

    if len(next_ver) != 2:
        raise Exception('Unknown version: %s, either amend the code to cope with this versioning system or amend the repository structure' % next_ver)
    else:
        next_ver[0] += major_inc
        next_ver[1] += minor_inc

    r = ".".join([str(v) for v in next_ver])
    print 'Tagging release version %s' % r
    run('svn cp --no-auth-cache --username %(user)s --password %(pass)s --message ''Tagging r%(release)s'' %(repo)s/dev %(repo)s/releases/%(release)s' % 
              {'repo':env.repo['url'], 'release':r, 'user':env.repo['username'], 'pass':env.repo['password']} 
              )
    env.release = r

def deploy_code():
    """
    Deploys the current release to the location specified in
    settings_live.PROJECT_PATH
    """
    print "Ensure directory is in place"
    run('mkdir -p %s' % env.deploy_to)
    print "Export code to directory"
    run('svn export --force --no-auth-cache --username %(u)s --password %(p)s %(repo)s/releases/%(rel)s %(to)s' % {
            'u': env.repo['username'], 
            'p':env.repo['password'],  
            'repo':env.repo['url'],            
            'rel':env.release, 
            'to':env.deploy_to
            })

def buildout():
    """Bootstraps zc.buildout, and runs the base config"""
    with cd(env.deploy_to):
        run('python bootstrap.py -c buildout_base.cfg')
        run('bin/buildout -c buildout_base.cfg')

def install_server_dependencies():
    run('apt-get update')
    run('apt-get install %s' % " ".join(SERVER_DEPENDENCIES))

def setup_site():
    """Adds an entry to sites-enabled with reference to the
    bin/django.wsgi created by the django buildout recipe"""
    check_env()
    install_server_dependencies()
    
    site_config = APACHE_CONFIG % {
        'email':env.email,
        'url':env.deploy_url,
        'domain':env.deploy_url.replace('http://',''),
        'siteroot': env.deploy_to,
        'app': env.app_name,
        'mediaroot':os.path.join(env.deploy_to, env.app_name, env.deploy_media_to)
        }
    run('rm -f /etc/apache2/sites-enabled/%s' % env.app_name)
    run('rm -f /etc/apache2/sites-available/%s' % env.app_name)
    run('echo "%s" > /etc/apache2/sites-available/%s' % (site_config, env.app_name))
    run('a2ensite %s' % env.app_name)

    run('/etc/init.d/apache2 restart')

def database():
    """Currently changes the permissions on the sqlite database and
    runs syncdb"""
    check_env()
    #temp sqlite hack :(
    run('chmod 777 %s/db' % env.deploy_to)
    with cd(env.deploy_to):
        run('bin/django syncdb')

def deploy():
    """Deployment release: deploys or updates site"""
    tag_release()
    deploy_code()
    buildout()
    setup_site()
    database()
    
def update():
    """Update site, assumes apache is already set up on the server"""
    tag_release()
    deploy_code()
    buildout()
    database()

Copy the address below if you want to share this with someone

View all New entry

Projects

Social

@jake74 I’m just not feeling the rage today. Bought the paperback instead, that’ll learn em!”10th May, 2012

Mildly frustrating that the kindle edition of some books is more expensive than the paperback.”10th May, 2012

Play it. Do something useful this afternoon. t.co/8vU0Pszr9th May, 2012