#!/usr/bin/env ruby require 'rubygems' require File.dirname(__FILE__) + '/../lib/sumo' require 'thor' class CLI < Thor desc "launch []", "launch an instance as role, or omit to ssh to vanilla instance" def launch(role=nil) id = task("Launch instance") { sumo.launch } host = task("Acquire hostname") { sumo.wait_for_hostname(id) } task("Wait for ssh") { sumo.wait_for_ssh(host) } if role task("Bootstrap chef") { sumo.bootstrap_chef(host) } role.split(',').each do |role| task("Setup #{role}") { sumo.setup_role(host, role) } end resources = sumo.resources(host) unless resources.empty? task("Open firewall") do ports = resources.map { |r| r.match(/:(\d+)\//)[1] } ports.each { |port| sumo.open_firewall(port) } "ports " + ports.join(", ") end end puts display_resources(host) else puts "\nLogging you in via ssh. Type 'exit' or Ctrl-D to return to your local system." puts '-' * 78 connect_ssh(host) end end desc "ssh []", "ssh to a specified instance or first available" def ssh(id=nil) inst = sumo.find(id) || sumo.running.first || abort("No running instances") hostname = inst[:hostname] || wait_for_hostname(inst[:instance_id]) connect_ssh hostname end desc "resources []", "show resources exported by an instance" def resources(id=nil) inst = sumo.find(id) || sumo.running.first || abort("No running instances") hostname = inst[:hostname] || wait_for_hostname(inst[:instance_id]) display_resources(inst[:hostname]) end desc "bootstrap", "bootstrap chef and cookbooks" def bootstrap(id=nil) inst = sumo.find(id) || sumo.running.first || abort("No running instances") task "Bootstrap chef" do sumo.bootstrap_chef(inst[:hostname]) end end desc "role", "setup instance as a role" def role(role, id=nil) inst = sumo.find(id) || sumo.running.first || abort("No running instances") task "Setup #{role}" do sumo.setup_role(inst[:hostname], role) end end desc "list", "list running instances" def list sumo.list.each do |inst| printf "%-50s %-12s %s\n", inst[:hostname], inst[:instance_id], inst[:status] end end desc "console []", "get console output for instance or first available" def console(id=nil) inst = sumo.find(id) || (sumo.running | sumo.pending).first || abort("No running or pending instances") puts sumo.console_output(inst[:instance_id]).inspect end desc "terminate []", "terminate specified instance or first available" def terminate(id=nil) inst = sumo.find(id) || (sumo.running | sumo.pending).first || abort("No running or pending instances") sumo.terminate(inst[:instance_id]) puts "#{inst[:hostname] || inst[:instance_id]} scheduled for termination" end desc "terminate_all", "terminate all instances" def terminate_all instances = (sumo.running | sumo.pending) abort("No running or pending instances") if instances.empty? instances.each do |inst| sumo.terminate(inst[:instance_id]) puts "#{inst[:hostname] || inst[:instance_id]} scheduled for termination" end end desc "volumes", "list all volumes" def volumes sumo.volumes.each do |v| printf "%-10s %4sGB %10s %15s %15s\n", v[:volume_id], v[:size], v[:status], v[:instance], v[:device] end end desc "create_volume []", "create a volume" def create_volume(size=5) task("Create #{size}GB volume") { sumo.create_volume(size) } end desc "destroy_volume []", "destroy a volume" def destroy_volume(volume=nil) vol_id = (sumo.find_volume(volume) || sumo.nondestroyed_volumes.first || abort("No volumes"))[:volume_id] task("Destroy volume") { sumo.destroy_volume(vol_id) } end desc "attach [] [] []", "attach volume to running instance" def attach(volume=nil, inst_id=nil, device=nil) vol_id = (sumo.find_volume(volume) || sumo.available_volumes.first || abort("No available volumes"))[:volume_id] inst_id = (sumo.find(inst_id) || sumo.running.first || abort("No running instances"))[:instance_id] device ||= '/dev/sdc1' task("Attach #{vol_id} to #{inst_id} as #{device}") do sumo.attach(vol_id, inst_id, device) end end desc "detach []", "detach volume from instance" def detach(volume=nil) vol_id = (sumo.find_volume(volume) || sumo.attached_volumes.first || abort("No attached volumes"))[:volume_id] task("Detach #{vol_id}") { sumo.detach(vol_id) } end no_tasks do def sumo @sumo ||= Sumo.new end def config sumo.config end def task(msg, &block) printf "---> %-24s ", "#{msg}..." start = Time.now result = block.call || 'done' finish = Time.now time = sprintf("%0.1f", finish - start) puts "#{result} (#{time}s)" result end def connect_ssh(hostname) sumo.wait_for_ssh(hostname) system "ssh -i #{sumo.keypair_file} #{config['user']}@#{hostname}" if $?.success? puts "\nType 'sumo terminate' if you're done with this instance." end end def display_resources(host) resources = sumo.resources(host) unless resources.empty? puts "Your instance is exporting the following resources:" resources.each do |resource| puts " #{resource}" end end end end end CLI.start