Refactoring deployment to include non-standard web apps that need a slightly different deployment.

This commit is contained in:
Samuel Clay 2015-12-20 14:11:37 -08:00
parent 5c7d39d032
commit 9cdf0cfaa2

85
fabfile.py vendored
View file

@ -39,6 +39,8 @@ env.VENDOR_PATH = "/srv/code"
env.user = 'sclay' env.user = 'sclay'
env.key_filename = os.path.join(env.SECRETS_PATH, 'keys/newsblur.key') env.key_filename = os.path.join(env.SECRETS_PATH, 'keys/newsblur.key')
env.connection_attempts = 10 env.connection_attempts = 10
env.do_ip_to_hostname = {}
env.colorize_errors = True
# ========= # =========
# = Roles = # = Roles =
@ -62,6 +64,7 @@ except:
def do_roledefs(split=False): def do_roledefs(split=False):
doapi = digitalocean.Manager(token=django_settings.DO_TOKEN_FABRIC) doapi = digitalocean.Manager(token=django_settings.DO_TOKEN_FABRIC)
droplets = doapi.get_all_droplets() droplets = doapi.get_all_droplets()
env.do_ip_to_hostname = {}
hostnames = {} hostnames = {}
for droplet in droplets: for droplet in droplets:
roledef = re.split(r"([0-9]+)", droplet.name)[0] roledef = re.split(r"([0-9]+)", droplet.name)[0]
@ -71,6 +74,7 @@ def do_roledefs(split=False):
hostnames[roledef] = [] hostnames[roledef] = []
if droplet.ip_address not in hostnames[roledef]: if droplet.ip_address not in hostnames[roledef]:
hostnames[roledef].append({'name': droplet.name, 'address': droplet.ip_address}) hostnames[roledef].append({'name': droplet.name, 'address': droplet.ip_address})
env.do_ip_to_hostname[droplet.ip_address] = droplet.name
if droplet.ip_address not in env.roledefs[roledef]: if droplet.ip_address not in env.roledefs[roledef]:
env.roledefs[roledef].append(droplet.ip_address) env.roledefs[roledef].append(droplet.ip_address)
@ -79,7 +83,7 @@ def do_roledefs(split=False):
return droplets return droplets
def list_do(): def list_do():
droplets = do(split=True) droplets = assign_digitalocean_roledefs(split=True)
pprint(droplets) pprint(droplets)
doapi = digitalocean.Manager(token=django_settings.DO_TOKEN_FABRIC) doapi = digitalocean.Manager(token=django_settings.DO_TOKEN_FABRIC)
@ -101,7 +105,7 @@ def list_do():
def host(*names): def host(*names):
env.hosts = [] env.hosts = []
env.doname = ','.join(names) env.doname = ','.join(names)
hostnames = do(split=True) hostnames = assign_digitalocean_roledefs(split=True)
for role, hosts in hostnames.items(): for role, hosts in hostnames.items():
for host in hosts: for host in hosts:
if isinstance(host, dict) and host['name'] in names: if isinstance(host, dict) and host['name'] in names:
@ -116,53 +120,53 @@ def server():
env.NEWSBLUR_PATH = "/srv/newsblur" env.NEWSBLUR_PATH = "/srv/newsblur"
env.VENDOR_PATH = "/srv/code" env.VENDOR_PATH = "/srv/code"
def do(split=False): def assign_digitalocean_roledefs(split=False):
server() server()
droplets = do_roledefs(split=split) droplets = do_roledefs(split=split)
if split: if split:
for roledef, hosts in env.roledefs.items(): for roledef, hosts in env.roledefs.items():
if roledef not in droplets: if roledef not in droplets:
droplets[roledef] = hosts droplets[roledef] = hosts
return droplets return droplets
def app(): def app():
do() web()
env.roles = ['app']
def web(): def web():
do() assign_digitalocean_roledefs()
env.roles = ['app', 'push', 'work'] env.roles = ['app', 'push', 'work', 'search']
def work(): def work():
do() assign_digitalocean_roledefs()
env.roles = ['work'] env.roles = ['work', 'search']
def www(): def www():
do() assign_digitalocean_roledefs()
env.roles = ['www'] env.roles = ['www']
def dev(): def dev():
do() assign_digitalocean_roledefs()
env.roles = ['dev'] env.roles = ['dev']
def debug(): def debug():
do() assign_digitalocean_roledefs()
env.roles = ['debug'] env.roles = ['debug']
def node(): def node():
do() assign_digitalocean_roledefs()
env.roles = ['node'] env.roles = ['node']
def push(): def push():
do() assign_digitalocean_roledefs()
env.roles = ['push'] env.roles = ['push']
def db(): def db():
do() assign_digitalocean_roledefs()
env.roles = ['db'] env.roles = ['db', 'search']
def task(): def task():
do() assign_digitalocean_roledefs()
env.roles = ['task'] env.roles = ['task']
def ec2task(): def ec2task():
@ -172,11 +176,11 @@ def ec2task():
def ec2(): def ec2():
env.user = 'ubuntu' env.user = 'ubuntu'
env.key_filename = ['/Users/sclay/.ec2/sclay.pem'] env.key_filename = ['/Users/sclay/.ec2/sclay.pem']
do() assign_digitalocean_roledefs()
def all(): def all():
do() assign_digitalocean_roledefs()
env.roles = ['app', 'db', 'task', 'debug', 'node', 'push', 'work', 'www'] env.roles = ['app', 'db', 'task', 'debug', 'node', 'push', 'work', 'www', 'search']
# ============= # =============
# = Bootstrap = # = Bootstrap =
@ -1310,17 +1314,30 @@ def pre_deploy():
def post_deploy(): def post_deploy():
cleanup_assets() cleanup_assets()
def role_for_host():
for role, hosts in env.roledefs.items():
if env.host in hosts:
return role
@parallel @parallel
def deploy(fast=False, reload=False): def deploy(fast=False, reload=False):
deploy_code(copy_assets=False, fast=fast, reload=reload) role = role_for_host()
if role in ['work', 'search']:
deploy_code(copy_assets=False, fast=fast, reload=True)
else:
deploy_code(copy_assets=False, fast=fast, reload=reload)
@parallel @parallel
def deploy_web(fast=False): def deploy_web(fast=False):
deploy_code(copy_assets=True, fast=fast, full=False) role = role_for_host()
if role in ['work', 'search']:
deploy_code(copy_assets=True, fast=fast, reload=True)
else:
deploy_code(copy_assets=True, fast=fast)
@parallel @parallel
def deploy_full(fast=False): def deploy_rebuild(fast=False):
deploy_code(copy_assets=True, fast=fast, full=True) deploy_code(copy_assets=True, fast=fast, rebuild=True)
@parallel @parallel
def kill_gunicorn(): def kill_gunicorn():
@ -1328,22 +1345,22 @@ def kill_gunicorn():
sudo('pkill -9 -u %s -f gunicorn_django' % env.user) sudo('pkill -9 -u %s -f gunicorn_django' % env.user)
@parallel @parallel
def deploy_code(copy_assets=False, full=False, fast=False, reload=False): def deploy_code(copy_assets=False, rebuild=False, fast=False, reload=False):
with cd(env.NEWSBLUR_PATH): with cd(env.NEWSBLUR_PATH):
run('git pull') run('git pull')
run('mkdir -p static') run('mkdir -p static')
if full: if rebuild:
run('rm -fr static/*') run('rm -fr static/*')
if copy_assets: if copy_assets:
transfer_assets() transfer_assets()
with settings(warn_only=True): with cd(env.NEWSBLUR_PATH), settings(warn_only=True):
if reload: if reload:
sudo('supervisorctl reload') sudo('supervisorctl reload')
elif fast: elif fast:
kill_gunicorn() kill_gunicorn()
else: else:
sudo('kill -HUP `cat /srv/newsblur/logs/gunicorn.pid`') sudo('kill -HUP `cat /srv/newsblur/logs/gunicorn.pid`')
@parallel @parallel
def kill(): def kill():
@ -1377,7 +1394,7 @@ def staging():
run('curl -s http://dev.newsblur.com > /dev/null') run('curl -s http://dev.newsblur.com > /dev/null')
run('curl -s http://dev.newsblur.com/m/ > /dev/null') run('curl -s http://dev.newsblur.com/m/ > /dev/null')
def staging_full(): def staging_build():
with cd('~/staging'): with cd('~/staging'):
run('git pull') run('git pull')
run('./manage.py migrate') run('./manage.py migrate')