Skip to content

Commit

Permalink
Merge pull request #90 from PierreFrisch/master
Browse files Browse the repository at this point in the history
Add rebuild command
  • Loading branch information
pearkes committed Feb 11, 2014
2 parents 57720bd + 5ce4fbb commit c9a6669
Show file tree
Hide file tree
Showing 6 changed files with 412 additions and 0 deletions.
34 changes: 34 additions & 0 deletions lib/tugboat/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,40 @@ def create(name)
})
end

desc "rebuild FUZZY_NAME IMAGE_NAME", "Rebuild a droplet."
method_option "id",
:type => :string,
:aliases => "-i",
:desc => "The ID of the droplet."
method_option "name",
:type => :string,
:aliases => "-n",
:desc => "The exact name of the droplet"
method_option "confirm",
:type => :boolean,
:aliases => "-c",
:desc => "Skip confirmation of the action"
method_option "image_id",
:type => :numeric,
:aliases => "-k",
:desc => "The ID of the image"
method_option "image_name",
:type => :string,
:aliases => "-m",
:desc => "The exact name of the image"
def rebuild(name=nil, image_name=nil)
Middleware.sequence_rebuild_droplet.call({
"user_droplet_id" => options[:id],
"user_droplet_name" => options[:name],
"user_droplet_fuzzy_name" => name,
"user_image_id" => options[:image_id],
"user_image_name" => options[:image_name],
"user_image_fuzzy_name" => image_name,
"user_confirm_action" => options[:confirm],
"user_quiet" => options[:quiet]
})
end

desc "destroy FUZZY_NAME", "Destroy a droplet"
method_option "id",
:type => :string,
Expand Down
15 changes: 15 additions & 0 deletions lib/tugboat/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ module Middleware
autoload :CheckDropletInactive, "tugboat/middleware/check_droplet_inactive"
autoload :ConfirmAction, "tugboat/middleware/confirm_action"
autoload :CreateDroplet, "tugboat/middleware/create_droplet"
autoload :RebuildDroplet, "tugboat/middleware/rebuild_droplet"
autoload :DestroyDroplet, "tugboat/middleware/destroy_droplet"
autoload :FindDroplet, "tugboat/middleware/find_droplet"
autoload :FindImage, "tugboat/middleware/find_image"
autoload :HaltDroplet, "tugboat/middleware/halt_droplet"
autoload :InfoDroplet, "tugboat/middleware/info_droplet"
autoload :InjectClient, "tugboat/middleware/inject_client"
Expand Down Expand Up @@ -141,6 +143,19 @@ def self.sequence_create_droplet
end
end

# Rebuild a droplet
def self.sequence_rebuild_droplet
::Middleware::Builder.new do
use InjectConfiguration
use CheckConfiguration
use InjectClient
use FindDroplet
use FindImage
use ConfirmAction
use RebuildDroplet
end
end

# Destroy a droplet
def self.sequence_destroy_droplet
::Middleware::Builder.new do
Expand Down
113 changes: 113 additions & 0 deletions lib/tugboat/middleware/find_image.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
module Tugboat
module Middleware
# Check if the client has set-up configuration yet.
class FindImage < Base
def call(env)
ocean = env["ocean"]
user_fuzzy_name = env['user_image_fuzzy_name']
user_image_name = env['user_image_name']
user_image_id = env['user_image_id']

# First, if nothing is provided to us, we should quit and
# let the user know.
if !user_fuzzy_name && !user_image_name && !user_image_id
say "Tugboat attempted to find an image with no arguments. Try `tugboat help`", :red
exit 1
end

# If you were to `tugboat restart foo -n foo-server-001` then we'd use
# 'foo-server-001' without looking up the fuzzy name.
#
# This is why we check in this order.

# Easy for us if they provide an id. Just set it to the image_id
if user_image_id
say "Image id provided. Finding Image...", nil, false
req = ocean.images.show user_image_id

if req.status == "ERROR"
say "#{req.status}: #{req.error_message}", :red
exit 1
end

env["image_id"] = req.image.id
env["image_name"] = "(#{req.image.name})"
end

# If they provide a name, we need to get the ID for it.
# This requires a lookup.
if user_image_name && !env["image_id"]
say "Image name provided. Finding image ID...", nil, false

# Look for the image by an exact name match.
ocean.images.list.images.each do |d|
if d.name == user_image_name
env["image_id"] = d.id
env["image_name"] = "(#{d.name})"
end
end

# If we coulnd't find it, tell the user and drop out of the
# sequence.
if !env["image_id"]
say "error\nUnable to find a image named '#{user_image_name}'.", :red
exit 1
end
end

# We only need to "fuzzy find" a image if a fuzzy name is provided,
# and we don't want to fuzzy search if an id or name is provided
# with a flag.
#
# This requires a lookup.
if user_fuzzy_name && !env["image_id"]
say "Image fuzzy name provided. Finding image ID...", nil, false

found_images = []
choices = []

ocean.images.list.images.each_with_index do |d, i|
# Check to see if one of the image names have the fuzzy string.
if d.name.upcase.include? user_fuzzy_name.upcase
found_images << d
end
end

# Check to see if we have more then one image, and prompt
# a user to choose otherwise.
if found_images.length == 1
env["image_id"] = found_images.first.id
env["image_name"] = "(#{found_images.first.name})"
elsif found_images.length > 1
# Did we run the multiple questionairre?
did_run_multiple = true

say "Multiple images found."
say
found_images.each_with_index do |d, i|
say "#{i}) #{d.name} (#{d.id})"
choices << i.to_s
end
say
choice = ask "Please choose a image:", :limited_to => choices
env["image_id"] = found_images[choice.to_i].id
env["image_name"] = found_images[choice.to_i].name
end

# If we coulnd't find it, tell the user and drop out of the
# sequence.
if !env["image_id"]
say "error\nUnable to find an image named '#{user_fuzzy_name}'.", :red
exit 1
end
end

if !did_run_multiple
say "done#{CLEAR}, #{env["image_id"]} #{env["image_name"]}", :green
end
@app.call(env)
end
end
end
end

23 changes: 23 additions & 0 deletions lib/tugboat/middleware/rebuild_droplet.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Tugboat
module Middleware
class RebuildDroplet < Base
def call(env)
ocean = env["ocean"]

say "Queuing rebuild for droplet #{env["droplet_id"]} #{env["droplet_name"]} with image #{env["image_id"]} #{env["image_name"]}...", nil, false

req = ocean.droplets.rebuild env["droplet_id"],
:image_id => env["image_id"]

if req.status == "ERROR"
say req.error_message, :red
exit 1
end

say "done", :green

@app.call(env)
end
end
end
end
Loading

0 comments on commit c9a6669

Please sign in to comment.