test-kitchen 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +1 -1
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +20 -9
  5. data/CHANGELOG.md +219 -108
  6. data/Gemfile +10 -6
  7. data/Guardfile +38 -9
  8. data/README.md +11 -1
  9. data/Rakefile +21 -37
  10. data/bin/kitchen +4 -4
  11. data/features/kitchen_action_commands.feature +161 -0
  12. data/features/kitchen_console_command.feature +34 -0
  13. data/features/kitchen_diagnose_command.feature +64 -0
  14. data/features/kitchen_init_command.feature +29 -17
  15. data/features/kitchen_list_command.feature +2 -2
  16. data/features/kitchen_login_command.feature +56 -0
  17. data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
  18. data/features/kitchen_test_command.feature +88 -0
  19. data/features/step_definitions/gem_steps.rb +8 -6
  20. data/features/step_definitions/git_steps.rb +4 -2
  21. data/features/step_definitions/output_steps.rb +5 -0
  22. data/features/support/env.rb +12 -9
  23. data/lib/kitchen.rb +60 -38
  24. data/lib/kitchen/base64_stream.rb +55 -0
  25. data/lib/kitchen/busser.rb +124 -58
  26. data/lib/kitchen/cli.rb +121 -38
  27. data/lib/kitchen/collection.rb +3 -3
  28. data/lib/kitchen/color.rb +4 -4
  29. data/lib/kitchen/command.rb +78 -11
  30. data/lib/kitchen/command/action.rb +3 -2
  31. data/lib/kitchen/command/console.rb +12 -5
  32. data/lib/kitchen/command/diagnose.rb +17 -3
  33. data/lib/kitchen/command/driver_discover.rb +26 -7
  34. data/lib/kitchen/command/exec.rb +41 -0
  35. data/lib/kitchen/command/list.rb +44 -14
  36. data/lib/kitchen/command/login.rb +2 -1
  37. data/lib/kitchen/command/sink.rb +2 -1
  38. data/lib/kitchen/command/test.rb +5 -4
  39. data/lib/kitchen/config.rb +146 -14
  40. data/lib/kitchen/configurable.rb +314 -0
  41. data/lib/kitchen/data_munger.rb +522 -18
  42. data/lib/kitchen/diagnostic.rb +43 -4
  43. data/lib/kitchen/driver.rb +4 -4
  44. data/lib/kitchen/driver/base.rb +80 -115
  45. data/lib/kitchen/driver/dummy.rb +34 -6
  46. data/lib/kitchen/driver/proxy.rb +14 -3
  47. data/lib/kitchen/driver/ssh_base.rb +61 -7
  48. data/lib/kitchen/errors.rb +109 -9
  49. data/lib/kitchen/generator/driver_create.rb +39 -5
  50. data/lib/kitchen/generator/init.rb +130 -45
  51. data/lib/kitchen/instance.rb +162 -28
  52. data/lib/kitchen/lazy_hash.rb +79 -7
  53. data/lib/kitchen/loader/yaml.rb +159 -27
  54. data/lib/kitchen/logger.rb +267 -21
  55. data/lib/kitchen/logging.rb +30 -3
  56. data/lib/kitchen/login_command.rb +11 -2
  57. data/lib/kitchen/metadata_chopper.rb +2 -2
  58. data/lib/kitchen/provisioner.rb +4 -4
  59. data/lib/kitchen/provisioner/base.rb +107 -103
  60. data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
  61. data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
  62. data/lib/kitchen/provisioner/chef_base.rb +206 -167
  63. data/lib/kitchen/provisioner/chef_solo.rb +25 -7
  64. data/lib/kitchen/provisioner/chef_zero.rb +105 -29
  65. data/lib/kitchen/provisioner/dummy.rb +1 -1
  66. data/lib/kitchen/provisioner/shell.rb +21 -6
  67. data/lib/kitchen/rake_tasks.rb +8 -3
  68. data/lib/kitchen/shell_out.rb +15 -18
  69. data/lib/kitchen/ssh.rb +122 -27
  70. data/lib/kitchen/state_file.rb +24 -7
  71. data/lib/kitchen/thor_tasks.rb +9 -4
  72. data/lib/kitchen/util.rb +43 -118
  73. data/lib/kitchen/version.rb +1 -1
  74. data/lib/vendor/hash_recursive_merge.rb +10 -2
  75. data/spec/kitchen/base64_stream_spec.rb +77 -0
  76. data/spec/kitchen/busser_spec.rb +490 -0
  77. data/spec/kitchen/collection_spec.rb +10 -10
  78. data/spec/kitchen/color_spec.rb +2 -2
  79. data/spec/kitchen/config_spec.rb +234 -62
  80. data/spec/kitchen/configurable_spec.rb +490 -0
  81. data/spec/kitchen/data_munger_spec.rb +1070 -862
  82. data/spec/kitchen/diagnostic_spec.rb +79 -0
  83. data/spec/kitchen/driver/base_spec.rb +80 -85
  84. data/spec/kitchen/driver/dummy_spec.rb +43 -14
  85. data/spec/kitchen/driver/proxy_spec.rb +134 -0
  86. data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
  87. data/spec/kitchen/driver_spec.rb +15 -15
  88. data/spec/kitchen/errors_spec.rb +309 -0
  89. data/spec/kitchen/instance_spec.rb +143 -46
  90. data/spec/kitchen/lazy_hash_spec.rb +36 -9
  91. data/spec/kitchen/loader/yaml_spec.rb +237 -226
  92. data/spec/kitchen/logger_spec.rb +419 -0
  93. data/spec/kitchen/logging_spec.rb +59 -0
  94. data/spec/kitchen/login_command_spec.rb +49 -0
  95. data/spec/kitchen/metadata_chopper_spec.rb +82 -0
  96. data/spec/kitchen/platform_spec.rb +4 -4
  97. data/spec/kitchen/provisioner/base_spec.rb +65 -125
  98. data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
  99. data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
  100. data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
  101. data/spec/kitchen/provisioner/shell_spec.rb +269 -0
  102. data/spec/kitchen/provisioner_spec.rb +6 -6
  103. data/spec/kitchen/shell_out_spec.rb +143 -0
  104. data/spec/kitchen/ssh_spec.rb +683 -0
  105. data/spec/kitchen/state_file_spec.rb +28 -21
  106. data/spec/kitchen/suite_spec.rb +7 -7
  107. data/spec/kitchen/util_spec.rb +68 -10
  108. data/spec/kitchen_spec.rb +107 -0
  109. data/spec/spec_helper.rb +18 -13
  110. data/support/chef-client-zero.rb +10 -9
  111. data/support/chef_helpers.sh +16 -0
  112. data/support/download_helpers.sh +109 -0
  113. data/test-kitchen.gemspec +42 -33
  114. metadata +107 -33
