This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description

Quickstart

There is full working example: https://github.com/vmihailenco/fabdeploy-example.

Create fabconf.py:

from fabdeploy.api import DefaultConf

class BaseConf(DefaultConf):
    django_dir = 'project_name'

class StagingConf(BaseConf):
    address = 'user@staging-host.com'

class ProdConf(BaseConf):
    address = 'user@prod-host.com'

Create fabfile.py:

from fabdeploy import monkey; monkey.patch_all()
from fabric.api import *
from fabdeploy.api import *; setup_fabdeploy()


@task
def user_create():
    users.create.run()
    ssh.push_key.run(pub_key_file='~/.ssh/id_rsa.pub')

@task
def deploy():
    pass

Fabdeploy uses two system (linux) users:

  • sudo_user to perform tasks that require sudo right (root by default).
  • user for other tasks (SSH user by default).

In Ubuntu root user is disabled by default. You can create special fabdeploy user using following command:

fab fabd.default_conf:address=user@host,sudo_user=user fabd.create_user

Then you should tell fabdeploy to use new sudo_user:

class ProdConf(BaseConf):
    sudo_user = 'fabdeploy'

List of available tasks:

fab --list

List of available variables:

fab fabd.debug

This is useful to test configuration:

$ fab fabd.conf:prod fabd.debug:django_path
/home/prj/src/prj

or:

$ fab fabd.conf:prod fabd.debug:cpu_count
2

or:

$ fab fabd.conf:prod fabd.debug:current_time
2011.11.27-13.40

To deploy project you may use:

$ fab fabd.conf:staging deploy
$ fab fabd.conf:prod deploy

Examples

Control where logs are stored

fabconf.py:

from fabdeploy.api import DefaultConf

class ProdConf(DefaultConf):
    my_task__log_path = '/var/log/my_task'

fabfile.py:

from fabdeploy.api import Task

class MyTask(Task):
    def do(self):
        print self.conf.log_path

my_task = MyTask()

Output:

$ fab fabd.conf:prod my_task
/var/log/my_task

You can also temporarily set log path:

$ fab fabd.conf:prod my_task:log_path='/var'
/var

This works for all variables and all tasks.

Multiple databases

fabconf.py:

from fabdeploy.api import DefaultConf

class ProdConf(DefaultConf):
    # default DB
    db_name = 'name1'
    db_user = 'user1'
    db_password = 'pass1'
    # logging DB
    loggingdb__db_name = 'name2'
    loggingdb__db_user = 'user2'
    loggingdb__db_password = 'pass2'

fabfile.py:

from fabdeploy import postgres

@task
def dump_db():
    postgres.dump.run()  # dump default DB
    postgres.dump.run(_namespace='loggingdb__')  # dump logging DB

Built-in tasks customization

Fabdeploy is written to be highly configurable. For example, there is built-in tar task, which by default packs whole project, uploads it to server and unpacks it there.

But you can freely use it to upload custom dirs:

from fabdeploy import tar

@task
def push_static():
    tar.push.run(
        src_dir=os.path.join(env.conf.django_ldir, 'static'),
        target_dir=posixpath.join(env.conf.django_dir, 'static'))

Different DBs for development and production

fabconf.py:

from fabdeploy import api
from fabdeploy.api import DefaultConf

class DevConf(DefaultConf):
    address = 'user@localhost'
    db = getattr(fabdeploy, 'mysql')

class ProdConf(DefaultConf):
    address = 'user@localhost'
    db = getattr(fabdeploy, 'postgres')

fabfile.py:

@task
def execute():
    print env.conf.db.execute

Configuration

