Commits

Brent Tubbs  committed 7ef595c

mid revamp

  • Participants
  • Parent commits 4e4bce3

Comments (0)

Files changed (3)

File silk/fabfile.py

 from fabric.contrib.files import exists, upload_template
 
 import silk.lib
+from silk.utils import _get_site_deps
 
 SRV_ROOT = '/srv'
 DEFAULT_ROLLBACK_CAP = 3
+DTS_FORMAT = '%Y%m%d_%H%M%S'
+NGINX_SITE_DIR = '/etc/nginx/sites-enabled'
 
 def _get_silk_deps():
     silk_deps_file = pkg_resources.resource_filename('silk', 'deps.yaml')
     return yaml.safe_load(open(silk_deps_file).read())
 
-def _get_site_deps(local_root):
-    site_deps_file = os.path.join(local_root, 'deps.yaml')
-    return yaml.safe_load(open(site_deps_file).read())
-
 def _set_vars():
     """
     Loads deployment settings into Fabric's global 'env' dict
     """
     env.local_root = silk.lib.get_site_root(os.getcwd())
     env.config = silk.lib.get_site_config(env.local_root)
+    dts = datetime.datetime.now().strftime(DTS_FORMAT)
     if len(env.roles) == 1:
         env.config.update(silk.lib.get_role_config(env.roles[0]))
         env.site = env.config['site']
-        env.remote_root = '/'.join([SRV_ROOT, env.site])
+        env.remote_root = '/'.join([SRV_ROOT, '%s_%s' % (env.site, dts)])
         env.envdir = '/'.join([env.remote_root, 'env'])
-        env.workdir = '/'.join(['/tmp', env.site])
         env.rollbackdir = '/'.join([SRV_ROOT, 'rollbacks'])
-        env.deploytime = datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
+        env.deploytime = dts
         env.config['bind'] = env.config['gunicorn'].get('bind', 'unix:/tmp/%s.sock'
                                                         % env.site)
         env.config['silk_deps'] = _get_silk_deps()
 _set_vars()
 
 # UGLY MAGIC
-# Here we're (ab)using Fabric's built in 'role' feature to work with the way 
-# we're loading context-specific config.  Could possibly use a refactor to 
+# Here we're (ab)using Fabric's built in 'role' feature to work with the way
+# we're loading context-specific config.  Could possibly use a refactor to
 # avoid Fabric roles altogether.
 def _get_hosts():
     """Return list of hosts to push to"""
     blamefile = tempfile.NamedTemporaryFile()
     blamefile.write(_get_blame())
     blamefile.seek(0) # Rewind the file so that the putter can read it.
-    remote_blame = '/'.join([env.workdir, 'blame.yaml'])
+    remote_blame = '/'.join([env.remote_root, 'blame.yaml'])
     put(blamefile.name, remote_blame)
     blamefile.close()
 
       oldest_rollback = '%(rollbackdir)s/%(site)s-rollback_%(rollback_cap)s.tar.bz2' % template_vars
       #first delete the oldest rollback if present
       if exists(oldest_rollback):
-          sudo('rm %s' % oldest_rollback) 
+          sudo('rm %s' % oldest_rollback)
 
       #then increment the numbers on the existing rollbacks
       for i in xrange(ROLLBACK_CAP - 1, 0, -1):
     print "ROLLING BACK"
     ROLLBACK_CAP = env.config.get('rollback_cap', DEFAULT_ROLLBACK_CAP)
     rollback_file = '%s/%s-rollback_1.tar.bz2' % (env.rollbackdir, env.site)
-    if exists(rollback_file): 
+    if exists(rollback_file):
         #unzip in a tmp dir
         tmpdir = os.path.join('/tmp', 'rollback-%s' % env.site)
         if exists(tmpdir, use_sudo=True):
     else:
         sys.exit('Error: %s not found' % rollback_file)
 
-
-def install_apt_deps():
-    """
-    Installs system packages and build dependencies with apt.
-    """
-    for deps_dict in (env.config['silk_deps'], env.config['site_deps']):
-        print deps_dict
-        if deps_dict['apt_build_deps']:
-            sudo('apt-get build-dep %s -y' % ' '.join(deps_dict['apt_build_deps']))
-        if deps_dict['apt_packages']:
-            sudo('apt-get install %s -y' % ' '.join(deps_dict['apt_packages']))
-
 #TODO: rebuild virtualenv if it exists but the python version is wrong
 def create_virtualenv():
     """
     tmpfile.close()
 
     # Run pip install remotely
-    pip_cmd = silk.lib.get_pip_cmd(env.config) 
+    pip_cmd = silk.lib.get_pip_cmd(env.config)
     sudo('%s/bin/%s -r %s' % (env.envdir, pip_cmd, tmp_remote))
-         
+
     # Clean up remote reqs file
     sudo('rm %s' % tmp_remote)
 
     Builds and install egenix-mx-tools into virtualenv
     """
     #egenix-mx-tools includes the mxdatetime module, which is
