Posts dealing with switchtower

Customizing disable_web for multiple sites

On Measure Map, we have two separate applications: the frontend that users log into and see their stats, and the tracker, where things about your blog are recorded. Links to tracker are sourced in users' blogs as Javascript, so they had better return valid Javascript code at all times, even when we take the application offline for maintenance.

Ok, so how do we override Switchtower's disable_web task to use a custom page? Here's one way. It assumes a custom page lives at config/templates/maintenance.rhtml.

task :disable_web do
  # Get the current path
  dir = `pwd`.chomp

  # Copy the template to the current path (this is where 'render' looks)
  `cp #{dir}/config/templates/maintenance.rhtml #{dir}/maintenance.rhtml`

  # Read in file with replacements
  maintenance = render("maintenance", :deadline => ENV['UNTIL'], :reason => ENV['REASON'])

  # Copy to the server
  put maintenance, "#{shared_path}/system/maintenance.html", :mode => 0644

  # Remove local copy
  `rm #{dir}/maintenance.rhtml`

  # Just in case something goes wrong, clean up
  on_rollback do
    `rm #{dir}/maintenance.rhtml`
    delete "#{shared_path}/system/maintenance.html"
  end
end

Remember when using the default mod_rewrite rules to support the maintenance page, you will redirect everything to this file, so you can't use any external stylesheet or image files unless you get tricky with mod_rewrite.

Cool, so now we have our own maintenance page. Next problem; how to use separate files for our two applications? Here's a nice DRY version that's easy to extend to as many roles as you need.

# Stay DRY by configuring the task
def move_maintenance_file(name)
  Proc.new do
    dir = `pwd`.chomp
    `cp #{dir}/config/templates/#{name}.rhtml #{dir}/#{name}.rhtml`
    maintenance = render(name, :deadline => ENV['UNTIL'], :reason => ENV['REASON'])
    put maintenance, "#{shared_path}/system/maintenance.html", :mode => 0644
    `rm #{dir}/#{name}.rhtml`
    on_rollback do
      `rm #{dir}/#{name}.rhtml`
      delete "#{shared_path}/system/maintenance.html"
    end
  end
end

# Define two new tasks for disabling web on our different applications
task :disable_web_frontend, :roles => :web_frontend, &move_maintenance_file('maintenance')
task :disable_web_tracker, :roles => :web_tracker, &move_maintenance_file('maintenance-tracker')

# Override disable_web to send different files to web_frontend and web_tracker
task :disable_web do
  disable_web_frontend
  disable_web_tracker
end

With this in place, we simply create two files, config/templates/maintenance.rhtml for the frontend, and config/templates/maintenance-tracker.rhtml for the tracker, and we're all set.

SwitchTower

I grabbed it from svn and started playing around last night. Today there's a manual on it. Nothing much to say except SwitchTower looks super, super sweet.

Combine that with migrations and FCGI scripts and wow, things just got simpler. Simpler is good.

I look forward to testing SwitchTower out on a few small projects in the next couple days, and then using it for the big one.

(announcement on "the big one" coming soonish)