tugboat 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +21 -1
- data/README.md +18 -0
- data/lib/tugboat/cli.rb +9 -3
- data/lib/tugboat/config.rb +43 -4
- data/lib/tugboat/middleware.rb +10 -0
- data/lib/tugboat/middleware/ask_for_credentials.rb +9 -1
- data/lib/tugboat/middleware/authentication_middleware.rb +40 -0
- data/lib/tugboat/middleware/check_credentials.rb +1 -1
- data/lib/tugboat/middleware/create_droplet.rb +21 -5
- data/lib/tugboat/middleware/custom_logger.rb +72 -0
- data/lib/tugboat/middleware/inject_client.rb +22 -3
- data/lib/tugboat/middleware/list_droplets.rb +1 -1
- data/lib/tugboat/version.rb +1 -1
- data/spec/cli/authorize_cli_spec.rb +44 -1
- data/spec/cli/create_cli_spec.rb +7 -7
- data/spec/cli/droplets_cli_spec.rb +1 -1
- data/spec/cli/verify_cli_spec.rb +26 -0
- data/spec/config_spec.rb +89 -35
- data/spec/middleware/ssh_droplet_spec.rb +1 -1
- data/spec/shared/environment.rb +6 -2
- metadata +14 -29
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: acb3d5fff3be496ee45a238c9219bea4c159ca4e
|
4
|
+
data.tar.gz: a88aea864325b1d5b0e7d37642b42418e79ed905
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e53bbe9b2bf1e3bd5bef1f748249857045da696f57e250b2819aa7261db9bdd769ed53b21e60258de6f1c5090e05de8906b0f47de4f313cacf62c20c74357c9a
|
7
|
+
data.tar.gz: 0806ce448db80b8a5436c647f56e144a4b94394fbc866bc4a676cea6f45bed21d4b1649339c1b3f55ca13c462fa89b08f251b539ab92d3b4358405162a69181a
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
|
-
## 0.0.
|
1
|
+
## 0.0.8 (Unreleased)
|
2
|
+
|
3
|
+
FEATURES:
|
4
|
+
|
5
|
+
- [Pete](https://github.com/petems) added configuration defaults
|
6
|
+
that you can set. [GH-61]
|
7
|
+
- [Pete](https://github.com/petems) added log filtering to debug output.
|
8
|
+
`DEBUG=1` now gives you filtered logs, `DEBUG=2`, raw. [GH-58]
|
2
9
|
|
3
10
|
IMPROVEMENTS:
|
11
|
+
|
12
|
+
- Error messages are now caught at the Faraday level and displayed
|
13
|
+
back to the user.
|
14
|
+
|
15
|
+
BUG FIXES:
|
16
|
+
|
17
|
+
- [Ørjan](https://github.com/blom) added a color reset on the `list`
|
18
|
+
command. [GH-57]
|
19
|
+
|
20
|
+
## 0.0.7 (August 2, 2013)
|
21
|
+
|
22
|
+
IMPROVEMENTS:
|
23
|
+
|
4
24
|
- [Pete](https://github.com/petems) made it clearer to the user
|
5
25
|
if they don't have any droplets or images. [GH-48], [GH-49]
|
6
26
|
|
data/README.md
CHANGED
@@ -19,6 +19,15 @@ Run the configuration utility, `tugboat authorize`. You can grab your keys
|
|
19
19
|
Enter your SSH key path (optional, defaults to ~/.ssh/id_rsa):
|
20
20
|
Enter your SSH user (optional, defaults to jack):
|
21
21
|
Enter your SSH port number (optional, defaults to 22):
|
22
|
+
|
23
|
+
To retrieve region, image, size and key ID's, you can use the corresponding tugboat command, such as `tugboat images`.
|
24
|
+
Defaults can be changed at any time in your ~/.tugboat configuration file.
|
25
|
+
|
26
|
+
Enter your default region ID (optional, defaults to 1 (New York)):
|
27
|
+
Enter your default image ID (optional, defaults to 284203 (Ubuntu 12.04 x64)):
|
28
|
+
Enter your default size ID (optional, defaults to 66 (512MB)):
|
29
|
+
Enter your default ssh key ID (optional, defaults to none):
|
30
|
+
|
22
31
|
Authentication with DigitalOcean was successful!
|
23
32
|
|
24
33
|
## Usage
|
@@ -180,6 +189,15 @@ For a complete overview of all of the available commands, run:
|
|
180
189
|
|
181
190
|
$ tugboat help
|
182
191
|
|
192
|
+
## Reporting Bugs
|
193
|
+
|
194
|
+
Yes, please!
|
195
|
+
|
196
|
+
It's very helpful if you can run `DEBUG=1 tugboat ...` with the command
|
197
|
+
that is causing you issues, and then include that in the issue.
|
198
|
+
|
199
|
+
You can create a new issue [here](https://github.com/pearkes/tugboat/issues/new). Thank you!
|
200
|
+
|
183
201
|
## Contributing
|
184
202
|
|
185
203
|
See the [contributing guide](CONTRIBUTING.md).
|
data/lib/tugboat/cli.rb
CHANGED
@@ -36,6 +36,15 @@ module Tugboat
|
|
36
36
|
Middleware.sequence_authorize.call({})
|
37
37
|
end
|
38
38
|
|
39
|
+
desc "verify", "Check your DigitalOcean credentials"
|
40
|
+
long_desc "This tests that your credentials created by the \`authorize\`
|
41
|
+
command that are stored in ~/.tugboat are correct and allow you to connect
|
42
|
+
to the API without errors.
|
43
|
+
"
|
44
|
+
def verify
|
45
|
+
Middleware.sequence_verify.call({})
|
46
|
+
end
|
47
|
+
|
39
48
|
desc "droplets", "Retrieve a list of your droplets"
|
40
49
|
def droplets
|
41
50
|
Middleware.sequence_list_droplets.call({})
|
@@ -89,17 +98,14 @@ module Tugboat
|
|
89
98
|
method_option "size",
|
90
99
|
:type => :numeric,
|
91
100
|
:aliases => "-s",
|
92
|
-
:default => 66,
|
93
101
|
:desc => "The size_id of the droplet"
|
94
102
|
method_option "image",
|
95
103
|
:type => :numeric,
|
96
104
|
:aliases => "-i",
|
97
|
-
:default => 284203,
|
98
105
|
:desc => "The image_id of the droplet"
|
99
106
|
method_option "region",
|
100
107
|
:type => :numeric,
|
101
108
|
:aliases => "-r",
|
102
|
-
:default => 1,
|
103
109
|
:desc => "The region_id of the droplet"
|
104
110
|
method_option "keys",
|
105
111
|
:type => :string,
|
data/lib/tugboat/config.rb
CHANGED
@@ -12,6 +12,10 @@ module Tugboat
|
|
12
12
|
FILE_NAME = '.tugboat'
|
13
13
|
DEFAULT_SSH_KEY_PATH = '.ssh/id_rsa'
|
14
14
|
DEFAULT_SSH_PORT = '22'
|
15
|
+
DEFAULT_REGION = '1'
|
16
|
+
DEFAULT_IMAGE = '284203'
|
17
|
+
DEFAULT_SIZE = '66'
|
18
|
+
DEFAULT_SSH_KEY = ''
|
15
19
|
|
16
20
|
def initialize
|
17
21
|
@path = ENV["TUGBOAT_CONFIG_PATH"] || File.join(File.expand_path("~"), FILE_NAME)
|
@@ -42,11 +46,27 @@ module Tugboat
|
|
42
46
|
def ssh_user
|
43
47
|
@data['ssh']['ssh_user']
|
44
48
|
end
|
45
|
-
|
49
|
+
|
46
50
|
def ssh_port
|
47
51
|
@data['ssh']['ssh_port']
|
48
52
|
end
|
49
53
|
|
54
|
+
def default_region
|
55
|
+
@data['defaults'].nil? ? DEFAULT_REGION : @data['defaults']['region']
|
56
|
+
end
|
57
|
+
|
58
|
+
def default_image
|
59
|
+
@data['defaults'].nil? ? DEFAULT_IMAGE : @data['defaults']['image']
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_size
|
63
|
+
@data['defaults'].nil? ? DEFAULT_SIZE : @data['defaults']['size']
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_ssh_key
|
67
|
+
@data['defaults'].nil? ? DEFAULT_SSH_KEY : @data['defaults']['ssh_key']
|
68
|
+
end
|
69
|
+
|
50
70
|
# Re-runs initialize
|
51
71
|
def reset!
|
52
72
|
self.send(:initialize)
|
@@ -58,7 +78,7 @@ module Tugboat
|
|
58
78
|
end
|
59
79
|
|
60
80
|
# Writes a config file
|
61
|
-
def create_config_file(client, api, ssh_key_path, ssh_user, ssh_port)
|
81
|
+
def create_config_file(client, api, ssh_key_path, ssh_user, ssh_port, region, image, size, ssh_key)
|
62
82
|
# Default SSH Key path
|
63
83
|
if ssh_key_path.empty?
|
64
84
|
ssh_key_path = File.join(File.expand_path("~"), DEFAULT_SSH_KEY_PATH)
|
@@ -72,10 +92,29 @@ module Tugboat
|
|
72
92
|
ssh_port = DEFAULT_SSH_PORT
|
73
93
|
end
|
74
94
|
|
95
|
+
if region.empty?
|
96
|
+
region = DEFAULT_REGION
|
97
|
+
end
|
98
|
+
|
99
|
+
if image.empty?
|
100
|
+
image = DEFAULT_IMAGE
|
101
|
+
end
|
102
|
+
|
103
|
+
if size.empty?
|
104
|
+
size = DEFAULT_SIZE
|
105
|
+
end
|
106
|
+
|
107
|
+
if ssh_key.empty?
|
108
|
+
default_ssh_key = DEFAULT_SSH_KEY
|
109
|
+
end
|
110
|
+
|
75
111
|
require 'yaml'
|
76
112
|
File.open(@path, File::RDWR|File::TRUNC|File::CREAT, 0600) do |file|
|
77
|
-
data = {
|
78
|
-
"
|
113
|
+
data = {
|
114
|
+
"authentication" => { "client_key" => client, "api_key" => api },
|
115
|
+
"ssh" => { "ssh_user" => ssh_user, "ssh_key_path" => ssh_key_path , "ssh_port" => ssh_port},
|
116
|
+
"defaults" => { "region" => region, "image" => image, "size" => size, "ssh_key" => ssh_key }
|
117
|
+
}
|
79
118
|
file.write data.to_yaml
|
80
119
|
end
|
81
120
|
end
|
data/lib/tugboat/middleware.rb
CHANGED
@@ -42,6 +42,16 @@ module Tugboat
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
# This checks that the credentials in ~/.tugboat are valid
|
46
|
+
def self.sequence_verify
|
47
|
+
::Middleware::Builder.new do
|
48
|
+
use InjectConfiguration
|
49
|
+
use CheckConfiguration
|
50
|
+
use InjectClient
|
51
|
+
use CheckCredentials
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
45
55
|
# Display a list of droplets
|
46
56
|
def self.sequence_list_droplets
|
47
57
|
::Middleware::Builder.new do
|
@@ -10,9 +10,17 @@ module Tugboat
|
|
10
10
|
ssh_key_path = ask "Enter your SSH key path (optional, defaults to ~/.ssh/id_rsa):"
|
11
11
|
ssh_user = ask "Enter your SSH user (optional, defaults to #{ENV['USER']}):"
|
12
12
|
ssh_port = ask "Enter your SSH port number (optional, defaults to 22):"
|
13
|
+
say
|
14
|
+
say "To retrieve region, image, size and key ID's, you can use the corresponding tugboat command, such as `tugboat images`."
|
15
|
+
say "Defaults can be changed at any time in your ~/.tugboat configuration file."
|
16
|
+
say
|
17
|
+
region = ask "Enter your default region ID (optional, defaults to 1 (New York)):"
|
18
|
+
image = ask "Enter your default image ID (optional, defaults to 284203 (Ubuntu 12.04 x64)):"
|
19
|
+
size = ask "Enter your default size ID (optional, defaults to 66 (512MB)):"
|
20
|
+
ssh_key = ask "Enter your default ssh key ID (optional, defaults to none):"
|
13
21
|
|
14
22
|
# Write the config file.
|
15
|
-
env['config'].create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port)
|
23
|
+
env['config'].create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port, region, image, size, ssh_key)
|
16
24
|
env['config'].reload!
|
17
25
|
|
18
26
|
@app.call(env)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Tugboat
|
2
|
+
class AuthenticationMiddleware < Faraday::Middleware
|
3
|
+
extend Forwardable
|
4
|
+
def_delegators :'Faraday::Utils', :parse_query, :build_query
|
5
|
+
RED = "\e[31m"
|
6
|
+
CLEAR = "\e[0m"
|
7
|
+
|
8
|
+
def initialize(app, client_id, api_key)
|
9
|
+
@client_id = client_id
|
10
|
+
@api_key = api_key
|
11
|
+
|
12
|
+
super(app)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
params = { 'client_id' => @client_id, 'api_key' => @api_key }.update query_params(env[:url])
|
17
|
+
|
18
|
+
env[:url].query = build_query params
|
19
|
+
|
20
|
+
begin
|
21
|
+
@app.call(env)
|
22
|
+
rescue Faraday::Error::ClientError => e
|
23
|
+
puts "#{RED}#{e}!#{CLEAR}\n"
|
24
|
+
if env[:body].status == "ERROR"
|
25
|
+
puts "\n#{RED}#{env[:body].error_message}#{CLEAR}\n\n"
|
26
|
+
end
|
27
|
+
puts "Double-check your parameters and configuration (in your ~/.tugboat file)"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def query_params(url)
|
33
|
+
if url.query.nil? or url.query.empty?
|
34
|
+
{}
|
35
|
+
else
|
36
|
+
parse_query url.query
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -6,11 +6,27 @@ module Tugboat
|
|
6
6
|
|
7
7
|
say "Queueing creation of droplet '#{env["create_droplet_name"]}'...", nil, false
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
env["create_droplet_region_id"] ?
|
10
|
+
droplet_region_id = env["create_droplet_region_id"] :
|
11
|
+
droplet_region_id = env["config"].default_region
|
12
|
+
|
13
|
+
env["create_droplet_image_id"] ?
|
14
|
+
droplet_image_id = env["create_droplet_image_id"] :
|
15
|
+
droplet_image_id = env["config"].default_image
|
16
|
+
|
17
|
+
env["create_droplet_size_id"] ?
|
18
|
+
droplet_size_id = env["create_droplet_size_id"] :
|
19
|
+
droplet_size_id = env["config"].default_size
|
20
|
+
|
21
|
+
env["create_droplet_ssh_key_ids"] ?
|
22
|
+
droplet_ssh_key_id = env["create_droplet_ssh_key_ids"] :
|
23
|
+
droplet_ssh_key_id = env["config"].default_ssh_key
|
24
|
+
|
25
|
+
req = ocean.droplets.create :name => env["create_droplet_name"],
|
26
|
+
:size_id => droplet_size_id,
|
27
|
+
:image_id => droplet_image_id,
|
28
|
+
:region_id => droplet_region_id,
|
29
|
+
:ssh_key_ids => droplet_ssh_key_id
|
14
30
|
|
15
31
|
if req.status == "ERROR"
|
16
32
|
say req.error_message, :red
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Tugboat
|
2
|
+
class CustomLogger < Faraday::Middleware
|
3
|
+
extend Forwardable
|
4
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
5
|
+
|
6
|
+
def initialize(app, options = {})
|
7
|
+
@app = app
|
8
|
+
@logger = options.fetch(:logger) {
|
9
|
+
require 'logger'
|
10
|
+
::Logger.new(STDOUT)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
start_time = Time.now
|
16
|
+
info { request_info(env) }
|
17
|
+
debug { request_debug(env) }
|
18
|
+
@app.call(env).on_complete do
|
19
|
+
end_time = Time.now
|
20
|
+
response_time = end_time - start_time
|
21
|
+
info { response_info(env, response_time) }
|
22
|
+
debug { response_debug(env) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def filter(output)
|
29
|
+
unless ENV['DEBUG'] == '2'
|
30
|
+
output = output.to_s.gsub(/client_id=[a-zA-Z0-9]*/,'client_id=[CLIENT-ID]')
|
31
|
+
output = output.to_s.gsub(/api_key=[a-zA-Z0-9]*/,'api_key=[API-KEY]')
|
32
|
+
output = output.to_s.gsub(/_digitalocean2_session_v2=[a-zA-Z0-9%-]*/,'_digitalocean2_session_v2=[SESSION_COOKIE]')
|
33
|
+
else
|
34
|
+
output
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def request_info(env)
|
39
|
+
"Started %s request to: %s" % [ env[:method].to_s.upcase, filter(env[:url]) ]
|
40
|
+
end
|
41
|
+
|
42
|
+
def response_info(env, response_time)
|
43
|
+
"Response from %s; Status: %d; Time: %.1fms" % [ filter(env[:url]), env[:status], (response_time * 1_000.0) ]
|
44
|
+
end
|
45
|
+
|
46
|
+
def request_debug(env)
|
47
|
+
debug_message("Request", env[:request_headers], env[:body])
|
48
|
+
end
|
49
|
+
|
50
|
+
def response_debug(env)
|
51
|
+
debug_message("Response", env[:response_headers], env[:body])
|
52
|
+
end
|
53
|
+
|
54
|
+
def debug_message(name, headers, body)
|
55
|
+
<<-MESSAGE.gsub(/^ +([^ ])/m, '\\1')
|
56
|
+
#{name} Headers:
|
57
|
+
----------------
|
58
|
+
#{format_headers(headers)}
|
59
|
+
|
60
|
+
#{name} Body:
|
61
|
+
-------------
|
62
|
+
#{body}
|
63
|
+
MESSAGE
|
64
|
+
end
|
65
|
+
|
66
|
+
def format_headers(headers)
|
67
|
+
length = headers.map {|k,v| k.to_s.size }.max
|
68
|
+
headers.map { |name, value| "#{name.to_s.ljust(length)} : #{filter(value)}" }.join("\n")
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -1,15 +1,34 @@
|
|
1
1
|
require 'digital_ocean'
|
2
|
+
require File.expand_path('../authentication_middleware', __FILE__)
|
3
|
+
require File.expand_path('../custom_logger', __FILE__)
|
4
|
+
|
2
5
|
module Tugboat
|
3
6
|
module Middleware
|
4
7
|
# Inject the digital ocean client into the environment
|
5
8
|
class InjectClient < Base
|
9
|
+
|
10
|
+
def tugboat_faraday
|
11
|
+
Faraday.new(:url => 'https://api.digitalocean.com/') do |faraday|
|
12
|
+
faraday.use AuthenticationMiddleware, @client_id, @api_key
|
13
|
+
faraday.use Faraday::Response::RaiseError
|
14
|
+
faraday.use CustomLogger if ENV['DEBUG']
|
15
|
+
faraday.request :url_encoded
|
16
|
+
faraday.response :rashify
|
17
|
+
faraday.response :json
|
18
|
+
faraday.adapter Faraday.default_adapter
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
6
22
|
def call(env)
|
7
23
|
# Sets the digital ocean client into the environment for use
|
8
24
|
# later.
|
25
|
+
@client_id = env["config"].client_key
|
26
|
+
@api_key = env["config"].api_key
|
27
|
+
|
9
28
|
env["ocean"] = DigitalOcean::API.new \
|
10
|
-
:client_id =>
|
11
|
-
:api_key =>
|
12
|
-
:
|
29
|
+
:client_id => @client_id,
|
30
|
+
:api_key => @api_key,
|
31
|
+
:faraday => tugboat_faraday
|
13
32
|
|
14
33
|
@app.call(env)
|
15
34
|
end
|
@@ -9,7 +9,7 @@ module Tugboat
|
|
9
9
|
|
10
10
|
if droplet_list.empty?
|
11
11
|
say "You don't appear to have any droplets.", :red
|
12
|
-
say "Try creating one with #{GREEN}\`tugboat create
|
12
|
+
say "Try creating one with #{GREEN}\`tugboat create\`#{CLEAR}"
|
13
13
|
else
|
14
14
|
droplet_list.each do |droplet|
|
15
15
|
|
data/lib/tugboat/version.rb
CHANGED
@@ -3,10 +3,12 @@ require 'spec_helper'
|
|
3
3
|
describe Tugboat::CLI do
|
4
4
|
include_context "spec"
|
5
5
|
|
6
|
+
let(:tmp_path) { project_path + "/tmp/tugboat" }
|
7
|
+
|
6
8
|
describe "authorize" do
|
7
9
|
before do
|
8
10
|
stub_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}").
|
9
|
-
|
11
|
+
to_return(:status => 200)
|
10
12
|
end
|
11
13
|
|
12
14
|
it "asks the right questions and checks credentials" do
|
@@ -22,10 +24,51 @@ describe Tugboat::CLI do
|
|
22
24
|
$stdin.should_receive(:gets).and_return(ssh_user)
|
23
25
|
$stdout.should_receive(:print).with("Enter your SSH port number (optional, defaults to 22): ")
|
24
26
|
$stdin.should_receive(:gets).and_return(ssh_port)
|
27
|
+
$stdout.should_receive(:print).with("Enter your default region ID (optional, defaults to 1 (New York)): ")
|
28
|
+
$stdin.should_receive(:gets).and_return(region)
|
29
|
+
$stdout.should_receive(:print).with("Enter your default image ID (optional, defaults to 284203 (Ubuntu 12.04 x64)): ")
|
30
|
+
$stdin.should_receive(:gets).and_return(image)
|
31
|
+
$stdout.should_receive(:print).with("Enter your default size ID (optional, defaults to 66 (512MB)): ")
|
32
|
+
$stdin.should_receive(:gets).and_return(size)
|
33
|
+
$stdout.should_receive(:print).with("Enter your default ssh key ID (optional, defaults to none): ")
|
34
|
+
$stdin.should_receive(:gets).and_return(ssh_key_id)
|
25
35
|
|
26
36
|
@cli.authorize
|
27
37
|
|
28
38
|
expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
|
39
|
+
|
40
|
+
File.read(tmp_path).should include "image: '#{image}'", "region: '#{region}'", "size: '#{size}'", "ssh_user: #{ssh_user}", "ssh_key_path: #{ssh_key_path}", "ssh_port: '#{ssh_port}'", "ssh_key: '#{ssh_key_id}'"
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sets defaults if no input given" do
|
45
|
+
|
46
|
+
$stdout.should_receive(:print).exactly(6).times
|
47
|
+
$stdout.should_receive(:print).with("Enter your client key: ")
|
48
|
+
$stdin.should_receive(:gets).and_return(client_key)
|
49
|
+
$stdout.should_receive(:print).with("Enter your API key: ")
|
50
|
+
$stdin.should_receive(:gets).and_return(api_key)
|
51
|
+
$stdout.should_receive(:print).with("Enter your SSH key path (optional, defaults to ~/.ssh/id_rsa): ")
|
52
|
+
$stdin.should_receive(:gets).and_return(ssh_key_path)
|
53
|
+
$stdout.should_receive(:print).with("Enter your SSH user (optional, defaults to #{ENV['USER']}): ")
|
54
|
+
$stdin.should_receive(:gets).and_return('')
|
55
|
+
$stdout.should_receive(:print).with("Enter your SSH port number (optional, defaults to 22): ")
|
56
|
+
$stdin.should_receive(:gets).and_return('')
|
57
|
+
$stdout.should_receive(:print).with("Enter your default region ID (optional, defaults to 1 (New York)): ")
|
58
|
+
$stdin.should_receive(:gets).and_return('')
|
59
|
+
$stdout.should_receive(:print).with("Enter your default image ID (optional, defaults to 284203 (Ubuntu 12.04 x64)): ")
|
60
|
+
$stdin.should_receive(:gets).and_return('')
|
61
|
+
$stdout.should_receive(:print).with("Enter your default size ID (optional, defaults to 66 (512MB)): ")
|
62
|
+
$stdin.should_receive(:gets).and_return('')
|
63
|
+
$stdout.should_receive(:print).with("Enter your default ssh key ID (optional, defaults to none): ")
|
64
|
+
$stdin.should_receive(:gets).and_return('')
|
65
|
+
|
66
|
+
@cli.authorize
|
67
|
+
|
68
|
+
expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
|
69
|
+
|
70
|
+
File.read(tmp_path).should include "image: '284203'", "region: '1'", "size: '66'", "ssh_user: #{ENV['USER']}", "ssh_key_path: ~/.ssh/id_rsa", "ssh_port: '22'", "ssh_key: ''"
|
71
|
+
|
29
72
|
end
|
30
73
|
end
|
31
74
|
|
data/spec/cli/create_cli_spec.rb
CHANGED
@@ -4,8 +4,8 @@ describe Tugboat::CLI do
|
|
4
4
|
include_context "spec"
|
5
5
|
|
6
6
|
describe "create a droplet" do
|
7
|
-
it "with a name" do
|
8
|
-
stub_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id&name=#{droplet_name}®ion_id&size_id&ssh_key_ids").
|
7
|
+
it "with a name, uses defaults from configuration" do
|
8
|
+
stub_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=#{image}&name=#{droplet_name}®ion_id=#{region}&size_id=#{size}&ssh_key_ids=#{ssh_key_id}").
|
9
9
|
to_return(:status => 200, :body => '{"status":"OK"}')
|
10
10
|
|
11
11
|
@cli.create(droplet_name)
|
@@ -13,21 +13,21 @@ describe Tugboat::CLI do
|
|
13
13
|
expect($stdout.string).to eq <<-eos
|
14
14
|
Queueing creation of droplet '#{droplet_name}'...done
|
15
15
|
eos
|
16
|
-
expect(a_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id&name=#{droplet_name}®ion_id&size_id&ssh_key_ids")).to have_been_made
|
16
|
+
expect(a_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=#{image}&name=#{droplet_name}®ion_id=#{region}&size_id=#{size}&ssh_key_ids=#{ssh_key_id}")).to have_been_made
|
17
17
|
end
|
18
18
|
|
19
|
-
it "with args" do
|
20
|
-
stub_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=
|
19
|
+
it "with args does not use defaults from configuration" do
|
20
|
+
stub_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=555&name=foo®ion_id=3&size_id=666&ssh_key_ids=4321").
|
21
21
|
to_return(:status => 200, :body => '{"status":"OK"}')
|
22
22
|
|
23
|
-
@cli.options = @cli.options.merge(:image =>
|
23
|
+
@cli.options = @cli.options.merge(:image => '555', :size => '666', :region => '3', :keys => '4321')
|
24
24
|
@cli.create(droplet_name)
|
25
25
|
|
26
26
|
expect($stdout.string).to eq <<-eos
|
27
27
|
Queueing creation of droplet '#{droplet_name}'...done
|
28
28
|
eos
|
29
29
|
|
30
|
-
expect(a_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=
|
30
|
+
expect(a_request(:get, "https://api.digitalocean.com/droplets/new?api_key=#{api_key}&client_id=#{client_key}&image_id=555&name=foo®ion_id=3&size_id=666&ssh_key_ids=4321")).to have_been_made
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -27,7 +27,7 @@ foo (ip: 33.33.33.10, status: \e[32mactive\e[0m, region: 1, id: 100823)
|
|
27
27
|
|
28
28
|
expect($stdout.string).to eq <<-eos
|
29
29
|
You don't appear to have any droplets.
|
30
|
-
Try creating one with \e[32m`tugboat create
|
30
|
+
Try creating one with \e[32m`tugboat create`\e[0m
|
31
31
|
eos
|
32
32
|
|
33
33
|
expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tugboat::CLI do
|
4
|
+
include_context "spec"
|
5
|
+
|
6
|
+
describe "verify" do
|
7
|
+
it "returns confirmation text when verify passes" do
|
8
|
+
stub_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}").
|
9
|
+
to_return(:status => 200)
|
10
|
+
@cli.verify
|
11
|
+
expect($stdout.string).to eq "Authentication with DigitalOcean was successful.\n"
|
12
|
+
expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns error string when verify fails" do
|
16
|
+
stub_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}").
|
17
|
+
to_return(:status => 401, :body => '{"status":"ERROR", "error_message":"Access Denied"}')
|
18
|
+
expect { @cli.verify }.to raise_error(SystemExit)
|
19
|
+
expect($stdout.string).to eq "\e[31mthe server responded with status 401!\e[0m\n\n\e[31mAccess Denied\e[0m\n\nDouble-check your parameters and configuration (in your ~/.tugboat file)\n"
|
20
|
+
expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
data/spec/config_spec.rb
CHANGED
@@ -29,12 +29,16 @@ describe Tugboat::Configuration do
|
|
29
29
|
let(:ssh_key_path) { "~/.ssh/id_rsa2" }
|
30
30
|
let(:ssh_key_path) { "~/.ssh/id_rsa2.pub" }
|
31
31
|
let(:ssh_port) { "22" }
|
32
|
+
let(:region) { "2" }
|
33
|
+
let(:image) { "345791" }
|
34
|
+
let(:size) { "66" }
|
35
|
+
let(:ssh_key_id) { '1234' }
|
32
36
|
|
33
37
|
let(:config) { config = Tugboat::Configuration.instance }
|
34
38
|
|
35
39
|
before :each do
|
36
40
|
# Create a temporary file
|
37
|
-
config.create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port)
|
41
|
+
config.create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port, region, image, size, ssh_key_id)
|
38
42
|
end
|
39
43
|
|
40
44
|
it "can be created" do
|
@@ -47,39 +51,89 @@ describe Tugboat::Configuration do
|
|
47
51
|
end
|
48
52
|
|
49
53
|
describe "the file format"
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
54
|
+
let(:data) { YAML.load_file(tmp_path) }
|
55
|
+
|
56
|
+
it "should have authentication at the top level" do
|
57
|
+
expect(data).to have_key("authentication")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should have ssh at the top level" do
|
61
|
+
expect(data).to have_key("ssh")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should have a client key" do
|
65
|
+
auth = data["authentication"]
|
66
|
+
expect(auth).to have_key("client_key")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should have an api key" do
|
70
|
+
auth = data["authentication"]
|
71
|
+
expect(auth).to have_key("api_key")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have an ssh key path" do
|
75
|
+
ssh = data["ssh"]
|
76
|
+
expect(ssh).to have_key("ssh_key_path")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should have an ssh user" do
|
80
|
+
ssh = data["ssh"]
|
81
|
+
expect(ssh).to have_key("ssh_user")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should have an ssh port" do
|
85
|
+
ssh = data["ssh"]
|
86
|
+
expect(ssh).to have_key("ssh_port")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
describe "backwards compatible" do
|
90
|
+
let(:client_key) { "foo" }
|
91
|
+
let(:api_key) { "bar" }
|
92
|
+
let(:ssh_user) { "baz" }
|
93
|
+
let(:ssh_key_path) { "~/.ssh/id_rsa2" }
|
94
|
+
let(:ssh_key_path) { "~/.ssh/id_rsa2.pub" }
|
95
|
+
let(:ssh_port) { "22" }
|
96
|
+
|
97
|
+
let(:config) { config = Tugboat::Configuration.instance }
|
98
|
+
let(:config_default_region) { Tugboat::Configuration::DEFAULT_REGION }
|
99
|
+
let(:config_default_image) { Tugboat::Configuration::DEFAULT_IMAGE }
|
100
|
+
let(:config_default_size) { Tugboat::Configuration::DEFAULT_SIZE }
|
101
|
+
let(:config_default_ssh_key) { Tugboat::Configuration::DEFAULT_SSH_KEY }
|
102
|
+
let(:backwards_config) {
|
103
|
+
{
|
104
|
+
"authentication" => { "client_key" => client_key, "api_key" => api_key },
|
105
|
+
"ssh" => { "ssh_user" => ssh_user, "ssh_key_path" => ssh_key_path , "ssh_port" => ssh_port},
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
before :each do
|
110
|
+
config.instance_variable_set(:@data, backwards_config)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should load a backwards compatible config file" do
|
114
|
+
data_file = config.instance_variable_get(:@data)
|
115
|
+
expect(data_file).to eql backwards_config
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should use default region if not in configuration" do
|
119
|
+
region = config.default_region
|
120
|
+
expect(region).to eql config_default_region
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should use default image if not in configuration" do
|
124
|
+
image = config.default_image
|
125
|
+
expect(image).to eql config_default_image
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should use default size if not in configuration" do
|
129
|
+
size = config.default_size
|
130
|
+
expect(size).to eql config_default_size
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should use default ssh key if not in configuration" do
|
134
|
+
ssh_key = config.default_ssh_key
|
135
|
+
expect(ssh_key).to eql config_default_ssh_key
|
136
|
+
end
|
137
|
+
|
84
138
|
end
|
85
139
|
end
|
data/spec/shared/environment.rb
CHANGED
@@ -6,11 +6,15 @@ shared_context "spec" do
|
|
6
6
|
let(:client_key) { "foo" }
|
7
7
|
let(:api_key) { "bar" }
|
8
8
|
let(:ssh_user) { "baz" }
|
9
|
-
let(:ssh_port) { "
|
9
|
+
let(:ssh_port) { "33" }
|
10
10
|
let(:ssh_key_path) { "~/.ssh/id_rsa2" }
|
11
11
|
let(:droplet_name) { "foo" }
|
12
12
|
let(:droplet_ip) { "33.33.33.10" }
|
13
13
|
let(:droplet_id) { 1234 }
|
14
|
+
let(:region) { '3' }
|
15
|
+
let(:image) { '345791'}
|
16
|
+
let(:size) { '67'}
|
17
|
+
let(:ssh_key_id) { '1234' }
|
14
18
|
let(:ocean) { DigitalOcean::API.new :client_id => client_key, :api_key =>api_key }
|
15
19
|
let(:app) { lambda { |env| } }
|
16
20
|
let(:env) { {} }
|
@@ -22,7 +26,7 @@ shared_context "spec" do
|
|
22
26
|
@cli = Tugboat::CLI.new
|
23
27
|
|
24
28
|
# Set a temprary project path and create fake config.
|
25
|
-
config.create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port)
|
29
|
+
config.create_config_file(client_key, api_key, ssh_key_path, ssh_user, ssh_port, region, image, size, ssh_key_id)
|
26
30
|
config.reload!
|
27
31
|
|
28
32
|
# Keep track of the old stderr / out
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tugboat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.8
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jack Pearkes
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-09-07 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: thor
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: digital_ocean
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: middleware
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,23 +55,20 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rake
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rspec-core
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - ~>
|
84
74
|
- !ruby/object:Gem::Version
|
@@ -86,7 +76,6 @@ dependencies:
|
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - ~>
|
92
81
|
- !ruby/object:Gem::Version
|
@@ -94,7 +83,6 @@ dependencies:
|
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: rspec-expectations
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
87
|
- - ~>
|
100
88
|
- !ruby/object:Gem::Version
|
@@ -102,7 +90,6 @@ dependencies:
|
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
94
|
- - ~>
|
108
95
|
- !ruby/object:Gem::Version
|
@@ -110,7 +97,6 @@ dependencies:
|
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: rspec-mocks
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ~>
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ~>
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -126,7 +111,6 @@ dependencies:
|
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: webmock
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
115
|
- - ~>
|
132
116
|
- !ruby/object:Gem::Version
|
@@ -134,7 +118,6 @@ dependencies:
|
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
122
|
- - ~>
|
140
123
|
- !ruby/object:Gem::Version
|
@@ -142,7 +125,6 @@ dependencies:
|
|
142
125
|
- !ruby/object:Gem::Dependency
|
143
126
|
name: coveralls
|
144
127
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
128
|
requirements:
|
147
129
|
- - ~>
|
148
130
|
- !ruby/object:Gem::Version
|
@@ -150,7 +132,6 @@ dependencies:
|
|
150
132
|
type: :development
|
151
133
|
prerelease: false
|
152
134
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
135
|
requirements:
|
155
136
|
- - ~>
|
156
137
|
- !ruby/object:Gem::Version
|
@@ -177,6 +158,7 @@ files:
|
|
177
158
|
- lib/tugboat/config.rb
|
178
159
|
- lib/tugboat/middleware.rb
|
179
160
|
- lib/tugboat/middleware/ask_for_credentials.rb
|
161
|
+
- lib/tugboat/middleware/authentication_middleware.rb
|
180
162
|
- lib/tugboat/middleware/base.rb
|
181
163
|
- lib/tugboat/middleware/check_configuration.rb
|
182
164
|
- lib/tugboat/middleware/check_credentials.rb
|
@@ -184,6 +166,7 @@ files:
|
|
184
166
|
- lib/tugboat/middleware/check_droplet_inactive.rb
|
185
167
|
- lib/tugboat/middleware/confirm_action.rb
|
186
168
|
- lib/tugboat/middleware/create_droplet.rb
|
169
|
+
- lib/tugboat/middleware/custom_logger.rb
|
187
170
|
- lib/tugboat/middleware/destroy_droplet.rb
|
188
171
|
- lib/tugboat/middleware/find_droplet.rb
|
189
172
|
- lib/tugboat/middleware/halt_droplet.rb
|
@@ -220,6 +203,7 @@ files:
|
|
220
203
|
- spec/cli/snapshot_cli_spec.rb
|
221
204
|
- spec/cli/ssh_cli_spec.rb
|
222
205
|
- spec/cli/start_cli_spec.rb
|
206
|
+
- spec/cli/verify_cli_spec.rb
|
223
207
|
- spec/cli/version_cli_spec.rb
|
224
208
|
- spec/cli/wait_cli_spec.rb
|
225
209
|
- spec/config_spec.rb
|
@@ -249,27 +233,26 @@ files:
|
|
249
233
|
- tugboat.gemspec
|
250
234
|
homepage: https://github.com/pearkes/tugboat
|
251
235
|
licenses: []
|
236
|
+
metadata: {}
|
252
237
|
post_install_message:
|
253
238
|
rdoc_options: []
|
254
239
|
require_paths:
|
255
240
|
- lib
|
256
241
|
required_ruby_version: !ruby/object:Gem::Requirement
|
257
|
-
none: false
|
258
242
|
requirements:
|
259
|
-
- -
|
243
|
+
- - '>='
|
260
244
|
- !ruby/object:Gem::Version
|
261
245
|
version: '0'
|
262
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
263
|
-
none: false
|
264
247
|
requirements:
|
265
|
-
- -
|
248
|
+
- - '>='
|
266
249
|
- !ruby/object:Gem::Version
|
267
250
|
version: '0'
|
268
251
|
requirements: []
|
269
252
|
rubyforge_project:
|
270
|
-
rubygems_version:
|
253
|
+
rubygems_version: 2.0.3
|
271
254
|
signing_key:
|
272
|
-
specification_version:
|
255
|
+
specification_version: 4
|
273
256
|
summary: A command line tool for interacting with your DigitalOcean droplets.
|
274
257
|
test_files:
|
275
258
|
- spec/cli/authorize_cli_spec.rb
|
@@ -289,6 +272,7 @@ test_files:
|
|
289
272
|
- spec/cli/snapshot_cli_spec.rb
|
290
273
|
- spec/cli/ssh_cli_spec.rb
|
291
274
|
- spec/cli/start_cli_spec.rb
|
275
|
+
- spec/cli/verify_cli_spec.rb
|
292
276
|
- spec/cli/version_cli_spec.rb
|
293
277
|
- spec/cli/wait_cli_spec.rb
|
294
278
|
- spec/config_spec.rb
|
@@ -314,3 +298,4 @@ test_files:
|
|
314
298
|
- spec/middleware/ssh_droplet_spec.rb
|
315
299
|
- spec/shared/environment.rb
|
316
300
|
- spec/spec_helper.rb
|
301
|
+
has_rdoc:
|