There are some conventions how to configure fabdeploy:

  • You should extend DefaultConf:

    from fabdeploy.api import DefaultConf
    
    class BaseConf(DefaultConf):
        pass
    
  • Each value can contain Python formatting:

    class BaseConf(DefaultConf):
        supervisor__log_dir = '%(var_dir)s/log/supervisor'
    
  • Remote pathes should have posfix _path. You can and should use task fabd.mkdirs to create all remote dirs with one command. It will look like this:

    $ fab fabd.conf:staging_conf fabd.mkdirs
    mkdir --parents /path/to/dir1 /path/to/dir2 /path/to/dir3
    
  • Remote dirs (e.g. var) have postfix _dir.

  • Local pathes have postfix _lpath. Local dirs have postfix _ldir. This is similar to Fabric cd and lcd tasks.

  • Dirs (postfix _dir and _ldir) and pathes (postfix _path and _lpath) can be Python lists. These lists will be passed to os.path.join() or posixpath.join(). Previous example can look like this:

    from fabdeploy.api import DefaultConf
    
    class BaseConf(DefaultConf):
        supervisor__log_dir = ['%(var_dir)s', 'log', 'supervisor']
    
  • Function can be decorated with conf decorator. For example, current_time task looks like this:

    from fabdeploy.api import DefaultConf
    
    class BaseConf(DefaultConf):
        @conf
        def current_time(self):
            return datetime.datetime.utcnow().strftime(self.time_format)
    

    You can use it in your task like this:

    from fabdeploy.api import Task
    
    class MyTask(Task):
        def do(self):
            puts(self.conf.current_time)
    
  • You can configure each task individually:

    class BaseConf(DefaultConf):
        postgres__db_name = 'postgresql_db'  # module=postres
        mysql__db_name = 'mysql_db'          # module=mysql
        mysql__create_db__db_user = 'root'   # module=mysql, task=create_db
    

Configuration is stored in task instance variable self.conf. Each task has its own copy of configuration. Configuration variables are searched in following places:

  • task keyword argument var (fab task:foo=bar);
  • task instance method var() decorated with @conf();
  • key var in env.conf, which is populated by fabd.conf task;
  • ask user to provide variable var using fabric prompt.

Global configuration is stored in env.conf.

Writing your task

Your task is class-based fabric class except fabdeploy manages configuration for you:

from fabric.api import puts
from fabdeploy.api import Task, conf

class MessagePrinter(Task):
    @conf
    def message(self):
        if 'message' in self.conf:
            return self.conf.message
        return 'Hi!'

    def do(self):
        if self.conf.secret == '123':
            puts(self.conf.message)
        else:
            puts('huh?')

message_printer = MessagePrinter()

Then you can run this task like this:

$ fab message_printer
> secret = 123
Hi!
$ fab message_printer:message='Hello world!'
> secret = 123
Hello world!

Fabfile example

Typical fabfile may look like this:

from fabdeploy import monkey; monkey.patch_all()
from fabric.api import *
from fabdeploy.api import *; setup_fabdeploy()

@task
def install():
    users.create.run()
    ssh.push_key.run(pub_key_file='~/.ssh/id_rsa.pub')

    system.setup_backports.run()
    system.install_common_software.run()

    with settings(warn_only=True):
        postgres.create_role.run()
        postgres.create_db.run()
        postgres.grant.run()

    nginx.install.run()

    for app in ['supervisor']:
        pip.install.run(app=app)


@task
def setup():
    fabd.mkdirs.run()

    nginx.push_gunicorn_config.run()
    nginx.restart.run()

    supervisor.d()


@task
def deploy():
    fabd.mkdirs.run()
    release.create.run()

    postgres.dump.run()

    git.init.run()
    git.push.run()

    supervisor.push_configs.run()
    django.push_settings.run()
    gunicorn.push_config.run()

    virtualenv.create.run()
    virtualenv.pip_install_req.run()
    virtualenv.pip_install.run(app='gunicorn')
    virtualenv.make_relocatable.run()

    django.syncdb.run()
    django.migrate.run()
    django.collectstatic.run()

    release.activate.run()

    supervisor.update.run()
    supervisor.restart_program.run(program='celeryd')
    gunicorn.reload_with_supervisor.run()
Release History

Release History

0.4

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.7

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.6

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.5

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.4

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.3

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
django-fabdeploy-plus-0.4.tar.gz (23.9 kB) Copy SHA256 Checksum SHA256 Source May 28, 2012

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting