turbot 0.0.2

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.
Files changed (71) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +36 -0
  3. data/bin/turbot +17 -0
  4. data/data/cacert.pem +3988 -0
  5. data/lib/turbot/auth.rb +315 -0
  6. data/lib/turbot/cli.rb +38 -0
  7. data/lib/turbot/client/cisaurus.rb +25 -0
  8. data/lib/turbot/client/pgbackups.rb +113 -0
  9. data/lib/turbot/client/rendezvous.rb +111 -0
  10. data/lib/turbot/client/ssl_endpoint.rb +25 -0
  11. data/lib/turbot/client/turbot_postgresql.rb +148 -0
  12. data/lib/turbot/client.rb +757 -0
  13. data/lib/turbot/command/auth.rb +85 -0
  14. data/lib/turbot/command/base.rb +192 -0
  15. data/lib/turbot/command/bots.rb +326 -0
  16. data/lib/turbot/command/config.rb +123 -0
  17. data/lib/turbot/command/help.rb +179 -0
  18. data/lib/turbot/command/keys.rb +115 -0
  19. data/lib/turbot/command/logs.rb +34 -0
  20. data/lib/turbot/command/ssl.rb +43 -0
  21. data/lib/turbot/command/status.rb +51 -0
  22. data/lib/turbot/command/update.rb +47 -0
  23. data/lib/turbot/command/version.rb +23 -0
  24. data/lib/turbot/command.rb +304 -0
  25. data/lib/turbot/deprecated/help.rb +38 -0
  26. data/lib/turbot/deprecated.rb +5 -0
  27. data/lib/turbot/distribution.rb +9 -0
  28. data/lib/turbot/errors.rb +28 -0
  29. data/lib/turbot/excon.rb +11 -0
  30. data/lib/turbot/helpers/log_displayer.rb +70 -0
  31. data/lib/turbot/helpers/pg_dump_restore.rb +115 -0
  32. data/lib/turbot/helpers/turbot_postgresql.rb +213 -0
  33. data/lib/turbot/helpers.rb +521 -0
  34. data/lib/turbot/plugin.rb +165 -0
  35. data/lib/turbot/updater.rb +171 -0
  36. data/lib/turbot/version.rb +3 -0
  37. data/lib/turbot.rb +19 -0
  38. data/lib/vendor/turbot/okjson.rb +598 -0
  39. data/spec/helper/legacy_help.rb +16 -0
  40. data/spec/helper/pg_dump_restore_spec.rb +67 -0
  41. data/spec/schemas/dummy_schema.json +12 -0
  42. data/spec/spec.opts +1 -0
  43. data/spec/spec_helper.rb +220 -0
  44. data/spec/support/display_message_matcher.rb +49 -0
  45. data/spec/support/dummy_api.rb +120 -0
  46. data/spec/support/openssl_mock_helper.rb +8 -0
  47. data/spec/support/organizations_mock_helper.rb +11 -0
  48. data/spec/turbot/auth_spec.rb +214 -0
  49. data/spec/turbot/client/pgbackups_spec.rb +43 -0
  50. data/spec/turbot/client/rendezvous_spec.rb +62 -0
  51. data/spec/turbot/client/ssl_endpoint_spec.rb +48 -0
  52. data/spec/turbot/client/turbot_postgresql_spec.rb +71 -0
  53. data/spec/turbot/client_spec.rb +548 -0
  54. data/spec/turbot/command/auth_spec.rb +38 -0
  55. data/spec/turbot/command/base_spec.rb +66 -0
  56. data/spec/turbot/command/bots_spec.rb +54 -0
  57. data/spec/turbot/command/config_spec.rb +143 -0
  58. data/spec/turbot/command/help_spec.rb +90 -0
  59. data/spec/turbot/command/keys_spec.rb +117 -0
  60. data/spec/turbot/command/logs_spec.rb +60 -0
  61. data/spec/turbot/command/status_spec.rb +48 -0
  62. data/spec/turbot/command/version_spec.rb +16 -0
  63. data/spec/turbot/command_spec.rb +131 -0
  64. data/spec/turbot/helpers/turbot_postgresql_spec.rb +181 -0
  65. data/spec/turbot/helpers_spec.rb +48 -0
  66. data/spec/turbot/plugin_spec.rb +172 -0
  67. data/spec/turbot/updater_spec.rb +44 -0
  68. data/templates/manifest.json +7 -0
  69. data/templates/scraper.py +5 -0
  70. data/templates/scraper.rb +6 -0
  71. metadata +199 -0
