tugboat 1.3.1 → 2.0.0.RC1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +12 -8
- data/lib/tugboat/cli.rb +8 -7
- data/lib/tugboat/config.rb +8 -12
- data/lib/tugboat/middleware/add_key.rb +9 -6
- data/lib/tugboat/middleware/ask_for_credentials.rb +7 -8
- data/lib/tugboat/middleware/check_configuration.rb +1 -1
- data/lib/tugboat/middleware/check_credentials.rb +4 -2
- data/lib/tugboat/middleware/config.rb +3 -4
- data/lib/tugboat/middleware/create_droplet.rb +32 -26
- data/lib/tugboat/middleware/destroy_droplet.rb +6 -6
- data/lib/tugboat/middleware/destroy_image.rb +6 -6
- data/lib/tugboat/middleware/find_droplet.rb +20 -16
- data/lib/tugboat/middleware/find_image.rb +17 -10
- data/lib/tugboat/middleware/halt_droplet.rb +8 -8
- data/lib/tugboat/middleware/info_droplet.rb +38 -25
- data/lib/tugboat/middleware/info_image.rb +5 -5
- data/lib/tugboat/middleware/inject_client.rb +3 -9
- data/lib/tugboat/middleware/list_droplets.rb +6 -4
- data/lib/tugboat/middleware/list_images.rb +28 -23
- data/lib/tugboat/middleware/list_regions.rb +3 -3
- data/lib/tugboat/middleware/list_sizes.rb +3 -3
- data/lib/tugboat/middleware/list_ssh_keys.rb +5 -4
- data/lib/tugboat/middleware/password_reset.rb +7 -7
- data/lib/tugboat/middleware/rebuild_droplet.rb +8 -8
- data/lib/tugboat/middleware/resize_droplet.rb +7 -7
- data/lib/tugboat/middleware/restart_droplet.rb +8 -8
- data/lib/tugboat/middleware/snapshot_droplet.rb +6 -6
- data/lib/tugboat/middleware/ssh_droplet.rb +3 -1
- data/lib/tugboat/middleware/start_droplet.rb +6 -6
- data/lib/tugboat/middleware/wait_for_state.rb +6 -6
- data/lib/tugboat/version.rb +1 -1
- data/spec/cli/add_key_spec.rb +16 -9
- data/spec/cli/authorize_cli_spec.rb +24 -29
- data/spec/cli/config_cli_spec.rb +57 -0
- data/spec/cli/create_cli_spec.rb +18 -28
- data/spec/cli/debug_cli_spec.rb +8 -14
- data/spec/cli/destroy_cli_spec.rb +39 -50
- data/spec/cli/destroy_image_cli_spec.rb +33 -39
- data/spec/cli/droplets_cli_spec.rb +15 -12
- data/spec/cli/halt_cli_spec.rb +50 -46
- data/spec/cli/images_cli_spec.rb +134 -58
- data/spec/cli/info_cli_spec.rb +139 -139
- data/spec/cli/info_image_cli_spec.rb +113 -26
- data/spec/cli/keys_cli_spec.rb +7 -5
- data/spec/cli/password_reset_cli_spec.rb +46 -44
- data/spec/cli/rebuild_cli_spec.rb +187 -101
- data/spec/cli/regions_cli_spec.rb +13 -6
- data/spec/cli/resize_cli_spec.rb +51 -48
- data/spec/cli/restart_cli_spec.rb +41 -39
- data/spec/cli/sizes_cli_spec.rb +13 -8
- data/spec/cli/snapshot_cli_spec.rb +36 -37
- data/spec/cli/ssh_cli_spec.rb +7 -15
- data/spec/cli/start_cli_spec.rb +39 -35
- data/spec/cli/verify_cli_spec.rb +20 -12
- data/spec/cli/wait_cli_spec.rb +43 -27
- data/spec/config_spec.rb +19 -25
- data/spec/fixtures/create_droplet.json +44 -0
- data/spec/fixtures/create_ssh_key.json +4 -4
- data/spec/fixtures/create_ssh_key_from_file.json +8 -0
- data/spec/fixtures/droplet_start_response.json +13 -0
- data/spec/fixtures/not_found.json +4 -0
- data/spec/fixtures/password_reset_response.json +13 -0
- data/spec/fixtures/power_cycle_response.json +13 -0
- data/spec/fixtures/resize_droplet.json +13 -0
- data/spec/fixtures/restart_response.json +13 -0
- data/spec/fixtures/show_coreos_image.json +23 -0
- data/spec/fixtures/show_droplet.json +90 -11
- data/spec/fixtures/show_droplet_inactive.json +90 -11
- data/spec/fixtures/show_droplets.json +249 -30
- data/spec/fixtures/show_droplets_empty.json +5 -2
- data/spec/fixtures/show_image.json +14 -7
- data/spec/fixtures/show_images.json +1075 -13
- data/spec/fixtures/show_images_global.json +25 -16
- data/spec/fixtures/show_keys.json +15 -7
- data/spec/fixtures/show_redmine_image.json +24 -0
- data/spec/fixtures/show_regions.json +181 -12
- data/spec/fixtures/show_sizes.json +178 -9
- data/spec/fixtures/shutdown_response.json +13 -0
- data/spec/fixtures/snapshot_response.json +13 -0
- data/spec/fixtures/ubuntu_image_9801951.json +24 -0
- data/spec/middleware/check_credentials_spec.rb +4 -3
- data/spec/middleware/inject_client_spec.rb +2 -2
- data/spec/shared/environment.rb +6 -7
- data/spec/spec_helper.rb +1 -1
- data/tugboat.gemspec +39 -19
- metadata +50 -14
- data/spec/fixtures/show_droplet_fuzzy.json +0 -13
- data/spec/fixtures/show_droplets_fuzzy.json +0 -35
- data/spec/fixtures/show_droplets_inactive.json +0 -37
@@ -2,35 +2,46 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class InfoDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
|
-
|
7
|
+
response = ocean.droplet.show env["droplet_id"]
|
8
8
|
|
9
|
-
|
10
|
-
say "
|
9
|
+
unless response.success?
|
10
|
+
say "Failed to get info for Droplet: #{response.message}", :red
|
11
11
|
exit 1
|
12
12
|
end
|
13
13
|
|
14
|
-
droplet =
|
14
|
+
droplet = response.droplet
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
unless response.success?
|
17
|
+
say "Failed to find droplet: #{response.message}", :red
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
if droplet.status == "active"
|
22
|
+
status_color = GREEN
|
23
|
+
else
|
24
|
+
status_color = RED
|
25
|
+
end
|
21
26
|
|
22
27
|
attribute = env["user_attribute"]
|
23
28
|
|
29
|
+
droplet_ip4_public = droplet.networks.v4.detect { |address| address.type == 'public' }.ip_address
|
30
|
+
droplet_ip6_public = droplet.networks.v6.detect { |address| address.type == 'public' }.ip_address unless droplet.networks.v6.empty?
|
31
|
+
check_private_ip = droplet.networks.v4.detect { |address| address.type == 'private' }
|
32
|
+
droplet_private_ip = check_private_ip.ip_address if check_private_ip
|
33
|
+
|
24
34
|
attributes_list = [
|
25
35
|
["name", droplet.name],
|
26
36
|
["id", droplet.id],
|
27
37
|
["status", droplet.status],
|
28
|
-
["
|
29
|
-
["
|
30
|
-
["
|
31
|
-
["
|
32
|
-
["
|
33
|
-
["
|
38
|
+
["ip4", droplet_ip4_public],
|
39
|
+
["ip6", droplet_ip6_public],
|
40
|
+
["private_ip", droplet_private_ip],
|
41
|
+
["region", droplet.region.slug],
|
42
|
+
["Image", droplet.image.id],
|
43
|
+
["size", droplet.size_slug],
|
44
|
+
["backups_active", !droplet.backup_ids.empty?]
|
34
45
|
]
|
35
46
|
attributes = Hash[*attributes_list.flatten(1)]
|
36
47
|
|
@@ -40,7 +51,8 @@ module Tugboat
|
|
40
51
|
else
|
41
52
|
say "Invalid attribute \"#{attribute}\"", :red
|
42
53
|
say "Provide one of the following:", :red
|
43
|
-
attributes_list.
|
54
|
+
attributes_list.each { |a| say " #{a[0]}", :red }
|
55
|
+
exit 1
|
44
56
|
end
|
45
57
|
else
|
46
58
|
if env["user_porcelain"]
|
@@ -50,16 +62,17 @@ module Tugboat
|
|
50
62
|
say "Name: #{droplet.name}"
|
51
63
|
say "ID: #{droplet.id}"
|
52
64
|
say "Status: #{status_color}#{droplet.status}#{CLEAR}"
|
53
|
-
say "
|
65
|
+
say "IP4: #{droplet_ip4_public}"
|
66
|
+
say "IP6: #{droplet_ip6_public}" unless droplet.networks.v6.empty?
|
54
67
|
|
55
|
-
if
|
56
|
-
|
57
|
-
|
68
|
+
if droplet_private_ip
|
69
|
+
say "Private IP: #{droplet_private_ip}"
|
70
|
+
end
|
58
71
|
|
59
|
-
say "Region
|
60
|
-
say "Image
|
61
|
-
say "Size
|
62
|
-
say "Backups Active: #{droplet.
|
72
|
+
say "Region: #{droplet.region.name} - #{droplet.region.slug}"
|
73
|
+
say "Image: #{droplet.image.id} - #{droplet.image.name}"
|
74
|
+
say "Size: #{droplet.size_slug.upcase}"
|
75
|
+
say "Backups Active: #{!droplet.backup_ids.empty?}"
|
63
76
|
end
|
64
77
|
end
|
65
78
|
|
@@ -2,16 +2,16 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class InfoImage < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
|
-
|
7
|
+
response = ocean.image.show env["image_id"]
|
8
8
|
|
9
|
-
|
10
|
-
say "
|
9
|
+
unless response.success?
|
10
|
+
say "Failed to get info for Image: #{response.message}", :red
|
11
11
|
exit 1
|
12
12
|
end
|
13
13
|
|
14
|
-
image =
|
14
|
+
image = response.image
|
15
15
|
|
16
16
|
say
|
17
17
|
say "Name: #{image.name}"
|
@@ -1,6 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require File.expand_path('../authentication_middleware', __FILE__)
|
3
|
-
require File.expand_path('../custom_logger', __FILE__)
|
1
|
+
require 'barge'
|
4
2
|
|
5
3
|
module Tugboat
|
6
4
|
module Middleware
|
@@ -22,13 +20,9 @@ module Tugboat
|
|
22
20
|
def call(env)
|
23
21
|
# Sets the digital ocean client into the environment for use
|
24
22
|
# later.
|
25
|
-
@
|
26
|
-
@api_key = env["config"].api_key
|
23
|
+
@access_token = env["config"].access_token
|
27
24
|
|
28
|
-
env[
|
29
|
-
:client_id => @client_id,
|
30
|
-
:api_key => @api_key,
|
31
|
-
:faraday => tugboat_faraday
|
25
|
+
env['barge'] = Barge::Client.new(:access_token => @access_token)
|
32
26
|
|
33
27
|
@app.call(env)
|
34
28
|
end
|
@@ -3,9 +3,9 @@ module Tugboat
|
|
3
3
|
# Check if the client has set-up configuration yet.
|
4
4
|
class ListDroplets < Base
|
5
5
|
def call(env)
|
6
|
-
ocean = env[
|
6
|
+
ocean = env['barge']
|
7
7
|
|
8
|
-
droplet_list = ocean.
|
8
|
+
droplet_list = ocean.droplet.all.droplets
|
9
9
|
|
10
10
|
if droplet_list.empty?
|
11
11
|
say "You don't appear to have any droplets.", :red
|
@@ -14,7 +14,8 @@ module Tugboat
|
|
14
14
|
droplet_list.each do |droplet|
|
15
15
|
|
16
16
|
if droplet.private_ip_address
|
17
|
-
|
17
|
+
private_addr = droplet.networks.v4.detect { |address| address.type == 'private' }
|
18
|
+
private_ip = ", privateip: #{private_addr.ip_address}"
|
18
19
|
end
|
19
20
|
|
20
21
|
if droplet.status == "active"
|
@@ -23,7 +24,8 @@ module Tugboat
|
|
23
24
|
status_color = RED
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
public_addr = droplet.networks.v4.detect { |address| address.type == 'public' }
|
28
|
+
say "#{droplet.name} (ip: #{public_addr.ip_address}#{private_ip}, status: #{status_color}#{droplet.status}#{CLEAR}, region: #{droplet.region.slug}, id: #{droplet.id})"
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -2,30 +2,36 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class ListImages < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
6
|
-
my_images = ocean.
|
7
|
-
|
8
|
-
global = ocean.images.list :filter => "global"
|
9
|
-
else
|
10
|
-
say "Listing Your Images"
|
11
|
-
say "(Use `tugboat images --global` to show all images)"
|
12
|
-
end
|
5
|
+
ocean = env['barge']
|
6
|
+
my_images = ocean.image.all(:private => true)
|
7
|
+
public_images = ocean.image.all.images - my_images.images
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
if env['user_show_just_private_images']
|
10
|
+
say "Showing just private images", :green
|
11
|
+
say "Private Images:", :blue
|
12
|
+
my_images_list = my_images.images
|
13
|
+
if my_images_list.nil? || my_images_list.empty?
|
14
|
+
say "No private images found"
|
15
|
+
else
|
16
|
+
my_images_list.each do |image|
|
17
|
+
say "#{image.name} (id: #{image.id}, distro: #{image.distribution})"
|
18
|
+
end
|
19
|
+
end
|
18
20
|
else
|
19
|
-
|
20
|
-
|
21
|
+
say "Showing both private and public images"
|
22
|
+
say "Private Images:", :blue
|
23
|
+
my_images_list = my_images.images
|
24
|
+
if my_images_list.nil? || my_images_list.empty?
|
25
|
+
say "No private images found"
|
26
|
+
else
|
27
|
+
my_images_list.each do |image|
|
28
|
+
say "#{image.name} (id: #{image.id}, distro: #{image.distribution})"
|
29
|
+
end
|
21
30
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
say "Global Images:"
|
27
|
-
global.images.each do |image|
|
28
|
-
say "#{image.name} (id: #{image.id}, distro: #{image.distribution})"
|
31
|
+
say ''
|
32
|
+
say "Public Images:", :blue
|
33
|
+
public_images.each do |image|
|
34
|
+
say "#{image.name} (slug: #{image.slug}, id: #{image.id}, distro: #{image.distribution})"
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
@@ -33,5 +39,4 @@ module Tugboat
|
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
36
|
-
end
|
37
|
-
|
42
|
+
end
|
@@ -2,12 +2,12 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class ListRegions < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
6
|
-
regions = ocean.
|
5
|
+
ocean = env['barge']
|
6
|
+
regions = ocean.region.all.regions.sort_by(&:name)
|
7
7
|
|
8
8
|
say "Regions:"
|
9
9
|
regions.each do |region|
|
10
|
-
say "#{region.name} (
|
10
|
+
say "#{region.name} (slug: #{region.slug})"
|
11
11
|
end
|
12
12
|
|
13
13
|
@app.call(env)
|
@@ -2,12 +2,12 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class ListSizes < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
6
|
-
sizes = ocean.
|
5
|
+
ocean = env['barge']
|
6
|
+
sizes = ocean.size.all.sizes
|
7
7
|
|
8
8
|
say "Sizes:"
|
9
9
|
sizes.each do |size|
|
10
|
-
say "#{size.
|
10
|
+
say "Disk: #{size.disk}GB, Memory: #{size.memory.round}MB (slug: #{size.slug})"
|
11
11
|
end
|
12
12
|
|
13
13
|
@app.call(env)
|
@@ -2,12 +2,13 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class ListSSHKeys < Base
|
4
4
|
def call(env)
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
ocean = env['barge']
|
7
|
+
ssh_keys = ocean.key.all.ssh_keys
|
7
8
|
|
8
9
|
say "SSH Keys:"
|
9
|
-
ssh_keys.
|
10
|
-
say "#{key.name} (id: #{key.id})"
|
10
|
+
ssh_keys.each do |key|
|
11
|
+
say "Name: #{key.name}, (id: #{key.id}), fingerprint: #{key.fingerprint}"
|
11
12
|
end
|
12
13
|
|
13
14
|
@app.call(env)
|
@@ -2,19 +2,19 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class PasswordReset < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
7
|
say "Queuing password reset for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
8
|
-
|
8
|
+
response = ocean.droplet.password_reset env["droplet_id"]
|
9
9
|
|
10
|
-
|
11
|
-
say
|
10
|
+
unless response.success?
|
11
|
+
say "Failed to reset password on Droplet: #{response.message}", :red
|
12
12
|
exit 1
|
13
|
+
else
|
14
|
+
say "Password reset successful!", :green
|
15
|
+
say "Your new root password will be emailed to you", :green
|
13
16
|
end
|
14
17
|
|
15
|
-
say "done", :green
|
16
|
-
say "Your new root password will be emailed to you"
|
17
|
-
|
18
18
|
@app.call(env)
|
19
19
|
end
|
20
20
|
end
|
@@ -2,20 +2,20 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class RebuildDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
7
|
say "Queuing rebuild for droplet #{env["droplet_id"]} #{env["droplet_name"]} with image #{env["image_id"]} #{env["image_name"]}...", nil, false
|
8
|
-
|
9
|
-
req = ocean.droplets.rebuild env["droplet_id"],
|
10
|
-
:image_id => env["image_id"]
|
11
8
|
|
12
|
-
|
13
|
-
|
9
|
+
response = ocean.droplet.rebuild env["droplet_id"],
|
10
|
+
:image_id => env["image_id"]
|
11
|
+
|
12
|
+
unless response.success?
|
13
|
+
say "Failed to rebuild Droplet: #{response.message}", :red
|
14
14
|
exit 1
|
15
|
+
else
|
16
|
+
say "Rebuild complete", :green
|
15
17
|
end
|
16
18
|
|
17
|
-
say "done", :green
|
18
|
-
|
19
19
|
@app.call(env)
|
20
20
|
end
|
21
21
|
end
|
@@ -2,20 +2,20 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class ResizeDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
7
|
say "Queuing resize for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
8
8
|
|
9
|
-
|
10
|
-
:
|
9
|
+
response = ocean.droplet.resize env["droplet_id"],
|
10
|
+
:size => env["user_droplet_size"]
|
11
11
|
|
12
|
-
|
13
|
-
say "
|
12
|
+
unless response.success?
|
13
|
+
say "Failed to resize Droplet: #{response.message}", :red
|
14
14
|
exit 1
|
15
|
+
else
|
16
|
+
say "Resize complete!", :green
|
15
17
|
end
|
16
18
|
|
17
|
-
say "done", :green
|
18
|
-
|
19
19
|
@app.call(env)
|
20
20
|
end
|
21
21
|
end
|
@@ -2,23 +2,23 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class RestartDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
|
-
|
7
|
+
response = if env["user_droplet_hard"]
|
8
8
|
say "Queuing hard restart for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
9
|
-
ocean.
|
9
|
+
ocean.droplet.power_cycle env["droplet_id"]
|
10
10
|
else
|
11
11
|
say "Queuing restart for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
12
|
-
ocean.
|
12
|
+
ocean.droplet.reboot env["droplet_id"]
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
say "
|
15
|
+
unless response.success?
|
16
|
+
say "Failed to restart Droplet: #{response.message}", :red
|
17
17
|
exit 1
|
18
|
+
else
|
19
|
+
say "Restart complete!", :green
|
18
20
|
end
|
19
21
|
|
20
|
-
say "done", :green
|
21
|
-
|
22
22
|
@app.call(env)
|
23
23
|
end
|
24
24
|
end
|
@@ -2,7 +2,7 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class SnapshotDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
# Right now, the digital ocean API doesn't return an error
|
7
7
|
# when your droplet is not powered off and you try to snapshot.
|
8
8
|
# This is a temporary measure to let the user know.
|
@@ -10,16 +10,16 @@ module Tugboat
|
|
10
10
|
|
11
11
|
say "Queuing snapshot '#{env["user_snapshot_name"]}' for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
12
12
|
|
13
|
-
|
13
|
+
response = ocean.droplet.snapshot env["droplet_id"],
|
14
14
|
:name => env["user_snapshot_name"]
|
15
15
|
|
16
|
-
|
17
|
-
say "
|
16
|
+
unless response.success?
|
17
|
+
say "Failed to snapshot Droplet: #{response.message}", :red
|
18
18
|
exit 1
|
19
|
+
else
|
20
|
+
say "Snapshot successful!", :red
|
19
21
|
end
|
20
22
|
|
21
|
-
say "done", :green
|
22
|
-
|
23
23
|
@app.call(env)
|
24
24
|
end
|
25
25
|
end
|
@@ -35,8 +35,10 @@ module Tugboat
|
|
35
35
|
if env["droplet_ip_private"]
|
36
36
|
say "This droplet has a private IP, checking if you asked to use the Private IP..."
|
37
37
|
if env["user_droplet_use_private_ip"]
|
38
|
-
say "You did! Using private IP for ssh..."
|
38
|
+
say "You did! Using private IP for ssh...", :yellow
|
39
39
|
host_ip = env["droplet_ip_private"]
|
40
|
+
else
|
41
|
+
say "You didn't! Using public IP for ssh...", :yellow
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
@@ -2,18 +2,18 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class StartDroplet < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
7
|
say "Queuing start for #{env["droplet_id"]} #{env["droplet_name"]}...", nil, false
|
8
|
-
|
8
|
+
response = ocean.droplet.power_on env["droplet_id"]
|
9
9
|
|
10
|
-
|
11
|
-
say "
|
10
|
+
unless response.success?
|
11
|
+
say "Failed to start Droplet: #{response.message}", :red
|
12
12
|
exit 1
|
13
|
+
else
|
14
|
+
say "Start complete!", :green
|
13
15
|
end
|
14
16
|
|
15
|
-
say "done", :green
|
16
|
-
|
17
17
|
@app.call(env)
|
18
18
|
end
|
19
19
|
end
|
@@ -2,24 +2,24 @@ module Tugboat
|
|
2
2
|
module Middleware
|
3
3
|
class WaitForState < Base
|
4
4
|
def call(env)
|
5
|
-
ocean = env[
|
5
|
+
ocean = env['barge']
|
6
6
|
|
7
7
|
say "Waiting for droplet to become #{env["user_droplet_desired_state"]}.", nil, false
|
8
8
|
|
9
9
|
start_time = Time.now
|
10
10
|
|
11
|
-
|
11
|
+
response = ocean.droplet.show env["droplet_id"]
|
12
12
|
|
13
13
|
say ".", nil, false
|
14
14
|
|
15
|
-
if
|
16
|
-
say
|
15
|
+
if !response.success?
|
16
|
+
say "Failed to get status of Droplet: #{response.message}", :red
|
17
17
|
exit 1
|
18
18
|
end
|
19
19
|
|
20
|
-
while
|
20
|
+
while response.droplet.status != env["user_droplet_desired_state"] do
|
21
21
|
sleep 2
|
22
|
-
|
22
|
+
response = ocean.droplet.show env["droplet_id"]
|
23
23
|
say ".", nil, false
|
24
24
|
end
|
25
25
|
|
data/lib/tugboat/version.rb
CHANGED
data/spec/cli/add_key_spec.rb
CHANGED
@@ -19,17 +19,21 @@ describe Tugboat::CLI do
|
|
19
19
|
describe "add-key" do
|
20
20
|
it "with a name and key string" do
|
21
21
|
|
22
|
-
stub_request(:
|
23
|
-
|
22
|
+
stub_request(:post, "https://api.digitalocean.com/v2/account/keys").
|
23
|
+
with(:body => "{\"name\":\"macbook_pro\",\"public_key\":\"ssh-dss A123= user@host\"}").
|
24
|
+
to_return(:status => 201, :body => fixture('create_ssh_key'), :headers => {})
|
24
25
|
|
25
26
|
@cli.options = @cli.options.merge(:key => "#{ssh_public_key}")
|
26
27
|
@cli.add_key(ssh_key_name)
|
27
28
|
|
28
29
|
expect($stdout.string).to eq <<-eos
|
29
|
-
Queueing upload of SSH key '
|
30
|
+
Queueing upload of SSH key 'macbook_pro'...SSH Key uploaded
|
31
|
+
|
32
|
+
Name: macbook_pro
|
33
|
+
ID: 3
|
30
34
|
eos
|
31
35
|
|
32
|
-
expect(a_request(:
|
36
|
+
expect(a_request(:post, "https://api.digitalocean.com/v2/account/keys")).to have_been_made
|
33
37
|
end
|
34
38
|
|
35
39
|
before :each do
|
@@ -41,8 +45,10 @@ Queueing upload of SSH key '#{ssh_key_name}'...done
|
|
41
45
|
end
|
42
46
|
|
43
47
|
it "with name, prompts from file folder" do
|
44
|
-
stub_request(:
|
45
|
-
|
48
|
+
stub_request(:post, "https://api.digitalocean.com/v2/account/keys").
|
49
|
+
with(:body => "{\"name\":\"macbook_pro\",\"public_key\":\"ssh-dss A456= user@host\"}",
|
50
|
+
:headers => {'Accept'=>'*/*', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json'}).
|
51
|
+
to_return(:status => 201, :body => fixture('create_ssh_key_from_file'), :headers => {})
|
46
52
|
|
47
53
|
expect($stdout).to receive(:print).exactly(4).times
|
48
54
|
expect($stdout).to receive(:print).with("Enter the path to your SSH key: ")
|
@@ -56,10 +62,11 @@ Possible public key paths from #{fake_home}/.ssh:
|
|
56
62
|
|
57
63
|
#{fake_home}/.ssh/id_rsa.pub
|
58
64
|
|
59
|
-
|
60
|
-
eos
|
65
|
+
SSH Key uploaded
|
61
66
|
|
62
|
-
|
67
|
+
Name: cool_key
|
68
|
+
ID: 5
|
69
|
+
eos
|
63
70
|
end
|
64
71
|
|
65
72
|
after :each do
|