runssh 0.2.2 → 0.4.0

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.
@@ -21,47 +21,18 @@ require 'stringio'
21
21
  require 'yaml'
22
22
 
23
23
  describe "The CLI interface" do
24
- # a shortcut to verify the help for print command
25
- def match_print
26
- @buffer.should match(/Print host configuration/)
27
- end
28
-
29
- before(:each) do
30
- @buffer = ""
31
- $stdout = StringIO.open(@buffer, 'w')
32
- $stderr = StringIO.open(@buffer, 'w')
33
- end
34
-
35
- describe "when initialized" do
36
- it "should display help when run with no arguments" do
37
- expect { RunSSHLib::CLI.new([]) }.to exit_normaly
38
- @buffer.should match(/Available commands:/)
39
- end
40
-
41
- it "should display help when called with help as the only parameter" do
42
- expect { RunSSHLib::CLI.new(['help']) }.to exit_normaly
43
- @buffer.should match(/Available commands:/)
44
- end
45
-
24
+ context "argument parser" do
46
25
  it "should correctly process the -f argument" do
47
26
  cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print test))
48
27
  global_options = cli.instance_variable_get :@global_options
49
28
  global_options[:config_file].should eql("#{TMP_FILE}")
50
- cli.instance_variable_get(:@c).
51
- instance_variable_get(:@config_file).
52
- should eql("#{TMP_FILE}")
53
29
  end
54
30
 
55
31
  it "should display version when asked for" do
56
- expect { RunSSHLib::CLI.new(['-v'])}.to exit_normaly
57
- @buffer.should include(RunSSHLib::Version::STRING)
58
- end
59
-
60
- it "should correctly process the `help command` scheme" do
61
- expect do
62
- RunSSHLib::CLI.new(%w(help print ?))
63
- end.to exit_normaly
64
- match_print
32
+ expect {
33
+ capture(:stdout) { RunSSHLib::CLI.new(['-v']) }
34
+ }.to exit_normaly
35
+ @buf.should include(RunSSHLib::Version::STRING)
65
36
  end
66
37
 
67
38
  it "should correctly parse the `?` for completion" do
@@ -71,334 +42,225 @@ describe "The CLI interface" do
71
42
 
72
43
  it "should raise an error when invoked with invalid command" do
73
44
  expect do
74
- RunSSHLib::CLI.new(%W(-f #{TMP_FILE} wrong))
75
- end.to exit_abnormaly
76
- @buffer.should match(/invalid command/)
77
- end
78
-
79
- it "should display right message upon older configuration error" do
80
- dump_config Hash.new
81
- expect do
82
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print ?))
45
+ capture(:stderr) {
46
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} wrong))
47
+ }
83
48
  end.to exit_abnormaly
84
- @buffer.should match(/--update-config/)
85
- @buffer.should match(/.none/)
49
+ @buf.should match(/invalid command/)
86
50
  end
87
51
 
88
- describe "with --update_config" do
89
- let(:config_v_none) do
90
- YAML.load_file(File.join(File.dirname(__FILE__), '..',
91
- 'fixtures', 'runssh_v_none.yml'))
92
- end
93
-
94
- it "should accept --update-config as argument" do
95
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
96
- end
97
-
98
- it "should not fail upon initialization if config is of older version" do
99
- dump_config config_v_none
100
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
101
- end
102
-
103
- it "should not initialize @config object after initialization" do
104
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
105
- cli.instance_variable_get(:@c).should be_nil
106
- end
52
+ it "displays completions and exit if requested" do
53
+ import_fixtures
54
+ capture(:stdout) {
55
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print ?)).run
56
+ }
57
+ @buf.should include("cust1")
58
+ @buf.should include("cust2")
107
59
  end
108
60
  end
109
61
 
110
- describe "main help" do
111
- it "should include a description of all subcommands" do
112
- expect { RunSSHLib::CLI.new([]) }.to exit_normaly
62
+ context "help" do
63
+ it "includes a description of all subcommands" do
64
+ expect {
65
+ capture(:stdout) { RunSSHLib::CLI.new([]) }
66
+ }.to exit_normaly
113
67
  RunSSHLib::CLI::COMMAND.each do |subcmd|
114
- @buffer.should include("* #{subcmd}")
68
+ @buf.should include("* #{subcmd}")
115
69
  end
116
70
  end
117
71
  end
118
72
 
119
- describe "when run" do
120
- before(:all) do
121
- import_fixtures
73
+ context "update_config" do
74
+ before(:each) do
75
+ dump_config Hash.new
122
76
  end