@@ -0,0 +1,220 @@
1
+ $stdin = File.new("/dev/null")
2
+
3
+ require "rubygems"
4
+
5
+ require "excon"
6
+ Excon.defaults[:mock] = true
7
+
8
+ # ensure these are around for errors
9
+ # as their require is generally deferred
10
+ #require "turbot-api"
11
+ require "rest_client"
12
+
13
+ require "turbot/cli"
14
+ require "rspec"
15
+ require "rr"
16
+ require "fakefs/safe"
17
+ require 'tmpdir'
18
+ require "webmock/rspec"
19
+
20
+ include WebMock::API
21
+
22
+ WebMock::HttpLibAdapters::ExconAdapter.disable!
23
+
24
+ def api
25
+ Turbot::API.new(:api_key => "pass", :mock => true)
26
+ end
27
+
28
+ def org_api
29
+ Turbot::Client::Organizations.api(:mock => true)
30
+ end
31
+
32
+ def stub_api_request(method, path)
33
+ stub_request(method, "https://api.turbot.com#{path}")
34
+ end
35
+
36
+ def prepare_command(klass)
37
+ command = klass.new
38
+ command.stub!(:bot).and_return("example")
39
+ command.stub!(:ask).and_return("")
40
+ command.stub!(:display)
41
+ command.stub!(:hputs)
42
+ command.stub!(:hprint)
43
+ command.stub!(:turbot).and_return(mock('turbot client', :host => 'turbot.com'))
44
+ command
45
+ end
46
+
47
+ def execute(command_line)
48
+ extend RR::Adapters::RRMethods
49
+
50
+ args = command_line.split(" ")
51
+ command = args.shift
52
+
53
+ Turbot::Command.load
54
+ object, method = Turbot::Command.prepare_run(command, args)
55
+
56
+ any_instance_of(Turbot::Command::Base) do |base|
57
+ stub(base).bot.returns("example")
58
+ end
59
+
60
+ stub(Turbot::Auth).get_credentials.returns(['email@example.com', 'apikey01'])
61
+ stub(Turbot::Auth).api_key.returns('apikey01')
62
+
63
+ original_stdin, original_stderr, original_stdout = $stdin, $stderr, $stdout
64
+
65
+ $stdin = captured_stdin = StringIO.new
66
+ $stderr = captured_stderr = StringIO.new
67
+ $stdout = captured_stdout = StringIO.new
68
+ class << captured_stdout
69
+ def tty?
70
+ true
71
+ end
72
+ end
73
+
74
+ begin
75
+ object.send(method)
76
+ rescue SystemExit
77
+ ensure
78
+ $stdin, $stderr, $stdout = original_stdin, original_stderr, original_stdout
79
+ Turbot::Command.current_command = nil
80
+ end
81
+
82
+ [captured_stderr.string, captured_stdout.string]
83
+ end
84
+
85
+ def any_instance_of(klass, &block)
86
+ extend RR::Adapters::RRMethods
87
+ any_instance_of(klass, &block)
88
+ end
89
+
90
+ def run(command_line)
91
+ capture_stdout do
92
+ begin
93
+ Turbot::CLI.start(*command_line.split(" "))
94
+ rescue SystemExit
95
+ end
96
+ end
97
+ end
98
+
99
+ alias turbot run
100
+
101
+ def capture_stderr(&block)
102
+ original_stderr = $stderr
103
+ $stderr = captured_stderr = StringIO.new
104
+ begin
105
+ yield
106
+ ensure
107
+ $stderr = original_stderr
108
+ end
109
+ captured_stderr.string
110
+ end
111
+
112
+ def capture_stdout(&block)
113
+ original_stdout = $stdout
114
+ $stdout = captured_stdout = StringIO.new
115
+ begin
116
+ yield
117
+ ensure
118
+ $stdout = original_stdout
119
+ end
120
+ captured_stdout.string
121
+ end
122
+
123
+ def fail_command(message)
124
+ raise_error(Turbot::Command::CommandFailed, message)
125
+ end
126
+
127
+ def stub_core
128
+ @stubbed_core ||= begin
129
+ stubbed_core = nil
130
+ any_instance_of(Turbot::Client) do |core|
131
+ stubbed_core = stub(core)
132
+ end
133
+ stub(Turbot::Auth).user.returns("email@example.com")
134
+ stub(Turbot::Auth).password.returns("pass")
135
+ stub(Turbot::Client).auth.returns("apikey01")
136
+ stubbed_core
137
+ end
138
+ end
139
+
140
+ def stub_pg
141
+ @stubbed_pg ||= begin
142
+ stubbed_pg = nil
143
+ any_instance_of(Turbot::Client::TurbotPostgresql) do |pg|
144
+ stubbed_pg = stub(pg)
145
+ end
146
+ stubbed_pg
147
+ end
148
+ end
149
+
150
+ def stub_pgbackups
151
+ @stubbed_pgbackups ||= begin
152
+ stubbed_pgbackups = nil
153
+ any_instance_of(Turbot::Client::Pgbackups) do |pgbackups|
154
+ stubbed_pgbackups = stub(pgbackups)
155
+ end
156
+ stubbed_pgbackups
157
+ end
158
+ end
159
+
160
+ def stub_rendezvous
161
+ @stubbed_rendezvous ||= begin
162
+ stubbed_rendezvous = nil
163
+ any_instance_of(Turbot::Client::Rendezvous) do |rendezvous|
164
+ stubbed_rendezvous = stub(rendezvous)
165
+ end
166
+ stubbed_rendezvous
167
+ end
168
+ end
169
+
170
+ def stub_cisaurus
171
+ @stub_cisaurus ||= begin
172
+ stub_cisaurus = nil
173
+ any_instance_of(Turbot::Client::Cisaurus) do |cisaurus|
174
+ stub_cisaurus = stub(cisaurus)
175
+ end
176
+ stub_cisaurus
177
+ end
178
+ end
179
+
180
+ def with_blank_git_repository(&block)
181
+ sandbox = File.join(Dir.tmpdir, "turbot", Process.pid.to_s)
182
+ FileUtils.mkdir_p(sandbox)
183
+
184
+ old_dir = Dir.pwd
185
+ Dir.chdir(sandbox)
186
+
187
+ `git init`
188
+ block.call
189
+
190
+ FileUtils.rm_rf(sandbox)
191
+ ensure
192
+ Dir.chdir(old_dir)
193
+ end
194
+
195
+ module SandboxHelper
196
+ def bash(cmd)
197
+ `#{cmd}`
198
+ end
199
+ end
200
+
201
+ require "turbot/helpers"
202
+ module Turbot::Helpers
203
+ @home_directory = Dir.mktmpdir
204
+ undef_method :home_directory
205
+ def home_directory
206
+ @home_directory
207
+ end
208
+ end
209
+
210
+ require "support/display_message_matcher"
211
+ require "support/organizations_mock_helper"
212
+ require "support/dummy_api"
213
+
214
+ RSpec.configure do |config|
215
+ config.color_enabled = true
216
+ config.include DisplayMessageMatcher
217
+ config.order = 'rand'
218
+ config.before { Turbot::Helpers.error_with_failure = false }
219
+ config.after { RR.reset }
220
+ end
@@ -0,0 +1,49 @@
1
+ module DisplayMessageMatcher
2
+
3
+ def display_message(command, message)
4
+ DisplayMessageMatcher::DisplayMessage.new command, message
5
+ end
6
+
7
+ class DisplayMessage
8
+ def initialize(command, message)
9
+ @command = command
10
+ @message = message
11
+ end
12
+
13
+ def matches?(given_proc)
14
+ displayed_expected_message = false
15
+ @given_messages = []
16
+
17
+ @command.should_receive(:display).
18
+ any_number_of_times do |message, newline|
19
+ @given_messages << message
20
+ displayed_expected_message = displayed_expected_message ||
21
+ message == @message
22
+ end
23
+
24
+ given_proc.call
25
+
26
+ displayed_expected_message
27
+ end
28
+
29
+ def failure_message
30
+ "expected #{ @command } to display the message #{ @message.inspect } but #{ given_messages }"
31
+ end
32
+
33
+ def negative_failure_message
34
+ "expected #{ @command } to not display the message #{ @message.inspect } but it was displayed"
35
+ end
36
+
37
+ private
38
+
39
+ def given_messages
40
+ if @given_messages.empty?
41
+ 'no messages were displayed'
42
+ else
43
+ formatted_given_messages = @given_messages.map(&:inspect).join ', '
44
+ "the follow messages were displayed: #{ formatted_given_messages }"
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,120 @@
1
+ require 'json'
2
+
3
+ module Turbot
4
+ class API
5
+ def initialize(params)
6
+ @headers = params[:headers]
7
+ @host = params[:host]
8
+ @port = params[:port]
9
+ @username = params[:username]
10
+ @password = params[:password]
11
+ @scheme = params[:scheme]
12
+ @ssl_verify_peer = params[:ssl_verify_peer]
13
+ @api_key = params[:api_key] || get_api_key(@username, @password)
14
+ authenticate
15
+
16
+ end
17
+
18
+ def authenticate
19
+ # Try to authenticate at this stage - something like
20
+ #user_pass = ":#{@api_key}"
21
+ #options[:headers] = HEADERS.merge({
22
+ # 'Authorization' => "Basic #{Base64.encode64(user_pass).gsub("\n", '')}",
23
+ # }).merge(options[:headers])
24
+
25
+ # @connection = Excon.new("http://missions.opencorporates.com/login", options)
26
+
27
+ end
28
+
29
+ def get_user
30
+ # raise if not authenticated
31
+ # @connection.code < 400
32
+ end
33
+
34
+ def get_api_key(user, password)
35
+ # get the api key, raise exception if credentials broken
36
+ # this is a hash of the username and password plus salt
37
+ return "some-api-key"
38
+ end
39
+
40
+ def get_keys
41
+ # return an array of ssh keys
42
+ read_db("keys")
43
+ end
44
+
45
+ def post_key(key)
46
+ # receive ssh key and associate with account
47
+ append_db("keys", {"contents" => key})
48
+ end
49
+
50
+ def delete_key(key)
51
+ keys = read_db("keys")
52
+ keys.delete(key)
53
+ write_db("keys", keys)
54
+ end
55
+
56
+ def delete_keys
57
+ write_db("keys", [])
58
+ end
59
+
60
+ def post_bot(data)
61
+ # XXX need to implement this to make the config command pass...
62
+ # save an "bot" - we'll replace this with the bot stuff chris did
63
+ db = read_db("bot")
64
+ db[data["name"]] = data
65
+ write_db("bot", db)
66
+ end
67
+
68
+ def delete_bot(bot)
69
+ db = read_db("bot")
70
+ db.delete(bot)
71
+ write_db("bot", db)
72
+ end
73
+
74
+ def get_bots
75
+ read_db("bot", [])
76
+ end
77
+
78
+ def get_bot(bot)
79
+ db = read_db("bot_data", [])
80
+ db[bot]
81
+ end
82
+
83
+ def put_config_vars(bot, vars)
84
+ # Set vars for bot specified
85
+ config = read_db("config")
86
+ config[bot] = vars
87
+ write_db("config", config)
88
+ end
89
+
90
+ def get_config_vars(bot)
91
+ read_db("config", [])[bot]
92
+ end
93
+
94
+ def delete_config_var(bot, key)
95
+ db = read_db("config", [])
96
+ keys = db[bot]
97
+ keys.delete(key)
98
+ db[bot] = keys
99
+ write_db("config", db)
100
+ end
101
+
102
+ private
103
+
104
+ def write_db(name, data)
105
+ open("/tmp/#{name}", "w") do |f|
106
+ f.write(JSON.dump(data))
107
+ end
108
+ end
109
+
110
+ def read_db(name, default={})
111
+ JSON.parse(open("/tmp/#{name}", "r").read) rescue {}
112
+ end
113
+
114
+ def append_db(name, data)
115
+ db = read_db(name, [])
116
+ db << data
117
+ write_db(name, db)
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,8 @@
1
+ def mock_openssl
2
+ @ctx_mock = mock "SSLContext", :key= => nil, :cert= => nil, :ssl_version= => nil
3
+ @tcp_socket_mock = mock "TCPSocket", :close => true
4
+ @ssl_socket_mock = mock "SSLSocket", :sync= => true, :connect => true, :close => true, :to_io => $stdin
5
+
6
+ OpenSSL::SSL::SSLSocket.stub(:new).and_return(@ssl_socket_mock)
7
+ OpenSSL::SSL::SSLContext.stub(:new).and_return(@ctx_mock)
8
+ end
@@ -0,0 +1,11 @@
1
+ class Turbot::Client::Organizations
2
+
3
+ # stub GET /v1/user/info
4
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/v1/user/info$} ) do |params|
5
+ {
6
+ :body => "",
7
+ :status => 404
8
+ }
9
+ end
10
+
11
+ end
@@ -0,0 +1,214 @@
1
+ require "spec_helper"
2
+ require "turbot/auth"
3
+ require "turbot/helpers"
4
+
5
+ module Turbot
6
+ describe Auth do
7
+ include Turbot::Helpers
8
+
9
+ before do
10
+ ENV['TURBOT_API_KEY'] = nil
11
+
12
+ @cli = Turbot::Auth
13
+ @cli.stub!(:check)
14
+ @cli.stub!(:display)
15
+ @cli.stub!(:running_on_a_mac?).and_return(false)
16
+ @cli.credentials = nil
17
+
18
+ FakeFS.activate!
19
+
20
+ FakeFS::File.stub!(:stat).and_return(double('stat', :mode => "0600".to_i(8)))
21
+ FakeFS::FileUtils.stub!(:chmod)
22
+ FakeFS::File.stub!(:readlines) do |path|
23
+ File.read(path).split("\n").map {|line| "#{line}\n"}
24
+ end
25
+
26
+ FileUtils.mkdir_p(@cli.netrc_path.split("/")[0..-2].join("/"))
27
+
28
+ File.open(@cli.netrc_path, "w") do |file|
29
+ file.puts("machine api.turbot.com\n login user\n password pass\n")
30
+ file.puts("machine code.turbot.com\n login user\n password pass\n")
31
+ end
32
+ end
33
+
34
+ after do
35
+ FileUtils.rm_rf(@cli.netrc_path)
36
+ FakeFS.deactivate!
37
+ end
38
+
39
+
40
+ context "API key is set via environment variable" do
41
+ before do
42
+ ENV['TURBOT_API_KEY'] = "secret"
43
+ end
44
+
45
+ it "gets credentials from environment variables in preference to credentials file" do
46
+ @cli.read_credentials.should == ['', ENV['TURBOT_API_KEY']]
47
+ end
48
+
49
+ it "returns a blank username" do
50
+ @cli.user.should be_empty
51
+ end
52
+
53
+ it "returns the api key as the password" do
54
+ @cli.password.should == ENV['TURBOT_API_KEY']
55
+ end
56
+
57
+ it "does not overwrite credentials file with environment variable credentials" do
58
+ @cli.should_not_receive(:write_credentials)
59
+ @cli.read_credentials
60
+ end
61
+
62
+ context "reauthenticating" do
63
+ before do
64
+ @cli.stub!(:ask_for_credentials).and_return(['new_user', 'new_password'])
65
+ @cli.stub!(:check)
66
+ @cli.should_receive(:check_for_associated_ssh_key)
67
+ @cli.reauthorize
68
+ end
69
+ it "updates saved credentials" do
70
+ Netrc.read(@cli.netrc_path)["api.#{@cli.host}"].should == ['new_user', 'new_password']
71
+ end
72
+ it "returns environment variable credentials" do
73
+ @cli.read_credentials.should == ['', ENV['TURBOT_API_KEY']]
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ describe "#base_host" do
80
+ it "returns the host without the first part" do
81
+ @cli.base_host("http://foo.bar.com").should == "bar.com"
82
+ end
83
+
84
+ it "works with localhost" do
85
+ @cli.base_host("http://localhost:3000").should == "localhost"
86
+ end
87
+ end
88
+
89
+ it "asks for credentials when the file doesn't exist" do
90
+ @cli.delete_credentials
91
+ @cli.should_receive(:ask_for_credentials).and_return(["u", "p"])
92
+ @cli.should_receive(:check_for_associated_ssh_key)
93
+ @cli.user.should == 'u'
94
+ @cli.password.should == 'p'
95
+ end
96
+
97
+ it "writes credentials and uploads authkey when credentials are saved" do
98
+ @cli.stub!(:credentials)
99
+ @cli.stub!(:check)
100
+ @cli.stub!(:ask_for_credentials).and_return("username", "apikey")
101
+ @cli.should_receive(:write_credentials)
102
+ @cli.should_receive(:check_for_associated_ssh_key)
103
+ @cli.ask_for_and_save_credentials
104
+ end
105
+
106
+ it "save_credentials deletes the credentials when the upload authkey is unauthorized" do
107
+ @cli.stub!(:write_credentials)
108
+ @cli.stub!(:retry_login?).and_return(false)
109
+ @cli.stub!(:ask_for_credentials).and_return("username", "apikey")
110
+ @cli.stub!(:check) { raise Turbot::API::Errors::Unauthorized.new("Login Failed", Excon::Response.new) }
111
+ @cli.should_receive(:delete_credentials)
112
+ lambda { @cli.ask_for_and_save_credentials }.should raise_error(SystemExit)
113
+ end
114
+
115
+ it "asks for login again when not authorized, for three times" do
116
+ @cli.stub!(:read_credentials)
117
+ @cli.stub!(:write_credentials)
118
+ @cli.stub!(:delete_credentials)
119
+ @cli.stub!(:ask_for_credentials).and_return("username", "apikey")
120
+ @cli.stub!(:check) { raise Turbot::API::Errors::Unauthorized.new("Login Failed", Excon::Response.new) }
121
+ @cli.should_receive(:ask_for_credentials).exactly(3).times
122
+ lambda { @cli.ask_for_and_save_credentials }.should raise_error(SystemExit)
123
+ end
124
+
125
+ it "writes the login information to the credentials file for the 'turbot login' command" do
126
+ @cli.stub!(:ask_for_credentials).and_return(['one', 'two'])
127
+ @cli.stub!(:check)
128
+ @cli.should_receive(:check_for_associated_ssh_key)
129
+ @cli.reauthorize
130
+ Netrc.read(@cli.netrc_path)["api.#{@cli.host}"].should == (['one', 'two'])
131
+ end
132
+
133
+ it "migrates long api keys to short api keys" do
134
+ @cli.delete_credentials
135
+ api_key = "7e262de8cac430d8a250793ce8d5b334ae56b4ff15767385121145198a2b4d2e195905ef8bf7cfc5"
136
+ @cli.netrc["api.#{@cli.host}"] = ["user", api_key]
137
+
138
+ @cli.get_credentials.should == ["user", api_key[0,40]]
139
+ %w{api code}.each do |section|
140
+ Netrc.read(@cli.netrc_path)["#{section}.#{@cli.host}"].should == ["user", api_key[0,40]]
141
+ end
142
+ end
143
+
144
+ describe "automatic key uploading" do
145
+ before(:each) do
146
+ FileUtils.mkdir_p("#{@cli.home_directory}/.ssh")
147
+ @cli.stub!(:ask_for_credentials).and_return("username", "apikey")
148
+ end
149
+
150
+ describe "an account with existing keys" do
151
+ before :each do
152
+ @api = mock(Object)
153
+ @response = mock(Object)
154
+ @response.should_receive(:body).and_return(['existingkeys'])
155
+ @api.should_receive(:get_ssh_keys).and_return(@response)
156
+ @cli.should_receive(:api).and_return(@api)
157
+ end
158
+
159
+ it "should not do anything if the account already has keys" do
160
+ @cli.should_not_receive(:associate_key)
161
+ @cli.check_for_associated_ssh_key
162
+ end
163
+ end
164
+
165
+ describe "an account with no keys" do
166
+ before :each do
167
+ @api = mock(Object)
168
+ @response = mock(Object)
169
+ @response.should_receive(:body).and_return([])
170
+ @api.should_receive(:get_ssh_keys).and_return(@response)
171
+ @cli.should_receive(:api).and_return(@api)
172
+ end
173
+
174
+ describe "with zero public keys" do
175
+ it "should ask to generate a key" do
176
+ @cli.should_receive(:ask).and_return("y")
177
+ @cli.should_receive(:generate_ssh_key).with("id_rsa")
178
+ @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa.pub")
179
+ @cli.check_for_associated_ssh_key
180
+ end
181
+ end
182
+
183
+ describe "with one public key" do
184
+ before(:each) { FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa.pub") }
185
+ after(:each) { FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa.pub") }
186
+
187
+ it "should upload the key" do
188
+ @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa.pub")
189
+ @cli.check_for_associated_ssh_key
190
+ end
191
+ end
192
+
193
+ describe "with many public keys" do
194
+ before(:each) do
195
+ FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa.pub")
196
+ FileUtils.touch("#{@cli.home_directory}/.ssh/id_rsa2.pub")
197
+ end
198
+
199
+ after(:each) do
200
+ FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa.pub")
201
+ FileUtils.rm("#{@cli.home_directory}/.ssh/id_rsa2.pub")
202
+ end
203
+
204
+ it "should ask which key to upload" do
205
+ File.open("#{@cli.home_directory}/.ssh/id_rsa.pub", "w") { |f| f.puts }
206
+ @cli.should_receive(:associate_key).with("#{@cli.home_directory}/.ssh/id_rsa2.pub")
207
+ @cli.should_receive(:ask).and_return("2")
208
+ @cli.check_for_associated_ssh_key
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+ require "turbot/client/pgbackups"
3
+ require "turbot/helpers"
4
+
5
+ describe Turbot::Client::Pgbackups do
6
+
7
+ include Turbot::Helpers
8
+
9
+ let(:path) { "http://id:password@pgbackups.turbot.com" }
10
+ let(:client) { Turbot::Client::Pgbackups.new path+'/api' }
11
+ let(:transfer_path) { path + '/client/transfers' }
12
+
13
+ describe "api" do
14
+ let(:version) { Turbot::Client.version }
15
+
16
+ it 'still has a turbot gem version' do
17
+ version.should be
18
+ version.split(/\./).first.to_i.should >= 0
19
+ end
20
+
21
+ it 'includes the turbot gem version' do
22
+ stub_request(:get, transfer_path)
23
+ client.get_transfers
24
+ a_request(:get, transfer_path).with(
25
+ :headers => {'X-Turbot-Gem-Version' => version}
26
+ ).should have_been_made.once
27
+ end
28
+ end
29
+
30
+ describe "create transfers" do
31
+ it "sends a request to the client" do
32
+ stub_request(:post, transfer_path).to_return(
33
+ :body => json_encode({"message" => "success"}),
34
+ :status => 200
35
+ )
36
+
37
+ client.create_transfer("postgres://from", "postgres://to", "FROMNAME", "TO_NAME")
38
+
39
+ a_request(:post, transfer_path).should have_been_made.once
40
+ end
41
+ end
42
+
43
+ end