tugboat 0.0.7 → 0.0.8
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 +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:
|