123
77
 
124
- it "should parse display completions and exit if requested" do
125
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print ?))
126
- cli.should_not_receive(:run_print)
127
- cli.instance_variable_get(:@c).should_receive(:list_groups).with([])
128
- cli.run
78
+ it "displays an appropriate message when configuration version is invalid" do
79
+ expect {
80
+ capture(:stdout) {
81
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} shell))
82
+ }
83
+ }.to exit_abnormaly
84
+ @buf.should match(/--update-config/)
85
+ @buf.should match(/.none/)
86
+ @buf.should include("-f #{TMP_FILE}")
129
87
  end
130
88
 
131
- it "should run run_update_config when called with --update-config" do
132
- @cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
133
- @cli.should_receive(:run_update_config)
134
- @cli.run
89
+ it "doesn't display the config file path in the error message if using default config file" do
90
+ RunSSHLib::ConfigFile.stub(:new) { raise RunSSHLib::OlderConfigVersionError, 'none' }
91
+ expect {
92
+ capture(:stdout) {
93
+ RunSSHLib::CLI.new(%w(shell)).run
94
+ }
95
+ }.to exit_abnormaly
96
+ @buf.should_not include("-f")
135
97
  end
136
98
 
137
- context "update_config" do
138
- let(:cf) { double('ConfigFile') }
139
-
140
- it "should initialize ConfigFile with old_version=true and run update_config" do
141
- cf.should_receive(:update_config)
142
- RunSSHLib::ConfigFile.should_receive(:new).with(TMP_FILE, true).
143
- and_return(cf)
144
- @cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
145
- @cli.run
146
- end
147
-
148
- it "should inform the user of success and backup file" do
149
- backup_path = "/path/to/backup_file"
150
- cf.should_receive(:update_config).and_return(backup_path)
151
- RunSSHLib::ConfigFile.should_receive(:new).and_return(cf)
152
- @cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
153
- @cli.run
154
- @buffer.should include(backup_path)
155
- end
156
-
157
- it "should inform the user if no backup was required" do
158
- cf.should_receive(:update_config).and_return(nil)
159
- RunSSHLib::ConfigFile.should_receive(:new).and_return(cf)
160
- @cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config))
161
- @cli.run
162
- @buffer.should include("No update was performed")
163
- end
99
+ it "upgrades the configuration" do
100
+ capture(:stdout) {
101
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config)).run
102
+ }
103
+ config = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print ?)).instance_variable_get(:@c)
104
+ config.instance_variable_get(:@config)['VERSION'].should == RunSSHLib::ConfigFile::Version
164
105
  end
165
106
 
166
- describe "with subcommand" do
167
- context "shell" do
168
- before(:each) do
169
- @shell_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} shell))
170
- end
171
-
172
- it "should require a path" do
173
- expect { @shell_cli.run }.to exit_abnormaly
174
- @buffer.should include("not host definition")
175
- end
176
-
177
- it "should execute the run_shell method" do
178
- @shell_cli.should_receive(:run_shell)
179
- @shell_cli.run
180
- end
181
-
182
- it "should parse 's' as shell" do
183
- @shell_cli.send(:extract_subcommand, %w(s root)).should eql('shell')
184
- end
185
-
186
- it "should have all required arguments" do
187
- options = @shell_cli.instance_variable_get :@options
188
- options.should have_key(:login)
189
- options.should have_key(:local_tunnel)
190
- end
191
-
192
- it "should not overwrite nil arguments with saved ones when merging" do
193
- import_fixtures
194
- RunSSHLib::SshBackend.should_receive(:shell).
195
- with(hash_including(
196
- :host_name => "a.example.com",
197
- :login => "otheruser")).
198
- and_return(nil)
199
- cli = RunSSHLib::CLI.new(
200
- %W(-f #{TMP_FILE} shell cust2 dc internal somehost))
201
- cli.run
202
- end
203
-
204
- it "should correctly call SshBackend.shell with merged definition" do
205
- import_fixtures
206
- RunSSHLib::SshBackend.should_receive(:shell).
207
- with(hash_including(:host_name => "a.example.com",
208
- :login => "someuser")).
209
- and_return(nil)
210
- cli = RunSSHLib::CLI.new(
211
- %W(-f #{TMP_FILE} shell -l someuser cust2 dc internal somehost))
212
- cli.run
213
- end
214
-
215
- it "should correctly allow overriding of hostname" do
216
- import_fixtures
217
- RunSSHLib::SshBackend.should_receive(:shell).
218
- with(hash_including(:host_name => "overridehost"))
219
- cli = RunSSHLib::CLI.new(
220
- %W(-f #{TMP_FILE} shell -n overridehost cust2 dc internal somehost))
221
- cli.run
222
- end
107
+ it "informs the user of success and backup file" do
108
+ capture(:stdout) {
109
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config)).run
110
+ }
111
+ @buf.should include "updated to the approproate version"
112
+ @buf.should include "#{TMP_FILE}.none"
113
+ end
223
114
 
224
- it "should correctly parse remote command (indicated by --)" do
225
- import_fixtures
226
- RunSSHLib::SshBackend.should_receive(:shell).
227
- with(hash_including(:remote_cmd => "ls -l /tmp")).
228
- and_return(nil)
229
- cli = RunSSHLib::CLI.new(
230
- %W(-f #{TMP_FILE} shell -l someuser cust2 dc internal somehost
231
- -- ls -l /tmp)
232
- )
233
- cli.run
234
- end
235
- end
115
+ it "informs the user if run with --update-config and no update is required" do
116
+ # we're running this twice to make sure we have a valid config file
117
+ # remember that we create invalid config file in the before method
118
+ capture(:stdout) {
119
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config)).run
120
+ }
121
+ capture(:stdout) {
122
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} --update-config)).run
123
+ }
124
+ @buf.should include "Your configuration seems to be at the appropriate version"
125
+ @buf.should include "No update was performed"
126
+ end
127
+ end
236
128
 
