diff --git a/lib/tugboat/cli.rb b/lib/tugboat/cli.rb index f2a8627..563a050 100644 --- a/lib/tugboat/cli.rb +++ b/lib/tugboat/cli.rb @@ -127,6 +127,10 @@ def images :type => :string, :aliases => [ "-c", "-y" ,], :desc => "Command to run on the droplet" + method_option "wait", + :type => :boolean, + :aliases => '-w', + :desc => 'Wait for droplet to become active before trying to SSH' def ssh(name=nil) Middleware.sequence_ssh_droplet.call({ "tugboat_action" => __method__, @@ -138,7 +142,8 @@ def ssh(name=nil) "user_droplet_use_private_ip" => options[:use_private_ip], "user_droplet_ssh_opts" => options[:ssh_opts], "user_droplet_ssh_command" => options[:ssh_command], - "user_quiet" => options[:quiet] + "user_droplet_ssh_wait" => options[:wait], + "user_quiet" => options[:quiet], }) end diff --git a/lib/tugboat/middleware/base.rb b/lib/tugboat/middleware/base.rb index ab33198..7441013 100644 --- a/lib/tugboat/middleware/base.rb +++ b/lib/tugboat/middleware/base.rb @@ -22,6 +22,29 @@ def call(env) @app.call(env) end + def wait_for_state(droplet_id, desired_state,ocean) + start_time = Time.now + + response = ocean.droplet.show droplet_id + + say ".", nil, false + + if !response.success? + say "Failed to get status of Droplet: #{response.message}", :red + exit 1 + end + + while response.droplet.status != desired_state do + sleep 2 + response = ocean.droplet.show droplet_id + say ".", nil, false + end + + total_time = (Time.now - start_time).to_i + + say "done#{CLEAR} (#{total_time}s)", :green + end + # Get all pages of droplets def get_droplet_list(ocean) page = ocean.droplet.all(per_page: 200, page: 1) diff --git a/lib/tugboat/middleware/ssh_droplet.rb b/lib/tugboat/middleware/ssh_droplet.rb index a592a31..deb4a26 100644 --- a/lib/tugboat/middleware/ssh_droplet.rb +++ b/lib/tugboat/middleware/ssh_droplet.rb @@ -50,6 +50,11 @@ def call(env) host_string = "#{ssh_user}@#{host_ip}" + if env['user_droplet_ssh_wait'] + say "Wait flag given, waiting for droplet to become active" + wait_for_state(env["droplet_id"],'active',env['barge']) + end + say "Attempting SSH: #{host_string}" options << host_string diff --git a/lib/tugboat/middleware/wait_for_state.rb b/lib/tugboat/middleware/wait_for_state.rb index f3d42cd..df94a9c 100644 --- a/lib/tugboat/middleware/wait_for_state.rb +++ b/lib/tugboat/middleware/wait_for_state.rb @@ -6,26 +6,7 @@ def call(env) say "Waiting for droplet to become #{env["user_droplet_desired_state"]}.", nil, false - start_time = Time.now - - response = ocean.droplet.show env["droplet_id"] - - say ".", nil, false - - if !response.success? - say "Failed to get status of Droplet: #{response.message}", :red - exit 1 - end - - while response.droplet.status != env["user_droplet_desired_state"] do - sleep 2 - response = ocean.droplet.show env["droplet_id"] - say ".", nil, false - end - - total_time = (Time.now - start_time).to_i - - say "done#{CLEAR} (#{total_time}s)", :green + wait_for_state(env["droplet_id"],env["user_droplet_desired_state"],ocean) @app.call(env) end diff --git a/spec/cli/ssh_cli_spec.rb b/spec/cli/ssh_cli_spec.rb index c78f0d9..228e1bf 100644 --- a/spec/cli/ssh_cli_spec.rb +++ b/spec/cli/ssh_cli_spec.rb @@ -12,6 +12,33 @@ @cli.ssh("example.com") end + it "wait's until droplet active if -w command is given" do + stub_request(:get, "https://api.digitalocean.com/v2/droplets?page=1&per_page=1"). + with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}). + to_return(:status => 200, :body => "", :headers => {}) + + stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200"). + with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}). + to_return(:status => 200, :body => fixture('show_droplet'), :headers => {}) + + stub_request(:get, "https://api.digitalocean.com/v2/droplets?page=1&per_page=200"). + to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplets")) + allow(Kernel).to receive(:exec).with('ssh', anything(), anything(),anything(), anything(),anything(), anything(),anything(), anything(),anything(), anything(),anything(), anything(),anything()) + + @cli.options = @cli.options.merge(:wait => true) + + @cli.ssh("example.com") + + expect($stdout.string).to eq <<-eos +Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 6918990 (example.com) +Executing SSH on Droplet (example.com)... +Wait flag given, waiting for droplet to become active +.done\e[0m (0s) +Attempting SSH: baz@104.236.32.182 +SShing with options: -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -i /Users/petersouter/.ssh/id_rsa2 -p 33 baz@104.236.32.182 + eos + end + it "does not allow ssh into a droplet that is inactive" do stub_request(:get, "https://api.digitalocean.com/v2/droplets?page=1&per_page=200"). to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplets"))