-    #a psycopg2 dependency.  Unfortunately it's not packaged in 
+    #a psycopg2 dependency.  Unfortunately it's not packaged in
     #a way that pip can install.  So we build it here instead
     print "INSTALLING MX TOOLS"
     build_dir = "/tmp/egenix_build"
         sudo('%s setup.py install' % os.path.join(env.envdir, 'bin', 'python'))
     sudo('rm -rf %s' % build_dir)
 
-def push_code():    
+def push_code():
     """
     Pushes site to remote host
     """
     print "PUSHING CODE TO HOST"
-    if exists(env.workdir):
-        sudo('rm %s -rf' % env.workdir)
-    _put_dir(env.local_root, env.workdir)
+    if exists(env.remote_root):
+        sudo('rm %s -rf' % env.remote_root)
+    _put_dir(env.local_root, env.remote_root)
 
 def _upload_config_template(template, dest, context):
     #first try to load the template from the local cfg_templates dir.
     }
     template_vars.update(env)
     template_vars.update(env.config)
-    config_dir = '/'.join([env.workdir, 'conf'])
+    config_dir = '/'.join([env.remote_root, 'conf'])
     #make sure the conf and logs dirs are created
     _ensure_dir(config_dir)
-    _ensure_dir('/'.join([env.workdir, 'logs']))
+    _ensure_dir('/'.join([env.remote_root, 'logs']))
 
     template_list = (
         ('supervisord.conf','/'.join([config_dir, 'supervisord.conf'])),
-        ('nginx.conf','/'.join([config_dir, 'nginx.conf'])),
+        ('nginx.conf','/'.join([NGINX_SITE_DIR, 'silk_%s.conf' % env.site])),
     )
     _write_templates(template_list, template_vars)
     _write_blame()
 
-def switch():
-    """
-    Does a little dance to move the old project dir out of the way and put
-    the new one in its place.
-    """
-    print "MOVING NEW CODE INTO PLACE"
-    #copy the virtualenv into env.workdir
-    sudo('cp %s %s/ -r' % (env.envdir, env.workdir))
-    #move old env.remote_root
-    olddir = '/'.join(['/tmp', 'old-%s' % env.site])
-    sudo('mv %s %s' % (env.remote_root, olddir))
-    #move code into place
-    sudo('mv %s %s' % (env.workdir, env.remote_root))
-
 def cleanup():
     """
     Removes the old project dir.  (But you still have a rollback!)
     install_apt_deps()
     template_list = (
         ('supervisord_root.conf', '/etc/supervisor/supervisord.conf'),
-        ('nginx_root.conf','/etc/nginx/nginx.conf'),
     )
     _write_templates(template_list, env)
     restart()
     configured, this function will put your site on the remote host and get it
     running.
     """
-    archive()
-    install_deps()
     push_code()
     write_config()
-    switch()
     reload()
     cleanup()
 
 import os
 import pkg_resources
 
-from silk_config import *
+from app_container import *
 
 def get_gunicorn_cmd(site_config, bin_dir=''):
     gconfig = copy.copy(site_config['gunicorn'])
 
     # Default to using a unix socket for nginx->gunicorn
