Skip to content

Instantly share code, notes, and snippets.

@coderanger
Created June 11, 2012 00:57
Show Gist options
  • Save coderanger/2907936 to your computer and use it in GitHub Desktop.
Save coderanger/2907936 to your computer and use it in GitHub Desktop.
Edited version of opscode's fabfile/
import os
from fabric.api import env, task, roles, run
from fabric.utils import abort
from chef import ChefAPI, autoconfigure
from chef.fabric import chef_roledefs
if 'OC_USER' in os.environ:
env.user = os.environ['OC_USER']
import community
import corpsite
from fabric.api import *
from fabric.utils import puts
from fabric.contrib.files import comment, uncomment
from chef import Search
from chef.fabric import chef_query
from utils import upload_env, no_daemon
LB_CONF = '/etc/nginx/sites-available/corpsite.conf'
LB_REGEX = r'server %s:80;$'
@roles('corpsite-lb')
@task
def set_lb(state, host):
op = uncomment if state else comment
op(LB_CONF, LB_REGEX%host, use_sudo=True)
sudo('killall -HUP nginx')
@roles('opscode-community-site')
@task
def upgrade():
query = 'fqdn:%s OR public_hostname:%s'%(env.host_string, env.host_string)
node = Search('node', query)[0].object
try:
addr = node.attributes.get_dotted('cloud.local_ipv4')
except KeyError:
addr = node['ipaddress']
execute(set_lb, False, addr)
sudo('chef-client')
# Wait for it to come up
puts('Waiting for server to come back up')
while True:
with settings(warn_only=True):
ret = run('curl http://localhost/ -w %{http_code} -o /dev/null -s')
if ret.succeeded and ret.strip() == '200':
break
execute(set_lb, True, addr)
@task(default=True)
def deploy():
with no_daemon('corpsite-lb', 'opscode-community-site'):
upload_env()
execute(upgrade)
from fabric.api import *
import os
from utils import set_env, upload_env, no_daemon, PROJECT_ROOT, next_version, git_branch
PATH = os.path.abspath(os.path.join(PROJECT_ROOT, '..', 'opscode-corpsite'))
@task
def release(version=None):
if env.oc_env == 'preprod':
abort('Corpsite preprod lives on master')
with lcd(PATH):
# Check if there is new stuff
local('git up')
with settings(hide('running', 'stdout', 'warnings'), warn_only=True):
diff = local('git diff release..master', capture=True)
if diff.strip():
# Release and master are different, issue a release
if not version:
version = next_version(PATH)
with lcd(PATH), git_branch('release'):
local('git merge --no-ff master')
local('git tag -a rel-%s -m "Release %s"'%(version, version))
local('git push')
local('git push --tags')
set_env('corpsite-www-revision', 'rel-%s'%version)
upload_env()
@roles('nanoc-builder')
@task
def upgrade():
sudo('chef-client')
@task(default=True)
def deploy(version=None):
with no_daemon('nanoc-builder'):
if env.oc_env == '...':
execute(release, version)
execute(upgrade)
from fabric.api import env, local, lcd, task, sudo, execute, settings, hide
from fabric.utils import abort
from chef import DataBagItem
from chef.fabric import chef_query
import collections
import contextlib
import json
import os
PROJECT_ROOT = os.path.abspath(os.path.join(__file__, '..', '..'))
def _item_name(oc_env=None, fail=True):
oc_env = oc_env or env.oc_env or 'opsmaster'
filename = {'preprod': 'rs-preprod', 'opsmaster': 'rs-prod'}.get(oc_env)
if fail and not filename:
abort('Cannot upload env: %s'%oc_env)
return filename
def _bag_item_path(bag, item):
return os.path.join(PROJECT_ROOT, 'data_bags', bag, item+'.json')
def _env_bag_item_path(oc_env=None):
return _bag_item_path('environments', _item_name(oc_env))
def upload_env(oc_env=None):
with lcd(PROJECT_ROOT):
local('git up') # Make sure we are up to date
item = DataBagItem('environments', _item_name(oc_env), skip_load=True)
item.raw_data = get_env()
item.save()
def set_env(key, value, oc_env=None):
get_env(oc_env, force=True)
env.oc_env_data[key] = value
outf = open(_env_bag_item_path(oc_env), 'wb')
for line in json.dumps(env.oc_env_data, indent=2).splitlines():
outf.write(line.rstrip())
outf.write('\n')
outf.close()
with lcd(PROJECT_ROOT):
local('git add %s'%_env_bag_item_path(oc_env))
local('git commit -m "Updating %s to %s in %s"'%(key, value, _item_name(oc_env)))
local('git up')
local('git push')
def get_env(oc_env=None, force=False):
filename = _item_name(oc_env)
if force or env.get('oc_env_data', {}).get('id') != filename:
path = _env_bag_item_path(oc_env)
env.oc_env_data = json.load(open(path, 'rb'), object_pairs_hook=collections.OrderedDict)
return env.oc_env_data
@contextlib.contextmanager
def no_daemon(*args):
# Allow passing a single iterable
if len(args) == 1 and not isinstance(args[0], basestring):
args = args[0]
query = [s if ':' in s else 'roles:%s'%s for s in args]
query = '( %s ) AND tags:daemonize' % (' '.join(query))
# Create a new task to use
@chef_query(query)
@task
def set_daemon(state):
cmd = 'start' if state else 'stop'
sudo('sv %s chef-client'%cmd)
execute(set_daemon, False)
yield
execute(set_daemon, True)
def next_version(path):
if not os.path.isabs(path):
path = os.path.abspath(os.path.join(PROJECT_ROOT, '..', path))
with settings(lcd(path), hide('running')):
tags = local('git tag', capture=True)
versions = []
for line in tags.splitlines():
line = line.strip()
if line.startswith('rel-'):
version = [int(s) for s in line[4:].split('.')]
version.extend([0] * (3 - len(version)))
versions.append(version)
latest = max(versions)
latest[-1] += 1
return '.'.join(str(n) for n in latest)
@contextlib.contextmanager
def git_branch(branch):
with settings(hide('warnings', 'running', 'stdout'), warn_only=True):
ref = local('git symbolic-ref -q HEAD', capture=True)
if ref.startswith('refs/heads/'):
ref = ref[11:]
if not ref:
abort('Unable to determine branch')
local('git checkout %s'%branch)
yield
with hide('running', 'stdout'):
local('git checkout %s'%ref)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment