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.
- data/.gitignore +2 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +22 -8
- data/README.rdoc +39 -9
- data/bin/runssh_comp.sh +1 -1
- data/features/add_bookmarks.feature +58 -0
- data/features/cli_help.feature +32 -0
- data/features/copy_id.feature +26 -0
- data/features/delete_bookmarks.feature +45 -0
- data/features/export_bookmarks.feature +19 -0
- data/features/import_bookmarks.feature +35 -0
- data/features/print_bookmarks.feature +42 -0
- data/features/run_shell.feature +83 -0
- data/features/step_definitions/argument_steps.rb +51 -0
- data/features/step_definitions/bookmarks_steps.rb +109 -0
- data/features/step_definitions/output_steps.rb +77 -0
- data/features/support/env.rb +36 -0
- data/features/update_bookmarks.feature +24 -0
- data/lib/runsshlib/cli.rb +248 -120
- data/lib/runsshlib/ssh_backend.rb +34 -4
- data/lib/runsshlib/ssh_host_def.rb +12 -2
- data/lib/runsshlib/version.rb +3 -3
- data/lib/runsshlib.rb +3 -0
- data/runssh.gemspec +0 -5
- data/spec/runsshlib/cli_spec.rb +181 -319
- data/spec/runsshlib/config_file_spec.rb +3 -5
- data/spec/runsshlib/ssh_backend_spec.rb +48 -3
- data/spec/runsshlib/ssh_host_def_spec.rb +5 -1
- data/spec/spec_helper.rb +4 -65
- data/spec/support/utils.rb +149 -0
- metadata +34 -86
data/spec/runsshlib/cli_spec.rb
CHANGED
@@ -21,47 +21,18 @@ require 'stringio'
|
|
21
21
|
require 'yaml'
|
22
22
|
|
23
23
|
describe "The CLI interface" do
|
24
|
-
|
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 {
|
57
|
-
|
58
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
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
|
-
@
|
85
|
-
@buffer.should match(/.none/)
|
49
|
+
@buf.should match(/invalid command/)
|
86
50
|
end
|
87
51
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
111
|
-
it "
|
112
|
-
expect {
|
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
|
-
@
|
68
|
+
@buf.should include("* #{subcmd}")
|
115
69
|
end
|
116
70
|
end
|
117
71
|
end
|
118
72
|
|
119
|
-
|
120
|
-
before(:
|
121
|
-
|
73
|
+
context "update_config" do
|
74
|
+
before(:each) do
|
75
|
+
dump_config Hash.new
|
122
76
|
end
|
123
77
|
|
124
|
-
it "
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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 "
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
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
|
-
|
247
|
-
|
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
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
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
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
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
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
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
|
-
|
353
|
-
|
354
|
-
|
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
|
-
|
357
|
-
|
358
|
-
|
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
|
-
|
362
|
-
|
363
|
-
|
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
|
-
|
367
|
-
|
368
|
-
|
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
|
-
|
373
|
-
|
374
|
-
|
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
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
388
|
-
|
389
|
-
|
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
|
-
|
393
|
-
|
394
|
-
|
258
|
+
it "should parse 'e' as export" do
|
259
|
+
@ab_cli.send(:extract_subcommand, ['e']).should eql('export')
|
260
|
+
end
|
395
261
|
|
396
|
-
|
397
|
-
|
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(
|
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(
|
306
|
+
c.import(YML_FIXTURE)
|
309
307
|
c.export(@tmp_yml)
|
310
|
-
YAML.load_file(@tmp_yml).should == YAML.load_file(
|
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
|
-
|
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
|
-
|
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"
|