@@ -0,0 +1,644 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2014, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../../spec_helper"
20
+
21
+ require "kitchen"
22
+
23
+ describe Kitchen::Driver::SSHBase do
24
+
25
+ let(:logged_output) { StringIO.new }
26
+ let(:logger) { Logger.new(logged_output) }
27
+ let(:config) { Hash.new }
28
+ let(:state) { Hash.new }
29
+
30
+ let(:busser) do
31
+ stub(
32
+ :setup_cmd => "setup",
33
+ :sync_cmd => "sync",
34
+ :run_cmd => "run"
35
+ )
36
+ end
37
+
38
+ let(:provisioner) do
39
+ stub(
40
+ :install_command => "install",
41
+ :init_command => "init",
42
+ :prepare_command => "prepare",
43
+ :run_command => "run",
44
+ :create_sandbox => true,
45
+ :cleanup_sandbox => true,
46
+ :sandbox_path => "/tmp/sandbox"
47
+ )
48
+ end
49
+
50
+ let(:instance) do
51
+ stub(
52
+ :name => "coolbeans",
53
+ :logger => logger,
54
+ :busser => busser,
55
+ :provisioner => provisioner,
56
+ :to_str => "instance"
57
+ )
58
+ end
59
+
60
+ let(:driver) do
61
+ Kitchen::Driver::SSHBase.new(config).finalize_config!(instance)
62
+ end
63
+
64
+ describe "configuration" do
65
+
66
+ it ":sudo defaults to true" do
67
+ driver[:sudo].must_equal true
68
+ end
69
+
70
+ it ":port defaults to 22" do
71
+ driver[:port].must_equal 22
72
+ end
73
+ end
74
+
75
+ it "#create raises a ClientError" do
76
+ proc { driver.create(state) }.must_raise Kitchen::ClientError
77
+ end
78
+
79
+ it "#destroy raises a ClientError" do
80
+ proc { driver.destroy(state) }.must_raise Kitchen::ClientError
81
+ end
82
+
83
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
84
+ def self.constructs_an_ssh_object
85
+ describe "constructs an SSH object" do
86
+
87
+ it "with hostname set from state" do
88
+ Kitchen::SSH.expects(:new).with { |hostname, _username, _opts|
89
+ hostname.must_equal "fizzy"
90
+ }.returns(stub(:login_command => stub))
91
+
92
+ cmd
93
+ end
94
+
95
+ it "with username set from state" do
96
+ Kitchen::SSH.expects(:new).with { |_hostname, username, _opts|
97
+ username.must_equal "bork"
98
+ }.returns(stub(:login_command => stub))
99
+
100
+ cmd
101
+ end
102
+
103
+ it "with :user_known_hosts_file option set to /dev/null" do
104
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
105
+ opts[:user_known_hosts_file].must_equal "/dev/null"
106
+ }.returns(stub(:login_command => stub))
107
+
108
+ cmd
109
+ end
110
+
111
+ it "with :paranoid option set to false" do
112
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
113
+ opts[:paranoid].must_equal false
114
+ }.returns(stub(:login_command => stub))
115
+
116
+ cmd
117
+ end
118
+
119
+ it "with :keys_only option set to falsey by default" do
120
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
121
+ opts[:keys_only].nil?
122
+ }.returns(stub(:login_command => stub))
123
+
124
+ cmd
125
+ end
126
+
127
+ it "with :keys_only option set to true if :ssh_key is set in config" do
128
+ config[:ssh_key] = "wicked"
129
+
130
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
131
+ opts[:keys_only].must_equal true
132
+ }.returns(stub(:login_command => stub))
133
+
134
+ cmd
135
+ end
136
+
137
+ it "with :keys_only option set to true if :ssh_key is set in state" do
138
+ state[:ssh_key] = "wicked"
139
+
140
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
141
+ opts[:keys_only].must_equal true
142
+ }.returns(stub(:login_command => stub))
143
+
144
+ cmd
145
+ end
146
+
147
+ it "with :keys option set to falsey by default" do
148
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
149
+ opts[:keys].nil?
150
+ }.returns(stub(:login_command => stub))
151
+
152
+ cmd
153
+ end
154
+
155
+ it "with :keys option set to an array if :ssh_key is set in config" do
156
+ config[:ssh_key] = "wicked"
157
+
158
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
159
+ opts[:keys].must_equal ["wicked"]
160
+ }.returns(stub(:login_command => stub))
161
+
162
+ cmd
163
+ end
164
+
165
+ it "with :keys option set to an array if :ssh_key is set in state" do
166
+ state[:ssh_key] = "wicked"
167
+
168
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
169
+ opts[:keys].must_equal ["wicked"]
170
+ }.returns(stub(:login_command => stub))
171
+
172
+ cmd
173
+ end
174
+
175
+ it "with :password option set to falsey by default" do
176
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
177
+ opts[:password].nil?
178
+ }.returns(stub(:login_command => stub))
179
+
180
+ cmd
181
+ end
182
+
183
+ it "with :password option set if given in config" do
184
+ config[:password] = "psst"
185
+
186
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
187
+ opts[:password].must_equal "psst"
188
+ }.returns(stub(:login_command => stub))
189
+
190
+ cmd
191
+ end
192
+
193
+ it "with :password option set if given in state" do
194
+ state[:password] = "psst"
195
+
196
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
197
+ opts[:password].must_equal "psst"
198
+ }.returns(stub(:login_command => stub))
199
+
200
+ cmd
201
+ end
202
+
203
+ it "with :forward_agent option set to falsey by default" do
204
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
205
+ opts[:forward_agent].nil?
206
+ }.returns(stub(:login_command => stub))
207
+
208
+ cmd
209
+ end
210
+
211
+ it "with :forward_agent option set if given in config" do
212
+ config[:forward_agent] = "yeah?"
213
+
214
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
215
+ opts[:forward_agent].must_equal "yeah?"
216
+ }.returns(stub(:login_command => stub))
217
+
218
+ cmd
219
+ end
220
+
221
+ it "with :forward_agent option set if given in state" do
222
+ state[:forward_agent] = "yeah?"
223
+
224
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
225
+ opts[:forward_agent].must_equal "yeah?"
226
+ }.returns(stub(:login_command => stub))
227
+
228
+ cmd
229
+ end
230
+
231
+ it "with :port option set to 22 by default" do
232
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
233
+ opts[:port].must_equal 22
234
+ }.returns(stub(:login_command => stub))
235
+
236
+ cmd
237
+ end
238
+
239
+ it "with :port option set if customized in config" do
240
+ config[:port] = 1234
241
+
242
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
243
+ opts[:port].must_equal 1234
244
+ }.returns(stub(:login_command => stub))
245
+
246
+ cmd
247
+ end
248
+
249
+ it "with :port option set if customized in state" do
250
+ state[:port] = 9999
251
+
252
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
253
+ opts[:port].must_equal 9999
254
+ }.returns(stub(:login_command => stub))
255
+
256
+ cmd
257
+ end
258
+
259
+ it "with :logger option set to driver's logger" do
260
+ Kitchen::SSH.expects(:new).with { |_hostname, _username, opts|
261
+ opts[:logger].must_equal logger
262
+ }.returns(stub(:login_command => stub))
263
+
264
+ cmd
265
+ end
266
+ end
267
+ end
268
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
269
+
270
+ describe "#login_command" do
271
+
272
+ let(:cmd) { driver.login_command(state) }
273
+
274
+ before do
275
+ state[:hostname] = "fizzy"
276
+ state[:username] = "bork"
277
+ end
278
+
279
+ it "returns a LoginCommand" do
280
+ cmd.must_be_instance_of Kitchen::LoginCommand
281
+ end
282
+
283
+ constructs_an_ssh_object
284
+ end
285
+
286
+ describe "#converge" do
287
+
288
+ let(:cmd) { driver.converge(state) }
289
+ let(:connection) { stub(:exec => true) }
290
+
291
+ before do
292
+ state[:hostname] = "fizzy"
293
+ state[:username] = "bork"
294
+ provisioner.stubs(:[]).with(:root_path).returns("/rooty")
295
+ FakeFS.activate!
296
+ FileUtils.mkdir_p("/tmp")
297
+ end
298
+
299
+ after do
300
+ FakeFS.deactivate!
301
+ FakeFS::FileSystem.clear
302
+ end
303
+
304
+ constructs_an_ssh_object
305
+
306
+ it "creates the sandbox" do
307
+ Kitchen::SSH.stubs(:new).yields(connection)
308
+ provisioner.expects(:create_sandbox)
309
+
310
+ cmd
311
+ end
312
+
313
+ it "ensures that the sandbox is cleaned up" do
314
+ Kitchen::SSH.stubs(:new).raises
315
+ provisioner.expects(:cleanup_sandbox)
316
+
317
+ begin
318
+ cmd
319
+ rescue # rubocop:disable Lint/HandleExceptions
320
+ end
321
+ end
322
+
323
+ it "invokes the provisioner commands over ssh" do
324
+ Kitchen::SSH.stubs(:new).yields(connection)
325
+ order = sequence("order")
326
+ connection.expects(:exec).with("install").in_sequence(order)
327
+ connection.expects(:exec).with("init").in_sequence(order)
328
+ connection.expects(:exec).with("prepare").in_sequence(order)
329
+ connection.expects(:exec).with("run").in_sequence(order)
330
+
331
+ cmd
332
+ end
333
+
334
+ it "invokes the #install_command with :http_proxy set in config" do
335
+ config[:http_proxy] = "http://proxy"
336
+ Kitchen::SSH.stubs(:new).yields(connection)
337
+ connection.expects(:exec).with("env http_proxy=http://proxy install")
338
+
339
+ cmd
340
+ end
341
+
342
+ it "invokes the #install_command with :https_proxy set in config" do
343
+ config[:https_proxy] = "https://proxy"
344
+ Kitchen::SSH.stubs(:new).yields(connection)
345
+ connection.expects(:exec).with("env https_proxy=https://proxy install")
346
+
347
+ cmd
348
+ end
349
+
350
+ it "invokes the #install_command with :http_proxy & :https_proxy set" do
351
+ config[:http_proxy] = "http://proxy"
352
+ config[:https_proxy] = "https://proxy"
353
+ Kitchen::SSH.stubs(:new).yields(connection)
354
+ connection.expects(:exec).with(
355
+ "env http_proxy=http://proxy https_proxy=https://proxy install")
356
+
357
+ cmd
358
+ end
359
+
360
+ describe "transferring files" do
361
+
362
+ before do
363
+ Kitchen::SSH.stubs(:new).yields(connection)
364
+ connection.stubs(:upload_path!)
365
+ FileUtils.mkdir_p "/tmp/sandbox/stuff"
366
+ end
367
+
368
+ it "uploads files" do
369
+ connection.expects(:upload_path!).with("/tmp/sandbox/stuff", "/rooty")
370
+
371
+ cmd
372
+ end
373
+
374
+ it "logs to info" do
375
+ cmd
376
+
377
+ logged_output.string.
378
+ must_match(/INFO -- : Transferring files to instance$/)
379
+ end
380
+
381
+ it "logs to debug" do
382
+ cmd
383
+
384
+ logged_output.string.must_match(/DEBUG -- : Transfer complete$/)
385
+ end
386
+
387
+ it "raises an ActionFailed on transfer when SSHFailed is raised" do
388
+ connection.stubs(:upload_path!).raises(Kitchen::SSHFailed.new("dang"))
389
+
390
+ proc { cmd }.must_raise Kitchen::ActionFailed
391
+ end
392
+
393
+ it "raises an ActionFailed on exec when Net::SSH:Exception is raised" do
394
+ connection.stubs(:upload_path!).raises(Net::SSH::Exception.new("dang"))
395
+
396
+ proc { cmd }.must_raise Kitchen::ActionFailed
397
+ end
398
+ end
399
+
400
+ it "raises an ActionFailed on exec when SSHFailed is raised" do
401
+ Kitchen::SSH.stubs(:new).yields(connection)
402
+ connection.stubs(:exec).raises(Kitchen::SSHFailed.new("dang"))
403
+
404
+ proc { cmd }.must_raise Kitchen::ActionFailed
405
+ end
406
+
407
+ it "raises an ActionFailed on exec when Net::SSH:Exception is raised" do
408
+ Kitchen::SSH.stubs(:new).yields(connection)
409
+ connection.stubs(:exec).raises(Net::SSH::Exception.new("dang"))
410
+
411
+ proc { cmd }.must_raise Kitchen::ActionFailed
412
+ end
413
+ end
414
+
415
+ describe "#setup" do
416
+
417
+ let(:cmd) { driver.setup(state) }
418
+ let(:connection) { mock }
419
+
420
+ before do
421
+ state[:hostname] = "fizzy"
422
+ state[:username] = "bork"
423
+ end
424
+
425
+ constructs_an_ssh_object
426
+
427
+ it "doesn't invoke an ssh command if busser#setup_cmd is nil" do
428
+ busser.stubs(:setup_cmd).returns(nil)
429
+ Kitchen::SSH.stubs(:new).yields(connection)
430
+
431
+ cmd
432
+ end
433
+
434
+ it "invokes the busser#setup_cmd over ssh" do
435
+ Kitchen::SSH.stubs(:new).yields(connection)
436
+ connection.expects(:exec).with("setup")
437
+
438
+ cmd
439
+ end
440
+
441
+ it "invokes the busser#setup_cmd with :http_proxy set in config" do
442
+ config[:http_proxy] = "http://proxy"
443
+ Kitchen::SSH.stubs(:new).yields(connection)
444
+ connection.expects(:exec).with("env http_proxy=http://proxy setup")
445
+
446
+ cmd
447
+ end
448
+
449
+ it "invokes the busser#setup_cmd with :https_proxy set in config" do
450
+ config[:https_proxy] = "https://proxy"
451
+ Kitchen::SSH.stubs(:new).yields(connection)
452
+ connection.expects(:exec).with("env https_proxy=https://proxy setup")
453
+
454
+ cmd
455
+ end
456
+
457
+ it "invokes the busser#setup_cmd with :http_proxy & :https_proxy set" do
458
+ config[:http_proxy] = "http://proxy"
459
+ config[:https_proxy] = "https://proxy"
460
+ Kitchen::SSH.stubs(:new).yields(connection)
461
+ connection.expects(:exec).with(
462
+ "env http_proxy=http://proxy https_proxy=https://proxy setup")
463
+
464
+ cmd
465
+ end
466
+
467
+ it "raises an ActionFailed when SSHFailed is raised" do
468
+ Kitchen::SSH.stubs(:new).yields(connection)
469
+ connection.stubs(:exec).raises(Kitchen::SSHFailed.new("dang"))
470
+
471
+ proc { cmd }.must_raise Kitchen::ActionFailed
472
+ end
473
+
474
+ it "raises an ActionFailed when Net::SSH:Exception is raised" do
475
+ Kitchen::SSH.stubs(:new).yields(connection)
476
+ connection.stubs(:exec).raises(Net::SSH::Exception.new("dang"))
477
+
478
+ proc { cmd }.must_raise Kitchen::ActionFailed
479
+ end
480
+ end
481
+
482
+ describe "#verify" do
483
+
484
+ let(:cmd) { driver.verify(state) }
485
+ let(:connection) { mock }
486
+
487
+ before do
488
+ state[:hostname] = "fizzy"
489
+ state[:username] = "bork"
490
+ end
491
+
492
+ constructs_an_ssh_object
493
+
494
+ it "doesn't invoke an ssh command if busser#sync_cmd & #run_cmd are nil" do
495
+ busser.stubs(:sync_cmd).returns(nil)
496
+ busser.stubs(:run_cmd).returns(nil)
497
+ Kitchen::SSH.stubs(:new).yields(connection)
498
+
499
+ cmd
500
+ end
501
+
502
+ it "doesn't invoke an ssh command for busser#sync_cmd if nil" do
503
+ busser.stubs(:sync_cmd).returns(nil)
504
+ Kitchen::SSH.stubs(:new).yields(connection)
505
+ connection.expects(:exec).with("run")
506
+
507
+ cmd
508
+ end
509
+
510
+ it "doesn't invoke an ssh command for busser#run_cmd if nil" do
511
+ busser.stubs(:run_cmd).returns(nil)
512
+ Kitchen::SSH.stubs(:new).yields(connection)
513
+ connection.expects(:exec).with("sync")
514
+
515
+ cmd
516
+ end
517
+
518
+ it "invokes the busser#sync_cmd & #run_cmd over ssh" do
519
+ Kitchen::SSH.stubs(:new).yields(connection)
520
+ connection.expects(:exec).with("sync")
521
+ connection.expects(:exec).with("run")
522
+
523
+ cmd
524
+ end
525
+
526
+ it "invokes the busser#setup_cmd with :http_proxy set in config" do
527
+ busser.stubs(:run_cmd).returns(nil)
528
+ config[:http_proxy] = "http://proxy"
529
+ Kitchen::SSH.stubs(:new).yields(connection)
530
+ connection.expects(:exec).with("env http_proxy=http://proxy sync")
531
+
532
+ cmd
533
+ end
534
+
535
+ it "invokes the busser#setup_cmd with :https_proxy set in config" do
536
+ busser.stubs(:run_cmd).returns(nil)
537
+ config[:https_proxy] = "https://proxy"
538
+ Kitchen::SSH.stubs(:new).yields(connection)
539
+ connection.expects(:exec).with("env https_proxy=https://proxy sync")
540
+
541
+ cmd
542
+ end
543
+
544
+ it "invokes the busser#setup_cmd with :http_proxy & :https_proxy set" do
545
+ busser.stubs(:run_cmd).returns(nil)
546
+ config[:http_proxy] = "http://proxy"
547
+ config[:https_proxy] = "https://proxy"
548
+ Kitchen::SSH.stubs(:new).yields(connection)
549
+ connection.expects(:exec).with(
550
+ "env http_proxy=http://proxy https_proxy=https://proxy sync")
551
+
552
+ cmd
553
+ end
554
+
555
+ it "raises an ActionFailed when SSHFailed is raised" do
556
+ Kitchen::SSH.stubs(:new).yields(connection)
557
+ connection.stubs(:exec).raises(Kitchen::SSHFailed.new("dang"))
558
+
559
+ proc { cmd }.must_raise Kitchen::ActionFailed
560
+ end
561
+
562
+ it "raises an ActionFailed when Net::SSH:Exception is raised" do
563
+ Kitchen::SSH.stubs(:new).yields(connection)
564
+ connection.stubs(:exec).raises(Net::SSH::Exception.new("dang"))
565
+
566
+ proc { cmd }.must_raise Kitchen::ActionFailed
567
+ end
568
+ end
569
+
570
+ describe "#ssh" do
571
+
572
+ let(:cmd) { driver.ssh(["host", "user", { :one => "two" }], "go") }
573
+ let(:connection) { mock }
574
+
575
+ it "creates an SSH object" do
576
+ Kitchen::SSH.expects(:new).with { |hostname, username, opts|
577
+ hostname.must_equal "host"
578
+ username.must_equal "user"
579
+ opts.must_equal(:one => "two")
580
+ }
581
+
582
+ cmd
583
+ end
584
+
585
+ it "invokes the command over ssh" do
586
+ Kitchen::SSH.stubs(:new).yields(connection)
587
+ connection.expects(:exec).with("go")
588
+
589
+ cmd
590
+ end
591
+ end
592
+
593
+ describe "#remote_command" do
594
+
595
+ let(:cmd) { driver.remote_command(state, "shipit") }
596
+ let(:connection) { mock }
597
+
598
+ before do
599
+ state[:hostname] = "fizzy"
600
+ state[:username] = "bork"
601
+ end
602
+
603
+ it "creates an SSH object" do
604
+ Kitchen::SSH.expects(:new).with { |hostname, username, _opts|
605
+ hostname.must_equal "fizzy"
606
+ username.must_equal "bork"
607
+ }
608
+
609
+ cmd
610
+ end
611
+
612
+ it "invokes the command over ssh" do
613
+ Kitchen::SSH.stubs(:new).yields(connection)
614
+ connection.expects(:exec).with("shipit")
615
+
616
+ cmd
617
+ end
618
+ end
619
+
620
+ describe "#wait_for_sshd" do
621
+
622
+ let(:cmd) do
623
+ driver.send(:wait_for_sshd, "host", "user", :one => "two")
624
+ end
625
+
626
+ it "creates an SSH object with merged options" do
627
+ Kitchen::SSH.expects(:new).with { |hostname, username, opts|
628
+ hostname.must_equal "host"
629
+ username.must_equal "user"
630
+ opts.must_equal(:one => "two", :logger => logger)
631
+ }.returns(stub(:wait => true))
632
+
633
+ cmd
634
+ end
635
+
636
+ it "calls wait on the SSH object" do
637
+ ssh = mock
638
+ Kitchen::SSH.stubs(:new).returns(ssh)
639
+ ssh.expects(:wait)
640
+
641
+ cmd
642
+ end
643
+ end
644
+ end