237
- describe "add" do
238
- before(:each) do
239
- @add_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} add -n host one two))
240
- end
129
+ describe "shell subcommand" do
130
+ it "should not overwrite nil arguments with saved ones when merging" do
131
+ import_fixtures
132
+ RunSSHLib::SshBackend.should_receive(:shell).
133
+ with(hash_including(
134
+ :host_name => "a.example.com",
135
+ :login => "otheruser")).
136
+ and_return(nil)
137
+ cli = RunSSHLib::CLI.new(
138
+ %W(-f #{TMP_FILE} shell cust2 dc internal somehost))
139
+ cli.run
140
+ end
241
141
 
242
- it "should parse 'a' as add" do
243
- @add_cli.send(:extract_subcommand, ['a']).should eql('add')
244
- end
142
+ it "should correctly call SshBackend.shell with merged definition" do
143
+ import_fixtures
144
+ RunSSHLib::SshBackend.should_receive(:shell).
145
+ with(hash_including(:host_name => "a.example.com",
146
+ :login => "someuser")).
147
+ and_return(nil)
148
+ cli = RunSSHLib::CLI.new(
149
+ %W(-f #{TMP_FILE} shell -l someuser cust2 dc internal somehost))
150
+ cli.run
151
+ end
245
152
 
246
- it "should have all required arguments" do
247
- options = @add_cli.instance_variable_get :@options
248
- options.should have_key(:host_name)
249
- options.should have_key(:login)
250
- end
153
+ it "merges given options with saved ones" do
154
+ stub_ssh_exec
251
155
 
252
- it "should invoke the add_host_def" do
253
- @add_cli.instance_variable_get(:@c).should_receive(:add_host_def).
254
- with([:one], :two, RunSSHLib::SshHostDef.new({
255
- :host_name => 'host',:login => nil
256
- }))
257
- @add_cli.run
258
- end
156
+ # multiple options saved, single option given
157
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} add one two -n some.host -N)).run
158
+ capture(:stdout) do
159
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} shell one two -o ForwardAgent=true)).run
259
160
  end
161
+ @buf.should include('ssh some.host')
162
+ @buf.should include('StrictHostKeyChecking=no')
163
+ @buf.should include('UserKnownHostsFile=/dev/null')
164
+ @buf.should include('ForwardAgent=true')
165
+
166
+ # single option saved, multiple options given
167
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} add one three -n some.host
168
+ -o ForwardAgent=true)).run
169
+ capture(:stdout) do
170
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} shell one three
171
+ -o StrictHostKeyChecking=no
172
+ -o UserKnownHostsFile=/dev/null)).run
173
+ end
174
+ @buf.should include('ssh some.host')
175
+ @buf.should include('StrictHostKeyChecking=no')
176
+ @buf.should include('UserKnownHostsFile=/dev/null')
177
+ @buf.should include('ForwardAgent=true')
178
+ end
260
179
 
