├── djangofab ├── __init__.py ├── vcs │ ├── __init__.py │ ├── git.py │ └── svn.py ├── fab.cfg ├── decorator.py ├── api.py ├── util.py └── django.py ├── .gitignore ├── MANIFEST.in ├── AUTHORS ├── examples ├── fab.cfg ├── fabfile-svn.py └── fabfile-git.py ├── setup.py └── README.rst /djangofab/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /djangofab/vcs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | django_fab.egg-info 3 | dist 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include examples/* 2 | include README.rst 3 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Ordered by date of first contribution: 2 | Harley Bussell 3 | Steve Steiner 4 | -------------------------------------------------------------------------------- /examples/fab.cfg: -------------------------------------------------------------------------------- 1 | [default] 2 | django.settings=website.settings 3 | giturl=server:/var/git/project 4 | svnurl=svn+ssh://server/var/svn/project 5 | dev_path=/var/projects/project/dev/ 6 | prod_path=/var/projects/project/prod 7 | -------------------------------------------------------------------------------- /djangofab/fab.cfg: -------------------------------------------------------------------------------- 1 | [default] 2 | django.settings=website.settings 3 | giturl=mail:/var/projects/aurealty-platform 4 | dev_path=/var/www/vhosts/aurealty.com/project/aurealty-platform 5 | prod_path=/var/www/vhosts/aurealty.com/project/aurealty-platform 6 | -------------------------------------------------------------------------------- /djangofab/decorator.py: -------------------------------------------------------------------------------- 1 | 2 | def user_settings(file='fab.cfg', group='default'): 3 | "Decorator to load user settings from a config file into the env" 4 | from djangofab.util import apply_settings 5 | def wrap(f=None): 6 | def wrapped_f(*args): 7 | f(*args) 8 | apply_settings(file,group) 9 | return wrapped_f 10 | return wrap 11 | 12 | 13 | -------------------------------------------------------------------------------- /djangofab/api.py: -------------------------------------------------------------------------------- 1 | from fabric.api import * 2 | from fabric.context_managers import * 3 | from fabric.operations import _handle_failure 4 | #from djangofab.vcs.git import update_remote, update_local, push, commit, add 5 | from djangofab.decorator import user_settings 6 | from djangofab.util import local as local, apply_settings 7 | from djangofab.django import get_remote_db, put_local_db, change_ownership, touch_wsgi 8 | 9 | from fabric.main import _internals 10 | _internals.append(apply_settings) 11 | _internals.append(user_settings) 12 | _internals.append(contextmanager) 13 | _internals.append(nested) 14 | _internals.append(local) 15 | -------------------------------------------------------------------------------- /djangofab/util.py: -------------------------------------------------------------------------------- 1 | import os 2 | import ConfigParser 3 | #from djangofab.api import * 4 | from fabric.api import * 5 | from fabric.operations import local as _local 6 | 7 | def local(cmd): 8 | if hasattr(env,'capture_default'): 9 | _local(cmd, env.capture_default) 10 | else: 11 | _local(cmd) 12 | 13 | def apply_settings(file='fab.cfg', group='default'): 14 | if not os.path.exists(file): 15 | _handle_failure(message='Configuration file %s does not exist' % file) 16 | return 17 | config = ConfigParser.ConfigParser() 18 | config.readfp(open(file)) 19 | user_settings = {} 20 | os.environ['DJANGO_SETTINGS_MODULE'] = config.get(group,'django.settings') 21 | for name,value in config.items(group): 22 | user_settings[name] = value 23 | for key in env: 24 | if env[key] and isinstance(env[key],str): 25 | env[key] = env[key] % user_settings 26 | 27 | -------------------------------------------------------------------------------- /djangofab/vcs/git.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | from djangofab.api import * 3 | import os 4 | 5 | def update_remote(): 6 | "Update remote checkout to the latest version" 7 | with cd(env.path): 8 | run('git reset --hard') 9 | run('git pull') 10 | 11 | def update_app(): 12 | "Update remote checkout to the latest version" 13 | app = prompt('app name?') 14 | #with cd(os.path.join(os.path.dirname(env.path),'src',app)): 15 | with cd(os.path.join(env.virtualenv,'src',app)): 16 | run('git reset --hard') 17 | run('git pull origin master') 18 | 19 | def push(): 20 | "Pull changes from version control" 21 | local('git push') 22 | 23 | def update_local(): 24 | "Pull changes from version control" 25 | local('git pull') 26 | 27 | def commit(): 28 | "Save changes to version control" 29 | local('git commit -a') 30 | 31 | def add(file): 32 | "Add files to the repository" 33 | local('git add %s' %file) 34 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import os 3 | def read(fname): 4 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 5 | 6 | setup(name='django-fab', 7 | version='1.0.4', 8 | description='Common methods to help create fabric deplopment scripts for django', 9 | long_description=read('README.rst'), 10 | author='Harley Bussell', 11 | author_email='modmac@gmail.com', 12 | url='http://github.com/hbussell/django-fab', 13 | classifiers=[ 14 | "License :: OSI Approved :: GNU General Public License (GPL)", 15 | "Programming Language :: Python", 16 | "Development Status :: 4 - Beta", 17 | "Intended Audience :: Developers", 18 | "Framework :: Django", 19 | "Environment :: Console", 20 | "Topic :: Software Development", 21 | "Topic :: System :: Software Distribution" 22 | 23 | ], 24 | keywords='django fabric deployment', 25 | zip_safe=False, 26 | license='GPL', 27 | install_requires=[ 28 | 'setuptools', 29 | ], 30 | packages = find_packages(), 31 | include_package_data = True, 32 | ) 33 | -------------------------------------------------------------------------------- /examples/fabfile-svn.py: -------------------------------------------------------------------------------- 1 | from djangofab.api import * 2 | from djangofab.vcs.svn import update_remote, update_local, commit, add 3 | env.capture_default = False 4 | 5 | #use the default section of fab.cfg 6 | @user_settings() 7 | def prod(): 8 | "Production settings" 9 | env.hosts = ['server1'] 10 | env.path = '%(prod_path)s' 11 | env.svnurl = '%(svnurl)s' 12 | env.site_user = 'owner' 13 | env.site_group = 'group' 14 | 15 | @user_settings() 16 | def dev(): 17 | "Development settings" 18 | env.hosts = ['server1'] 19 | env.path = '%(dev_path)s' 20 | env.svnurl = '%(svnurl)s' 21 | env.site_user = 'owner' 22 | env.site_group = 'group' 23 | 24 | #use the local section 25 | @user_settings('fab.cfg','local') 26 | def localhost(): 27 | "Local settings" 28 | env.path = '%(dev_path)s' 29 | env.svnurl = '%(svnurl)s' 30 | 31 | def deploy(): 32 | "Push local changes and update checkout on the remote host" 33 | update_remote() #this will update a checkout 34 | #remote_export() 35 | change_ownership() 36 | touch_wsgi() 37 | -------------------------------------------------------------------------------- /djangofab/vcs/svn.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import with_statement 3 | from djangofab.api import * 4 | 5 | def update_remote(): 6 | "Update remote checkout to the latest version" 7 | with cd(env.path): 8 | if not remote_checkout_exists(): 9 | run('svn co %s %s' % (env.svnurl, env.path)) 10 | run('svn update') 11 | 12 | def remote_export(): 13 | "Update remote checkout to the latest version" 14 | with cd(env.path): 15 | run('svn export %s %s' % (env.svnurl, env.svnpath)) 16 | 17 | def update_local(): 18 | "Pull changes from version control" 19 | local('svn update') 20 | 21 | def commit(): 22 | "Save changes to version control" 23 | local('svn commit') 24 | 25 | def add(file): 26 | "Add files to the repository" 27 | local('svn add %s' %file) 28 | 29 | def checkout_local(): 30 | local('svn co %s %s' % (env.svnurl, env.path)) 31 | 32 | def remote_checkout_exists(): 33 | #with cd(env.path): 34 | out = run('ls -a | grep svn').strip() 35 | if out=='.svn': 36 | return True 37 | return False 38 | -------------------------------------------------------------------------------- /examples/fabfile-git.py: -------------------------------------------------------------------------------- 1 | from djangofab.api import * 2 | from django.conf import settings 3 | from djangofab.vcs.git import update_remote, update_local, push, commit, add 4 | env.capture_default = False 5 | 6 | # apply the settings from fab.cfg default section 7 | # sets DJANGO_SETTINGS which allows access to django.conf.settings values 8 | apply_settings() 9 | 10 | #use the default section of fab.cfg 11 | @user_settings() 12 | def prod(): 13 | "Production settings" 14 | env.hosts = ['server1'] 15 | env.path = '%(prod_path)s' 16 | env.giturl = '%(giturl)s' 17 | env.site_user = 'owner' 18 | env.site_group = 'group' 19 | 20 | @user_settings() 21 | def dev(): 22 | "Development settings" 23 | env.hosts = ['server1'] 24 | env.path = '%(dev_path)s' 25 | env.giturl = '%(giturl)s' 26 | env.site_user = 'owner' 27 | env.site_group = 'group' 28 | 29 | #use the local section 30 | @user_settings('fab.cfg','local') 31 | def localhost(): 32 | "Local settings" 33 | env.path = '%(dev_path)s' 34 | env.giturl = '%(giturl)s' 35 | 36 | def deploy(): 37 | "Push local changes and update checkout on the remote host" 38 | push() 39 | update_remote() # reset and pull on the remote server 40 | #remote_export() 41 | change_ownership() 42 | touch_wsgi() 43 | 44 | def test(): 45 | print "website using database %s " % (settings.DATABASE_NAME,) 46 | 47 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | django-fab 3 | ========== 4 | 5 | Common methods to help create fabric deplopment scripts for django 6 | 7 | The idea is to allow you to use a fabfile.py that has just the unique things for your specific project, while taking advantage of common functions for version control and django tasks. 8 | 9 | You can also move configuration out of the fabfile.py into ini style configuration files. 10 | 11 | 12 | Installation :: 13 | 14 | sudo easy_install django-fab 15 | sudo easy_install http://git.fabfile.org/cgit.cgi/fabric/snapshot/fabric-0.9b1.tar.gz 16 | 17 | git example fabfile.py :: 18 | 19 | from djangofab.api import * 20 | from django.conf import settings 21 | from djangofab.vcs.git import update_remote, update_local, push, commit, add 22 | env.capture_default = False 23 | 24 | # apply the settings from fab.cfg default section 25 | # sets DJANGO_SETTINGS which allows access to django.conf.settings values 26 | apply_settings() 27 | 28 | #use the default section of fab.cfg 29 | @user_settings() 30 | def prod(): 31 | "Production settings" 32 | env.hosts = ['server1'] 33 | env.path = '%(prod_path)s' 34 | env.giturl = '%(giturl)s' 35 | env.site_user = 'owner' 36 | env.site_group = 'group' 37 | 38 | @user_settings() 39 | def dev(): 40 | "Development settings" 41 | env.hosts = ['server1'] 42 | env.path = '%(dev_path)s' 43 | env.giturl = '%(giturl)s' 44 | env.site_user = 'owner' 45 | env.site_group = 'group' 46 | 47 | #use the local section 48 | @user_settings('fab.cfg','local') 49 | def localhost(): 50 | "Local settings" 51 | env.path = '%(dev_path)s' 52 | env.giturl = '%(giturl)s' 53 | 54 | def deploy(): 55 | "Push local changes and update checkout on the remote host" 56 | push() 57 | update_remote() # reset and pull on the remote server 58 | #remote_export() 59 | change_ownership() 60 | touch_wsgi() 61 | 62 | def test(): 63 | print "website using database %s " % (settings.DATABASE_NAME,) 64 | 65 | 66 | 67 | Requries fabric>=0.9 68 | http://git.fabfile.org/cgit.cgi/fabric/snapshot/fabric-0.9b1.tar.gz 69 | 70 | See fabric docs 71 | http://docs.fabfile.org/ 72 | -------------------------------------------------------------------------------- /djangofab/django.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import with_statement 3 | import os 4 | from djangofab.api import * 5 | 6 | def get_remote_db(): 7 | "Download the latest database from the server and load it onto your local database" 8 | dbsettings = get_db_settings() 9 | with cd(env.path): 10 | if dbsettings['engine']=='mysql': 11 | run('mysqldump -u%(user)s -p%(pass)s %(name)s > database' % dbsettings ) 12 | elif dbsettings['engine']=='postgresql' or dbsettings['engine']=='postgresql_psycopg2': 13 | run('psql -u%(user)s -p%(pass)s %(name)s > database' % dbsettings) 14 | 15 | get(env.path+'/database', 'database') 16 | if dbsettings['engine']=='mysql': 17 | local('echo "create database if not exists %(name)s;" | mysql -u%(user)s -p%(pass)s' % dbsettings) 18 | local('mysql -u%(user)s -p%(pass)s %(name)s < database' % dbsettings) 19 | elif dbsettings['engine']=='postgresql' or dbsettings['engine']=='postgresql_psycopg2': 20 | run('echo "create database if not exists %(name)s;" | psql -u%(user)s -p%(pass)s' % dbsettings) 21 | 22 | def put_local_db(): 23 | "Dump your local database and load it onto the servers databse" 24 | dbsettings = get_db_settings() 25 | if dbsettings['engine']=='mysql': 26 | local('mysqldump -u%s -p%s %s > database' %\ 27 | (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)) 28 | put('database', 'database') 29 | local('mysql -u%s -p%s %s < database' %\ 30 | (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)) 31 | elif dbsettings['engine']=='postgresql' or dbsettings['engine']=='postgresql_psycopg2': 32 | local('mysqldump -u%s -p%s %s > database' %\ 33 | (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)) 34 | put('database', 'database') 35 | local('mysql -u%s -p%s %s < database' %\ 36 | (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)) 37 | 38 | def get_db_settings(): 39 | try: 40 | from fabfile import settings 41 | except ImportError: 42 | msg = 'Please import django settings in your fabfile.py \nfrom django.conf import settings' 43 | _handle_failure(message=msg) 44 | if not 'DJANGO_SETTINGS_MODULE' in os.environ: 45 | msg = 'DJANGO_SETTINGS_MODULE not set \nYou must call a settings function that sets the os.environ[DJANGO_SETTINGS_MODULE] first' 46 | _handle_failure(message=msg) 47 | if not hasattr(settings, 'DATABASE_USER'): 48 | # global settings is not the django settings 49 | msg = 'Please import django settings in your fabfile.py \nfrom django.conf import settings' 50 | _handle_failure(message=msg) 51 | return {'user': settings.DATABASE_USER, 'pass':settings.DATABASE_PASSWORD, \ 52 | 'name':settings.DATABASE_NAME,'engine':settings.DATABASE_ENGINE} 53 | 54 | 55 | def change_ownership(): 56 | "Set user and group ownership on the website path" 57 | with cd(env.path): 58 | sudo('chown %s.%s -R .' % (env.site_user, env.site_group,)) 59 | sudo('chmod ug+rw -R .') 60 | 61 | def touch_wsgi(): 62 | "Touch the wsgi file to trigger wsgi to reload the processes." 63 | with cd(env.path): 64 | #run("touch bin/django.wsgi") 65 | run("touch %s" % env.wsgi) 66 | 67 | def syncdb(): 68 | "Sync database and run" 69 | pass 70 | 71 | 72 | 73 | --------------------------------------------------------------------------------