def chown(): """ Fix project directory permissions after an initial deploy. """ with settings(remote_path='/tmp'): print(cyan('\nFixing permissions...')) do('chown -R tobias:tobias /srv/www/app')
def test(): """Run unit tests""" print(cyan("\nRunning tests...")) do( "export FLASK_CONFIG=config/test.py && %s/bin/nosetests --exclude-dir-file='.noseexclude' --with-yanc --with-spec --spec-color -q --nocapture" % venv_path )
def project(): """ Set up project directory. """ with settings(remote_path='/tmp'): # Set up project directory print(cyan('\nSetting up project directory...')) do('mkdir -p /srv/www/app')
def software(): """ Install required software. """ with settings(remote_path='/tmp'): # Install prerequisites print(cyan('\nInstalling software...')) do('apt-get -qq update') do('apt-get -qq install -y puppet git')
def build(): """Build or update the virtualenv.""" with settings(hide('stdout')): print(cyan('\nUpdating venv, installing packages...')) do('[ -e %s ] || virtualenv %s --distribute --no-site-packages' % (venv_path, venv_path)) # annoyingly, pip prints errors to stdout (instead of stderr), so we # have to check the return code and output only if there's an error. with settings(warn_only=True): pip = do('%s/bin/pip install -r requirements.txt' % venv_path, capture=True) if pip.failed: print(red(pip)) abort("pip exited with return code %i" % pip.return_code)
def run(debug=False): """ Apply Puppet manifest. """ check_syntax() print cyan("\nApplying puppet manifest...") if debug: debug = "--debug" else: debug = "" do("sudo /usr/bin/puppet apply puppet/manifests/default.pp " "--modulepath=puppet/modules {0}".format(debug))
def drop(db_name=None, warn=True): if not db_name: abort('You must provide a database name') if warn is True: print('\nYou are about to drop the database ' + yellow('%s' % db_name, bold=True)) if not confirm('Continue?', default=False): abort('User aborted') if _pg_db_exists(db_name): do('dropdb %s' % db_name)
def user(): """ Add and configure deploy user. """ with settings(remote_path='/tmp'): # Set up deploy user print(cyan('\nSetting up deploy user...')) with settings(hide('warnings'), warn_only=True): do('useradd tobias') do('[ -e /home/tobias ] || cp -r /etc/skel /home/tobias') # Copy authorized_keys from the current user into deploy user's home do('mkdir -p /home/tobias/.ssh') do('[ -e ~/.ssh/authorized_keys ] && cp ~/.ssh/authorized_keys /home/tobias/.ssh/') do('chown -R tobias:tobias /home/tobias')
def build(): """ Run application build tasks. """ # Generate static assets. Note that we always build assets with the # production config because dev will never point to compiled files. print(cyan('\nBuilding static assets...')) do('mkdir -p app/static/assets/css') do('mkdir -p app/static/assets/js') do('export FLASK_CONFIG=config/production.py && %s/bin/python manage.py build' % venv_path)
def build(db_name=None, config=None): """Initialise and migrate database to latest version.""" if db_name: DB['name'] = db_name config_export = '' if config: config_export = 'FLASK_CONFIG=config/%s.py ' % config print(cyan('\nUpdating database...')) # Ensure database exists if not _pg_db_exists(DB['name']): do('createdb -O \'%(user)s\' \'%(name)s\'' % DB) # Ensure versions folder exists do('mkdir -p db/versions') # Run migrations do('%s%s/bin/alembic -c db/alembic.ini upgrade head' % (config_export, venv_path))
def build(): """ Run application build tasks. """ # Ensure all base files exist do("mkdir -p app/static/assets/tmp") do("touch app/static/assets/tmp/mustache-compiled-templates.min.js") # Bower install print(cyan("\nRunning bower install...")) do("npm_config_loglevel=error bower install") do("npm_config_loglevel=error bower list --paths > app/static/assets/tmp/bower-paths.json") for path in json.loads(open("app/static/assets/tmp/bower-paths.json").read()).values(): do("mkdir -p app/static/assets/%s" % os.path.dirname(path)) do("cp %s app/static/assets/%s" % (path, path)) # Generate static assets. Note that we always build assets with the # production config because dev will never point to compiled files. print(cyan("\nGenerating static assets...")) do("export FLASK_CONFIG=config/production.py && %s/bin/python manage.py mustache_compile" % venv_path) do("export FLASK_CONFIG=config/production.py && %s/bin/python manage.py assets clean" % venv_path) do("export FLASK_CONFIG=config/production.py && %s/bin/python manage.py assets -v build" % venv_path)
def run(): """Apply Puppet manifest.""" check() print(cyan('\nApplying puppet manifest...')) do('sudo /usr/bin/puppet apply --modulepath="/srv/www/app/puppet/modules" "/srv/www/app/puppet/manifests/site.pp"')
def check(): """Syntax check on Puppet config.""" print(cyan('\nChecking puppet syntax...')) do('find puppet -type f -name \'*.pp\' |xargs puppet parser validate')
def check_syntax(): """ Syntax check on Puppet config. """ print cyan("\nChecking puppet syntax...") do("find puppet -type f -name '*.pp' | xargs puppet parser validate")
def run(): """Start app in debug mode (for development).""" do('export FLASK_CONFIG=config/dev.py && %s/bin/python manage.py runserver' % venv_path)
def stop(): """Stop app using init.""" do("sudo stop gunicorn")
def test(): """Run unit tests""" print(cyan('\nRunning tests...')) do('FLASK_CONFIG=config/test.py %s/bin/nosetests --exclude-dir-file=\'.noseexclude\' --with-yanc --with-spec --spec-color -q' % venv_path)
def run(): """Start app in debug mode (for development).""" do("export FLASK_CONFIG=config/dev.py && %s/bin/python manage.py runserver" % venv_path)
def coverage(): """Generate test coverage report""" do( "export FLASK_CONFIG=config/test.py && %s/bin/nosetests --exclude-dir-file='.noseexclude' --with-cov --cov=app --cov-report=html" % venv_path )
def build(): """Initialise and migrate database to latest version.""" print(cyan('\nUpdating database...')) # Ensure database exists if not _pg_db_exists(DB['name']): do('createdb -O \'%(user)s\' \'%(name)s\'' % DB) # Ensure versions folder exists do('mkdir -p db/versions') do('rm -f db/versions/*.pyc') # Run migrations do('%s/bin/alembic -c db/alembic.ini upgrade head' % venv_path) # Ensure www-data has permission on all objects do('psql -tAc \'GRANT ALL ON ALL TABLES IN SCHEMA public TO "%(user)s";\' %(name)s' % DB) do('psql -tAc \'GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO "%(user)s";\' %(name)s' % DB) do('psql -tAc \'ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO GROUP "%(user)s";\' %(name)s' % DB) do('psql -tAc \'ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO GROUP "%(user)s";\' %(name)s' % DB)
def restart(): """Restart app using init.""" do('sudo restart gunicorn')
def stop(): """Stop app using init.""" do('sudo stop gunicorn')
def start(): """Start app using init.""" do('sudo start gunicorn')
def coverage(): """Generate test coverage report""" do('FLASK_CONFIG=config/test.py %s/bin/nosetests --exclude-dir-file=\'.noseexclude\' --with-cov --cov=app --cov-report=html' % venv_path)
def stop(): """Stop app using init.""" do('sudo stop uwsgi')
def start(): """Start app using init.""" do("sudo start gunicorn")
def freeze(): """Build app as static site""" do('export FLASK_CONFIG=config/dev.py && %s/bin/python manage.py freeze' % venv_path)
def restart(): """Restart app using init.""" do("sudo restart gunicorn")
def gh_pages(): # switch branch do('git checkout gh-pages') # get rid of everything currently commited to that branch # except .gitignore. this won't get rid of frozen/ # as long as it's not been commited by mistake do('git ls-tree gh-pages --name-only |grep -v .gitignore |xargs rm -rf') # copy eveything in frozen/flask-static-blog/ to the top level do('cp -r frozen/flask-static-blog/* .') # get rid of the old copies do('rm -rf frozen/flask-static-blog/') # add, add -u, commit and push do('git add .') do('git add -u') with settings(warn_only=True): do('git commit -am "fab test"') do('git push -f origin gh-pages') do('git checkout master')
def start(): """Start app using init.""" do('sudo start uwsgi')
def build(): """ Run application build tasks. """ # Ensure all base files exist do('mkdir -p app/static/assets/tmp') do('touch app/static/assets/tmp/mustache-compiled-templates.min.js') # Bower install print(cyan('\nRunning bower install...')) do('npm_config_loglevel=error bower install') do('npm_config_loglevel=error bower list --paths > app/static/assets/tmp/bower-paths.json' ) for path in json.loads( open('app/static/assets/tmp/bower-paths.json').read()).values(): do('mkdir -p app/static/assets/%s' % os.path.dirname(path)) do('cp %s app/static/assets/%s' % (path, path)) # Generate static assets. Note that we always build assets with the # production config because dev will never point to compiled files. print(cyan('\nGenerating static assets...')) do('export FLASK_CONFIG=config/production.py && %s/bin/python manage.py mustache_compile' % venv_path) do('export FLASK_CONFIG=config/production.py && %s/bin/python manage.py assets clean' % venv_path) do('export FLASK_CONFIG=config/production.py && %s/bin/python manage.py assets -v build' % venv_path)
def _pg_db_exists(database): """ Helper function to check if the postgresql database exists. """ with settings(hide('running', 'warnings'), warn_only=True): return do('psql -tAc "SELECT 1 FROM pg_database WHERE datname = \'%s\'" postgres |grep -q 1' % database, capture=True).succeeded
def reload(): """Restart app using init.""" do('sudo reload uwsgi')
def serve_frozen(): """Serve static site up on development server""" do('export FLASK_CONFIG=config/dev.py && %s/bin/python manage.py serve_frozen' % venv_path)
def generate(message=None): """Generates a new Alembic revision based on DB changes.""" args = '' if message: args = '-m "%s"' % message do('%s/bin/alembic -c db/alembic.ini revision --autogenerate %s' % (venv_path, args))
def run(): """Start app in debug mode (for development).""" do('%s/bin/python manage.py runserver' % venv_path)
def check_syntax(): """ Syntax check on Puppet config. """ print cyan('\nChecking puppet syntax...') do("find puppet -type f -name '*.pp' | xargs puppet parser validate")