261
- describe "del" do
262
- before(:each) do
263
- @d_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} del))
264
- @d_cli.instance_variable_get(:@c).stub(:delete_path)
265
- @hl = double('HighLine')
266
- HighLine.stub(:new) {@hl}
267
- @hl.stub(:agree)
268
- end
269
-
270
- it "should parse 'd' as del" do
271
- @d_cli.send(:extract_subcommand, ['d']).should eql('del')
272
- end
273
-
274
- it "should verify the deletion" do
275
- @hl.should_receive(:agree).with(/Are you sure/)
276
- @d_cli.run
277
- end
278
-
279
- it "should perform the deletion upon confirmation" do
280
- @hl.should_receive(:agree).and_return(true)
281
- @d_cli.instance_variable_get(:@c).should_receive(:delete_path)
282
- @d_cli.run
283
- end
284
-
285
- it "should cancel the deletion if not confirmed" do
286
- @hl.should_receive(:agree).and_return(false)
287
- @d_cli.instance_variable_get(:@c).should_not_receive(:delete_path)
288
- @d_cli.run
289
- @buffer.should match(/cancel/)
290
- end
291
-
292
- it "should pass the right path to delete_path" do
293
- cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} del one two three))
294
- @hl.should_receive(:agree).and_return(true)
295
- cli.instance_variable_get(:@c).should_receive(:delete_path).
296
- with([:one, :two, :three])
297
- cli.run
298
- end
180
+ context "insecure-host-key" do
181
+ let (:cli) {
182
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} shell --insecure-host-key 1 some host))
183
+ }
184
+ let(:khud) { double('RunSSHLib::SshBackend::KnownHostsUtils') }
185
+ let(:input) { 'no' }
186
+
187
+ before(:each) do
188
+ stub_ssh_exec
189
+ create_known_hosts_file 'some.host'
190
+ RunSSHLib::CLI.new(%W(-f #{TMP_FILE} add some host -n some.host))
191
+ RunSSHLib::SshBackend::KnownHostsUtils.should_receive(:new).and_return(khud)
192
+ khud.should_receive(:known_hosts_file).and_return(KNOWN_HOSTS_FILE)
299
193
  end
300
194
 
301
- describe "update" do
302
- before(:each) do
303
- @update_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} update -n newhost root))
304
- end
305
-
306
- it "should parse 'u' as update" do
307
- @update_cli.send(:extract_subcommand, ['u']).should eql('update')
308
- end
309
-
310
- it "should have all required argumants" do
311
- options = @update_cli.instance_variable_get :@options
312
- options.should have_key(:host_name)
313
- options.should have_key(:login)
314
- end
315
-
316
- it "should invoke update_host_def" do
317
- config = @update_cli.instance_variable_get :@c
318
- config.should_receive(:update_host_def).
319
- with([:root], RunSSHLib::SshHostDef.new({
320
- :host_name => "newhost", :login => nil
321
- }))
322
- @update_cli.run
195
+ it "warns the user about deleting conflicting key" do
196
+ capture(:stderr) do # avoid stderr
197
+ capture(:stdout, input) do |variable|
198
+ # Since were cancelling it should exit with error but we don't
199
+ # test that now
200
+ expect { cli.run }.to exit_abnormaly
201
+ end
202
+ @buf.should match /Conflicting key could indicate compromised host/
203
+ @buf.should match /some.host/
323
204
  end
324
205
  end
325
206
 
326
- describe "print" do
327
- before(:each) do
328
- import_fixtures
329
- @p_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print cust2 dc internal somehost))
330
- end
331
-
332
- it "should parse 'p' as print" do
333
- @p_cli.send(:extract_subcommand, ['p']).should eql('print')
334
- end
335
-
336
- it "should print correctly host definition" do
337
- @p_cli.run
338
- @buffer.should match(/Host definition for: somehost/)
339
- @buffer.should match(/host: a.example.com/)
207
+ it "aborts execution if canceling the deletion at the prompt" do
208
+ capture(:stdout) do # just a wrapper to avoid output
209
+ capture(:stderr, input) do
210
+ expect { cli.run }.to exit_abnormaly
211
+ end.should == "Cancelled\n"
340
212
  end
341
213
  end
214
+ end
215
+ end
342
216
 
