Pythonic Application Deployment

I have been reading up on deployment tools like Fabric and zc.buildout recently. This is an area I don’t have much prior experience, although many of the problems are familiar. Probably the most well known tool in this category is Capistrano, but I would like to see a Python alternative as well for ease of hacking (or really, saving me from learning Ruby for a while). There are also other alternatives which are about managing things more like an inventory rather than thinking of deployment. Jeff Forcier pointed out Puppet, but that might be an overkill for my situation and it would also duplicate some functionality provided by some deployed systems.

Fabric seemed nice because of its simplicity. It is a new project, and pretty small still, so you can quickly read through the code to see what it does if the online documentation doesn’t cover what you are looking for. However, as Fabric currently stands, it isn’t really ideal for my deployment situation where different things need to be installed on different computers running different operating systems with different directory layouts and so on. Fabric wants to execute the same sets of steps on a bunch of machines. This can of course be worked around by writing individual fabfiles for each computer that needs to be setup. There is also the problem of deploying to staging and production environments, but Fabric’s implied solution is to write different fabfiles for each environment. This can be worked around rather easily by writing the environment settings into .ini files, specifying the location in an environment variable, and reading them with configobj. It would be even better if you could pass the location on the command line, but alas that isn’t supported. So this is how you would do deployment:

FAB_OPTS=staging.ini fab deploy

The fabfile.py would then need some boilerplate, or you could put the boilerplate into a config.py file:

import os, sys
from configobj import ConfigObj
 
FAB_OPTS ='DEPLOYMENT_CONFIG'
 
try:
    fab_opts = os.environ[FAB_OPTS]
except KeyError:
    sys.exit('%s needs to be set to point to deployment config file' % FAB_OPTS)
 
try:
    config = ConfigObj(fab_opts, file_error=True)
except IOError:
    sys.exit('%s does not point to valid config file' % FAB_OPTS)
 
user = config['main']['user']
hosts = config['main']['hosts']
installdir = config['main']['installdir']

which you can then load() in your fabfile.py:

load('/path/to/config.py')

Christian Vest Hansen also showed how to effectively load options with just Fabric by using variables, the load() function and passing using: parameter on the command line. While neat, I think I have a slight preference for configobj.

Fabric seems suitable for deploying my personal projects, but it seems I need to do some more reading on zc.buildout, and actually try it out.

Similar Posts:

    None Found

2 Comments

  1. Jeff:

    You should check out bcfg2 at bcfg2.org. It is written in python.

    Bcfg2 takes a different approach than cfengine and puppet. Instead of writing code to do something, you write an xml specification of how you want the system to look. Bcfg2 checks the target system against the specification and installs any packages, files, or services that do not match. Then it reports if anything wasn’t able to be installed correctly. With the others, there is not an integrated way of verifying that your changes got deployed properly.

    We’re using it to deploy and manage about 175 Ubuntu workstations and 2 Ubuntu servers. We are able to specify that particular computers or groups of computers should get one configuration file or package while others get something completely different.

    There is active development, and the developers are receptive of bug reports and patches.

  2. Heikki Toivonen:

    Thanks, I had never heard of that. Definitely worth a look.