tugboat 1.3.1 → 2.0.0.RC1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|