-    gconfig['bind'] = gconfig.get('bind', 
+    gconfig['bind'] = gconfig.get('bind',
                                   'unix:/tmp/%s.sock' % site_config['site'])
-    
+
     # Default to using the site name in the procname
     gconfig['name'] = gconfig.get('name', site_config['site'])
 
         site_root = get_site_root(os.getcwd())
 
     # If role is None, then try getting it from cmd line and/or env vars ourselves
-    role = role or get_role() 
+    role = role or get_role()
 
-    # If role is still none, then look for a blame file, which doesn't require a role. 
+    # If role is still none, then look for a blame file, which doesn't require a role.
             # If no role and no blame file, give up.
 
     config = get_site_config(site_root)
-    config.update(get_role_config(role))
+
+    role_config = get_role_config(role)
+    if isinstance(role_config, dict):
+        config.update()
     return config
 def get_template_path(template, site_root=None):
     """

File silk/utils.py

 import yaml
 
 import silk.lib
+import app_container
 
-def run_til_you_die(args, kill_signal, cwd=os.getcwd(), env={}):
+def _run(args, kill_signal, cwd=os.getcwd(), env={}):
     env.update(os.environ)
     proc = subprocess.Popen(args, cwd=cwd, env=env)
     try:
 
 def run_fab(args):
     args[0] = 'fab'
-    run_til_you_die(args, SIGTERM)
+    _run(args, SIGTERM)
 
 def run_devserver():
     # Overwrite the wsgi_app config var to point to our internal app that will
     role = os.environ['SILK_ROLE']
     config = silk.lib.get_config(root, role)
     config['wsgi_app'] = 'silk.devserver:app'
-    
+
     cmd = silk.lib.get_gunicorn_cmd(config)
-    
+
     subproc_env = {
         'SILK_ROOT': root,
-        'SILK_ROLE': silk.lib.get_role(),
+        'SILK_ROLE': app_container.get_role(),
     }
 
     # By adding our current subproc_environment to that used for the subprocess, we
     # ensure that the same paths will be used (such as those set by virtualsubproc_env)
     subproc_env.update(os.environ)
 
-    run_til_you_die(cmd.split(), SIGINT, cwd=root, env=subproc_env)
+    _run(cmd.split(), SIGINT, cwd=root, env=subproc_env)
 
     # This 1 second sleep lets the gunicorn workers exit before we show the
     # prompt again.
         shutil.copytree(src, os.path.join(os.getcwd(), sitename))
     except OSError, e:
         print e
-    
+
 def freeze_2_yaml():
     """Read lines of text from stdin and print a python_packages yaml list"""
     lines = sys.stdin.read().split('\n')#split only on newlines, not spaces
     depfile = os.path.join(silk.lib.get_site_root(os.getcwd()), 'deps.yaml')
     txt = open(depfile).read()
     deps = yaml.safe_load(txt)
-    reqs = '\n'.join(deps['python_packages'])
+    if deps['python_packages']:
+        reqs = '\n'.join(deps['python_packages'])
 
-    tmpfile = tempfile.NamedTemporaryFile()
-    tmpfile.write(reqs)
-    tmpfile.seek(0)
+        tmpfile = tempfile.NamedTemporaryFile()
+        tmpfile.write(reqs)
+        tmpfile.seek(0)
 
-    pip_cmd = silk.lib.get_pip_cmd(config) 
-    cmd = '%s -r %s' % (pip_cmd, tmpfile.name)
-    run_til_you_die(cmd.split(), SIGTERM)
-    tmpfile.close()
+        pip_cmd = silk.lib.get_pip_cmd(config)
+        cmd = '%s -r %s' % (pip_cmd, tmpfile.name)
+        _run(cmd.split(), SIGTERM)
+        tmpfile.close()
+    else:
+        print "No python deps listed."
+
+def _get_site_deps(local_root):
+    site_deps_file = os.path.join(local_root, 'deps.yaml')
+    return yaml.safe_load(open(site_deps_file).read())
+
+def local_apt_deps():
+    """
+    Installs system packages and build dependencies with apt.
+    """
+    root = os.environ['SILK_ROOT']
+    role = os.environ['SILK_ROLE']
+    deps = _get_site_deps(root)
+    if deps['apt_build_deps']:
+        cmd = 'sudo apt-get build-dep %s -y' % ' '.join(deps['apt_build_deps'])
+        _run(cmd.split(), SIGINT)
+    if deps['apt_packages']:
+        cmd = 'sudo apt-get install %s -y' % ' '.join(deps['apt_packages'])
+        _run(cmd.split(), SIGINT)
+
+def local_deps():
+    """Install local python deps, and ubuntu ones too if possible"""
+    local_python_deps()
+    local_apt_deps()
+
 
 cmd_map = {
     'run': run_devserver,
     'skel': install_skel,
-    'deps': local_python_deps
+    'deps': local_deps
 }
 
 def cmd_dispatcher():
         if cmd in cmd_map:
             # Stick some information about the role and root into the current env,
             # then call the local function in cmd_map.
-            os.environ['SILK_ROLE'] = silk.lib.get_role() or '' 
+            os.environ['SILK_ROLE'] = app_container.get_role() or ''
             os.environ['SILK_ROOT'] = silk.lib.get_site_root(os.getcwd()) or ''
             cmd_map[cmd]()
         else: