Brent Tubbs avatar Brent Tubbs committed 09d1b05

ver 0.3.0

Comments (0)

Files changed (1)

 import re
 import copy
 import yaml
+import pkg_resources
 
 from fabric.api import *
 from fabric.colors import green, red, yellow
 
 import silk.lib
 
-
 def _join(*args):
     """Convenience wrapper around posixpath.join to make the rest of our
     functions more readable."""
     env.supd_conf_file = '/etc/supervisor/conf.d/%s.conf' % env.deployment
 
     # Set up gunicorn config
-    default_bind = silk.lib.GUNICORN_BIND_PATTERN % env.deployment
+    env.default_bind = silk.lib.GUNICORN_BIND_PATTERN % env.deployment
     if 'gunicorn' in env.config:
-        env.config['bind'] = env.config['gunicorn'].get('bind', default_bind)
+        env.config['bind'] = env.config['gunicorn'].get('bind', env.default_bind)
     else:
         env.config['bind'] = default_bind 
 
     _write_file(file, yaml.safe_dump(site_yaml_dict, default_flow_style=False))
 
 def _write_template(template, dest, context):
-    #first try to load the template from the local conf_templates dir.
-    #if it's not there then try loading from pkg_resources
     path = silk.lib.get_template_path(template, env.local_root)
     upload_template(path, dest, context=context, use_sudo=True)
 
     old_conf_file = _join(SRV_ROOT, site, 'conf', 'supervisord.conf')
     return exists(env.supd_conf_file) or exists(old_conf_file)
 
+def _socket_head_request(path):
+    """Given a path to a socket, make an HTTP HEAD request on it"""
+    # Get the local path for the unix socket http tool
+    script = pkg_resources.resource_filename('silk', 'sock_http.py')
+    # copy it over to the host
+    dest = _tmpfile()
+    put(script, dest, use_sudo=True)
+    # run it, passing in the path to the socket
+    return sudo('python %s %s HEAD / %s' % (dest, path,
+                                            env.config['listen_hosts'][0]))
+
+def _port_head_request(port):
+    """Given a port number, use curl to make an http HEAD request to it.
+    Return response status as integer."""
+    return run('curl -I http://localhost:%s' % port)
+
+def returns_good_status():
+    """Makes an HTTP request to '/' on the site and returns True if it gets
+    back a status in the 200, 300, or 400 ranges.
+    
+    You can only use this as a standalone silk command if your site has a
+    hard-configured 'bind'."""
+    _yellow("Making http request to site to ensure upness.")
+    bind = env.config['bind']
+    if bind.startswith('unix:'):
+        result = _socket_head_request(bind.replace('unix:', ''))
+    else:
+        result = _port_head_request(bind.split(':')[-1])
+    first_line = result.split('\r\n')[0]
+    status = int(first_line.split()[1])
+    return 200 <= status < 500
+
 def _is_running(procname, tries=3, wait=2):
     """Given the name of a supervisord process, tell you whether it's running
     or not.  If status is 'starting', will wait until status has settled."""
     # mysite_20110623_162319 RUNNING    pid 628, uptime 0:34:13
     # mysite_20110623_231206 FATAL      Exited too quickly (process log may have details)
 
-    status_parts = sudo('supervisorctl status %s' % env.deployment).split()
+    status_parts = sudo('supervisorctl status %s' % procname).split()
     if status_parts[1] == 'RUNNING':
-        return True
+        # For super extra credit, we're actually going to make an HTTP request
+        # to the site to verify that it's up and running.  Unfortunately we
+        # can only do that if Gunicorn is binding to a different socket or port
+        # on each deployment (Silk binds to a new socket on each deployment by
+        # default.)  If you've configured your site to bind to a port, we'll
+        # just have to wing it.
+        if env.config['bind'] == env.default_bind:
+            if returns_good_status():
+                _green("You're golden!")
+                return True
+            else:
+                _red(":(")
+                return False
+        else:
+            return True
     elif status_parts[1] == "FATAL":
         return False
     elif tries > 0:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.