343
- describe "import" do
344
- before(:each) do
345
- @i_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} import -i inputfile))
346
- @i_cli.instance_variable_get(:@c).stub(:import)
347
- @hl = double('HighLine')
348
- HighLine.stub(:new) {@hl}
349
- @hl.stub(:agree)
350
- end
217
+ context "Add bookmark with ssh options" do
218
+ it "adds options specified with '-o' to the '--no-host-key-checking' options" do
219
+ options = %W(-f #{TMP_FILE} add -o ForwardAgent=true --no-host-key-checking -n some.host one two)
220
+ RunSSHLib::CLI.new(options).run
221
+ host = get_host('one two')
222
+ host.definition[:option].should include('ForwardAgent=true')
223
+ host.definition[:option].should include('StrictHostKeyChecking=no')
224
+ host.definition[:option].should include('UserKnownHostsFile=/dev/null')
225
+ end
226
+ end
351
227
 
352
- it "should parse 'i' as import" do
353
- @i_cli.send(:extract_subcommand, ['i']).should eql('import')
354
- end
228
+ context "Command abbreviation" do
229
+ before(:each) do
230
+ # we just need valid cli. Args are not important!
231
+ @ab_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} print))
232
+ end
355
233
 
356
- it "should have the right arguments" do
357
- options = @i_cli.instance_variable_get :@options
358
- options.include?(:input_file)
359
- end
234
+ it "should parse 'd' as del" do
235
+ @ab_cli.send(:extract_subcommand, ['d']).should eql('del')
236
+ end
360
237
 
361
- it "should verify the import with the user" do
362
- @hl.should_receive(:agree).with(/OVERWRITES/)
363
- @i_cli.run
364
- end
238
+ it "should parse 'a' as add" do
239
+ @ab_cli.send(:extract_subcommand, ['a']).should eql('add')
240
+ end
365
241
 
366
- it "should run import upon confirmation" do
367
- @hl.should_receive(:agree).and_return(true)
368
- @i_cli.instance_variable_get(:@c).should_receive(:import)
369
- @i_cli.run
370
- end
242
+ it "should parse 's' as shell" do
243
+ @ab_cli.send(:extract_subcommand, %w(s root)).should eql('shell')
244
+ end
371
245
 
372
- it "should cancel if not confirmed" do
373
- @hl.should_receive(:agree).and_return(false)
374
- @i_cli.instance_variable_get(:@c).should_not_receive(:import)
375
- @i_cli.run
376
- @buffer.should match(/cancel/)
377
- end
246
+ it "should parse 'i' as import" do
247
+ @ab_cli.send(:extract_subcommand, ['i']).should eql('import')
248
+ end
378
249
 
379
- it "should pass the right argument to import" do
380
- @hl.should_receive(:agree).and_return(true)
381
- @i_cli.instance_variable_get(:@c).should_receive(:import).
382
- with('inputfile')
383
- @i_cli.run
384
- end
385
- end
250
+ it "should parse 'u' as update" do
251
+ @ab_cli.send(:extract_subcommand, ['u']).should eql('update')
252
+ end
386
253
 
