Gwadeloop.com

Tip #2 From Gwadeloop: Fabric

Fabric

Fabric is a python package that helps to automate tasks. It is flexible and simple to use, it will help you to define a repeatable installation / configuration process.The tasks defined in your fabric's script, often call fabfile.py, can be run on any host that is accessible via ssh.

Installation

This is one of the few package that I install globally because I use it all the time and not always in the context of a virtualenv.

1
pip install Fabric

Usage

Once Fabric is installed you can use the command called "fab" to run the tasks defined in the "fabfile.py". The tasks can be chained and like this

1
fab machine environment  my-task

In the example above machine, environment, my-task are 3 tasks defined in your "fabfile.py". I used the first 2 tasks to set some environment variable that are used by the third task "my-task" to actually do something useful.

You can also pass argument to you task

1
fab my-task:arg1="my first argument"

Writing a task

Writing a fabric task is as simple as writing a python method, Fabric comes with a set of small wrapper that will help you to get things done quickly : local, run, cd, ..

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from uuid import uuid1
from os import path
from fabric.api import *

def localhost():
    env.hosts = ['localhost']

def example():
    env.hosts = ['example.com']

def project_settings():
    env.db_user = '<database Username>'
    env.webapps = '/opt/webapps/'
    env.backups = '/opt/backups/'
    env.www = '/var/www/'
    env.project_name = 'example-project'
    env.test_settings = 'project.conf.dev.settings'
    env.static_cache = path.join('project_cms','themes','example',
                                 'static','CACHE')        
    env.pip_requirements = 'requirements.pip'

def prod():
    env.site = 'example.com'
    env.db_name = env.site
    env.settings = 'project_cms.conf.prod.settings'
    project_settings()

def dev():
    env.site = 'dev.example.com'
    env.db_name = env.site
    env.settings = 'project_cms.conf.dev.settings'
    project_settings()

def backup_db(identifier=None, db_name=None, db_user=None,
              site=None, backups=None):
    """
    Backup db
    """
    db_name = db_name or env.db_name
    db_user = db_user or env.db_user
    site = site or env.site
    backups = backups or env.backups

    backup_file = "%s-dump-%s.sql" % (identifier or uuid1(), db_name)
    backup_site = path.join(backups, site)
    with cd(backup_site):
        run("pg_dump -U %s %s > %s" % (db_user, db_name, backup_file))

def backup_media(identifier=None,backups=None,
                 www=None, site=None):
    """
    Back up the media directory
    """
    www = www or env.www
    site = site or env.site
    backups = backups or env.backups

    backup_file = path.join(backups,site,
                            "%s-media.tar.bz2" % (identifier or uuid1()))
    with cd(path.join(www,site)):
        run("tar -cjf %s media/" %(backup_file))

The example above shows how fabric can be used, as you can read each task aim to automate a particular activity. You should have a task for all your installation / configuration / deployment / backup / restore. This will enable you to write some macro task like :

1
fab example prod install

or

1
fab example prod delete

The above tasks can be used like this :

1
fab  example dev backup_db

This will execute a backup of the db on example.com via ssh. I usually have a complete automation of all the activity done on my servers. Do not be afraid of having a large fabfiles.py, this is just python so you can organize it in modules just like you would do with the rest of your code.

Conclusion

This article just scratch the tip of the iceberg and only cover 20 % of the Fabric package however they are the one I use 80 % of the time. I hope that you find this article useful and I would be glad to hear from you if you can improve this article.

blog comments powered by Disqus

Entry Details

Published: Mar 15, 2010 at 12:51 PM

© 2009 - 2012 Yann Malet