387
- describe "export" do
388
- before(:each) do
389
- @e_cli = RunSSHLib::CLI.new(%W(-f #{TMP_FILE} export -o somefile))
390
- end
254
+ it "should parse 'p' as print" do
255
+ @ab_cli.send(:extract_subcommand, ['p']).should eql('print')
256
+ end
391
257
 
392
- it "should parse 'e' as export" do
393
- @e_cli.send(:extract_subcommand, ['e']).should eql('export')
394
- end
258
+ it "should parse 'e' as export" do
259
+ @ab_cli.send(:extract_subcommand, ['e']).should eql('export')
260
+ end
395
261
 
396
- it "should run export with the right parameters" do
397
- @e_cli.instance_variable_get(:@c).should_receive(:export).
398
- with('somefile')
399
- @e_cli.run
400
- end
401
- end
262
+ it "should parse 'c' as cpid" do
263
+ @ab_cli.send(:extract_subcommand, ['c']).should eql('cpid')
402
264
  end
403
265
  end
404
266
 
@@ -291,10 +291,8 @@ describe "RunSSH Configuration class" do
291
291
  end
292
292
 
293
293
  describe "when importing" do
294
- let(:yml) { File.join(File.dirname(__FILE__), '../fixtures', 'runssh.yml') }
295
-
296
294
  it "should not accept config from different config version" do
297
- y = YAML.load_file(yml)
295
+ y = YAML.load_file(YML_FIXTURE)
298
296
  y['VERSION'] = 2.0
299
297
  File.open(@tmp_yml, 'w') { |out| YAML.dump(y, out) }
300
298
  expect do
@@ -305,9 +303,9 @@ describe "RunSSH Configuration class" do
305
303
 
306
304
  it "should correctly export and import YAML files" do
307
305
  c = RunSSHLib::ConfigFile.new(@temp_file)
308
- c.import(yml)
306
+ c.import(YML_FIXTURE)
309
307
  c.export(@tmp_yml)
310
- YAML.load_file(@tmp_yml).should == YAML.load_file(yml)
308
+ YAML.load_file(@tmp_yml).should == YAML.load_file(YML_FIXTURE)
311
309
  end
312
310
  end
313
311
 
@@ -20,7 +20,33 @@ require 'spec_helper'
20
20
  require 'runsshlib'
21
21
 
22
22
  describe RunSSHLib::SshBackend do
23
- context "#shell" do
23
+
24
+ describe "KnownHostsUtils" do
25
+ let(:ckhu) {
26
+ RunSSHLib::SshBackend::KnownHostsUtils
27
+ }
28
+
29
+ it "initializes with ~/.ssh/known_hosts file by default" do
30
+ khu = ckhu.new
31
+ khu.instance_variable_get(:@known_hosts_file).should == File.expand_path('~/.ssh/known_hosts')
32
+ end
33
+
34
+ it "accepts custom known_hosts file" do
35
+ khu = ckhu.new(KNOWN_HOSTS_FILE)
36
+ khu.instance_variable_get(:@known_hosts_file).should == KNOWN_HOSTS_FILE
37
+ end
38
+
39
+ it "deletes the correct line number" do
40
+ File.open(KNOWN_HOSTS_FILE, 'w') do |io|
41
+ io.write("some bogus line\nline to delete\nlast line\n")
42
+ end
43
+ khu = ckhu.new(KNOWN_HOSTS_FILE)
44
+ khu.delete_line_from_known_hosts_file(2)
45
+ IO.read(KNOWN_HOSTS_FILE).should == "some bogus line\nlast line\n"
46
+ end
47
+ end
48
+
49
+ describe "#shell" do
24
50
  let(:test_data) do
25
51
  {:host_name => "a",
26
52
  :login => "user",
@@ -54,11 +80,19 @@ describe RunSSHLib::SshBackend do
54
80
 
55
81
  it "should handle correctly remote commands" do
56
82
  RunSSHLib::SshBackend.should_receive(:exec).
57
- with(/^ssh\s+-l\s+#{test_data[:login]}\s+#{test_data[:host_name]}\s+--\s+"uptime"$/).
83
+ with(/^ssh\s+-t\s-l\s+#{test_data[:login]}\s+#{test_data[:host_name]}\s+--\s+"uptime"$/).
58
84
  and_return(nil)
59
85
  RunSSHLib::SshBackend.shell(test_data)
60
86
  end
61
87
 
88
+ it "should not enable pseudo terminal with remote command if run with -T" do
89
+ data = test_data.merge(:no_pseudo_terminal => true)
90
+ RunSSHLib::SshBackend.should_receive(:exec).
91
+ with(/^ssh\s+-l\s+#{test_data[:login]}\s+#{test_data[:host_name]}\s+--\s+"uptime"$/).
92
+ and_return(nil)
93
+ RunSSHLib::SshBackend.shell(data)
94
+ end
95
+
62
96
  it "should ignore empty remote commands" do
63
97
  data = test_data.merge(:remote_cmd => "")
64
98
  RunSSHLib::SshBackend.should_receive(:exec).
@@ -73,9 +107,20 @@ describe RunSSHLib::SshBackend do
73
107
  with(/^ssh\s+.*\s-L\s+6000:localhost:6000.*/)
74
108
  RunSSHLib::SshBackend.shell(data)
75
109
  end
110
+
111
+ it "calls all available ssh options, each with '-o'" do
112
+ data = test_data.merge(:remote_cmd => '', :login => '',
113
+ :option => %w(UserKnownHostsFile=/dev/null StrictHostKeyChecking=no))
114
+ stub_ssh_exec
115
+ capture(:stdout) do
116
+ RunSSHLib::SshBackend.shell(data)
117
+ end
118
+ @buf.should match(%r{-o UserKnownHostsFile=/dev/null})
119
+ @buf.should match(/-o StrictHostKeyChecking=no/)
120
+ end
76
121
  end
77
122
 
78
- context "#normalize_tunnel_definition" do
123
+ describe "#normalize_tunnel_definition" do
79
124
  it "converts abbreviated tunnel definition correctly" do
80
125
  RunSSHLib::SshBackend.normalize_tunnel_definition("7070").should ==
81
126
  "7070:localhost:7070"