test-kitchen 1.4.2 → 1.5.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +27 -2
  4. data/CHANGELOG.md +40 -1
  5. data/Gemfile.proxy_tests +6 -0
  6. data/features/kitchen_driver_discover_command.feature +6 -0
  7. data/features/kitchen_init_command.feature +5 -3
  8. data/features/step_definitions/gem_steps.rb +12 -4
  9. data/features/step_definitions/git_steps.rb +1 -1
  10. data/features/step_definitions/output_steps.rb +1 -1
  11. data/features/support/env.rb +13 -9
  12. data/lib/kitchen/cli.rb +3 -0
  13. data/lib/kitchen/command/driver_discover.rb +8 -0
  14. data/lib/kitchen/configurable.rb +32 -0
  15. data/lib/kitchen/driver/ssh_base.rb +18 -4
  16. data/lib/kitchen/generator/driver_create.rb +2 -2
  17. data/lib/kitchen/lazy_hash.rb +20 -0
  18. data/lib/kitchen/provisioner/base.rb +16 -1
  19. data/lib/kitchen/provisioner/chef_base.rb +42 -98
  20. data/lib/kitchen/provisioner/chef_solo.rb +6 -4
  21. data/lib/kitchen/provisioner/chef_zero.rb +7 -5
  22. data/lib/kitchen/transport/winrm.rb +36 -2
  23. data/lib/kitchen/verifier/base.rb +18 -1
  24. data/lib/kitchen/verifier/busser.rb +12 -5
  25. data/lib/kitchen/verifier/shell.rb +101 -0
  26. data/lib/kitchen/version.rb +1 -1
  27. data/spec/kitchen/configurable_spec.rb +211 -2
  28. data/spec/kitchen/driver/ssh_base_spec.rb +131 -8
  29. data/spec/kitchen/lazy_hash_spec.rb +27 -0
  30. data/spec/kitchen/provisioner/base_spec.rb +25 -0
  31. data/spec/kitchen/provisioner/chef_base_spec.rb +133 -252
  32. data/spec/kitchen/provisioner/chef_solo_spec.rb +17 -0
  33. data/spec/kitchen/provisioner/chef_zero_spec.rb +14 -2
  34. data/spec/kitchen/provisioner/shell_spec.rb +60 -12
  35. data/spec/kitchen/transport/winrm_spec.rb +50 -0
  36. data/spec/kitchen/verifier/base_spec.rb +26 -0
  37. data/spec/kitchen/verifier/busser_spec.rb +69 -3
  38. data/spec/kitchen/verifier/shell_spec.rb +157 -0
  39. data/support/busser_install_command.sh +1 -2
  40. data/test-kitchen.gemspec +10 -2
  41. metadata +86 -6
@@ -296,6 +296,23 @@ describe Kitchen::Provisioner::ChefSolo do
296
296
 
297
297
  let(:cmd) { provisioner.run_command }
298
298
 
299
+ describe "common behavior" do
300
+
301
+ before { platform.stubs(:shell_type).returns("fake") }
302
+
303
+ it "prefixs the whole command with the command_prefix if set" do
304
+ config[:command_prefix] = "my_prefix"
305
+
306
+ cmd.must_match(/\Amy_prefix /)
307
+ end
308
+
309
+ it "does not prefix the command if command_prefix is not set" do
310
+ config[:command_prefix] = nil
311
+
312
+ cmd.wont_match(/\Amy_prefix /)
313
+ end
314
+ end
315
+
299
316
  describe "for bourne shells" do
300
317
 
301
318
  before { platform.stubs(:shell_type).returns("bourne") }
@@ -588,8 +588,8 @@ describe Kitchen::Provisioner::ChefZero do
588
588
  " --config #{custom_base}client.rb", :partial_line)
589
589
  end
590
590
 
591
- it "sets log level flag on chef-client to auto by default" do
592
- cmd.must_match regexify(" --log_level auto", :partial_line)
591
+ it "sets log level flag on chef-client to warn by default" do
592
+ cmd.must_match regexify(" --log_level warn", :partial_line)
593
593
  end
594
594
 
595
595
  it "set log level flag for custom level" do
@@ -634,6 +634,18 @@ describe Kitchen::Provisioner::ChefZero do
634
634
  it "does not set logfile flag by default" do
635
635
  cmd.wont_match regexify(" --logfile ", :partial_line)
636
636
  end
637
+
638
+ it "prefixs the whole command with the command_prefix if set" do
639
+ config[:command_prefix] = "my_prefix"
640
+
641
+ cmd.must_match(/\Amy_prefix /)
642
+ end
643
+
644
+ it "does not prefix the command if command_prefix is not set" do
645
+ config[:command_prefix] = nil
646
+
647
+ cmd.wont_match(/\Amy_prefix /)
648
+ end
637
649
  end
638
650
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
639
651
 
@@ -119,15 +119,27 @@ describe Kitchen::Provisioner::Shell do
119
119
  ])
120
120
  end
121
121
 
122
- it "exports all http proxy variables when both are set" do
122
+ it "exports ftp_proxy & FTP_PROXY when :ftp_proxy is set" do
123
+ config[:ftp_proxy] = "ftp://proxy"
124
+
125
+ cmd.lines.to_a[1..2].must_equal([
126
+ %{ftp_proxy="ftp://proxy"; export ftp_proxy\n},
127
+ %{FTP_PROXY="ftp://proxy"; export FTP_PROXY\n}
128
+ ])
129
+ end
130
+
131
+ it "exports all proxy variables when all are set" do
123
132
  config[:http_proxy] = "http://proxy"
124
133
  config[:https_proxy] = "https://proxy"
134
+ config[:ftp_proxy] = "ftp://proxy"
125
135
 
126
- cmd.lines.to_a[1..4].must_equal([
136
+ cmd.lines.to_a[1..6].must_equal([
127
137
  %{http_proxy="http://proxy"; export http_proxy\n},
128
138
  %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
129
139
  %{https_proxy="https://proxy"; export https_proxy\n},
130
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
140
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n},
141
+ %{ftp_proxy="ftp://proxy"; export ftp_proxy\n},
142
+ %{FTP_PROXY="ftp://proxy"; export FTP_PROXY\n}
131
143
  ])
132
144
  end
133
145
 
@@ -184,15 +196,27 @@ describe Kitchen::Provisioner::Shell do
184
196
  ])
185
197
  end
186
198
 
187
- it "exports all http proxy variables when both are set" do
199
+ it "exports ftp_proxy & FTP_PROXY when :ftp_proxy is set" do
200
+ config[:ftp_proxy] = "ftp://proxy"
201
+
202
+ cmd.lines.to_a[0..1].must_equal([
203
+ %{$env:ftp_proxy = "ftp://proxy"\n},
204
+ %{$env:FTP_PROXY = "ftp://proxy"\n}
205
+ ])
206
+ end
207
+
208
+ it "exports all proxy variables when all are set" do
188
209
  config[:http_proxy] = "http://proxy"
189
210
  config[:https_proxy] = "https://proxy"
211
+ config[:ftp_proxy] = "ftp://proxy"
190
212
 
191
- cmd.lines.to_a[0..3].must_equal([
213
+ cmd.lines.to_a[0..5].must_equal([
192
214
  %{$env:http_proxy = "http://proxy"\n},
193
215
  %{$env:HTTP_PROXY = "http://proxy"\n},
194
216
  %{$env:https_proxy = "https://proxy"\n},
195
- %{$env:HTTPS_PROXY = "https://proxy"\n}
217
+ %{$env:HTTPS_PROXY = "https://proxy"\n},
218
+ %{$env:ftp_proxy = "ftp://proxy"\n},
219
+ %{$env:FTP_PROXY = "ftp://proxy"\n}
196
220
  ])
197
221
  end
198
222
 
@@ -253,15 +277,27 @@ describe Kitchen::Provisioner::Shell do
253
277
  ])
254
278
  end
255
279
 
256
- it "exports all http proxy variables when both are set" do
280
+ it "exports ftp_proxy & FTP_PROXY when :ftp_proxy is set" do
281
+ config[:ftp_proxy] = "ftp://proxy"
282
+
283
+ cmd.lines.to_a[1..2].must_equal([
284
+ %{ftp_proxy="ftp://proxy"; export ftp_proxy\n},
285
+ %{FTP_PROXY="ftp://proxy"; export FTP_PROXY\n}
286
+ ])
287
+ end
288
+
289
+ it "exports all proxy variables when all are set" do
257
290
  config[:http_proxy] = "http://proxy"
258
291
  config[:https_proxy] = "https://proxy"
292
+ config[:ftp_proxy] = "ftp://proxy"
259
293
 
260
- cmd.lines.to_a[1..4].must_equal([
294
+ cmd.lines.to_a[1..6].must_equal([
261
295
  %{http_proxy="http://proxy"; export http_proxy\n},
262
296
  %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
263
297
  %{https_proxy="https://proxy"; export https_proxy\n},
264
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
298
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n},
299
+ %{ftp_proxy="ftp://proxy"; export ftp_proxy\n},
300
+ %{FTP_PROXY="ftp://proxy"; export FTP_PROXY\n}
265
301
  ])
266
302
  end
267
303
 
@@ -306,15 +342,27 @@ describe Kitchen::Provisioner::Shell do
306
342
  ])
307
343
  end
308
344
 
309
- it "exports all http proxy variables when both are set" do
345
+ it "exports ftp_proxy & FTP_PROXY when :ftp_proxy is set" do
346
+ config[:ftp_proxy] = "ftp://proxy"
347
+
348
+ cmd.lines.to_a[0..1].must_equal([
349
+ %{$env:ftp_proxy = "ftp://proxy"\n},
350
+ %{$env:FTP_PROXY = "ftp://proxy"\n}
351
+ ])
352
+ end
353
+
354
+ it "exports all proxy variables when all are set" do
310
355
  config[:http_proxy] = "http://proxy"
311
356
  config[:https_proxy] = "https://proxy"
357
+ config[:ftp_proxy] = "ftp://proxy"
312
358
 
313
- cmd.lines.to_a[0..3].must_equal([
359
+ cmd.lines.to_a[0..5].must_equal([
314
360
  %{$env:http_proxy = "http://proxy"\n},
315
361
  %{$env:HTTP_PROXY = "http://proxy"\n},
316
362
  %{$env:https_proxy = "https://proxy"\n},
317
- %{$env:HTTPS_PROXY = "https://proxy"\n}
363
+ %{$env:HTTPS_PROXY = "https://proxy"\n},
364
+ %{$env:ftp_proxy = "ftp://proxy"\n},
365
+ %{$env:FTP_PROXY = "ftp://proxy"\n}
318
366
  ])
319
367
  end
320
368
 
@@ -24,6 +24,23 @@ require "winrm/transport/command_executor"
24
24
  require "winrm/transport/shell_closer"
25
25
  require "winrm/transport/file_transporter"
26
26
 
27
+ module Kitchen
28
+
29
+ module Transport
30
+
31
+ class WinRMConnectionDummy < Kitchen::Transport::Winrm::Connection
32
+
33
+ attr_reader :saved_command, :remote_path, :local_path
34
+
35
+ def upload(locals, remote)
36
+ @saved_command = IO.read(locals)
37
+ @local_path = locals
38
+ @remote_path = remote
39
+ end
40
+ end
41
+ end
42
+ end
43
+
27
44
  describe Kitchen::Transport::Winrm do
28
45
 
29
46
  let(:logged_output) { StringIO.new }
@@ -576,6 +593,39 @@ describe Kitchen::Transport::Winrm::Connection do
576
593
  end
577
594
  end
578
595
 
596
+ describe "long command" do
597
+ let(:command) { %{Write-Host "#{"a" * 4000}"} }
598
+
599
+ let(:connection) do
600
+ Kitchen::Transport::WinRMConnectionDummy.new(options)
601
+ end
602
+
603
+ let(:response) do
604
+ o = WinRM::Output.new
605
+ o[:exitcode] = 0
606
+ o[:data].concat([
607
+ { :stdout => "ok\r\n" },
608
+ { :stderr => "congrats\r\n" }
609
+ ])
610
+ o
611
+ end
612
+
613
+ before do
614
+ executor.expects(:open).returns("shell-123")
615
+ executor.expects(:run_powershell_script).
616
+ with(%{& "$env:TEMP/kitchen/coolbeans-long_script.ps1"}).
617
+ yields("ok\n", nil).returns(response)
618
+ end
619
+
620
+ it "uploads the long command" do
621
+ with_fake_fs do
622
+ connection.execute(command)
623
+
624
+ connection.saved_command.must_equal command
625
+ end
626
+ end
627
+ end
628
+
579
629
  describe "for a failed command" do
580
630
 
581
631
  let(:response) do
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
 
19
19
  require_relative "../../spec_helper"
20
+ require_relative "../ssh_spec"
20
21
 
21
22
  require "logger"
22
23
  require "stringio"
@@ -139,6 +140,10 @@ describe Kitchen::Verifier::Base do
139
140
  it ":http_proxys defaults to nil" do
140
141
  verifier[:https_proxy].must_equal nil
141
142
  end
143
+
144
+ it ":ftp_proxy defaults to nil" do
145
+ verifier[:ftp_proxy].must_equal nil
146
+ end
142
147
  end
143
148
 
144
149
  describe "#call" do
@@ -333,4 +338,25 @@ describe Kitchen::Verifier::Base do
333
338
  end
334
339
  end
335
340
  end
341
+
342
+ describe "#prefix_command" do
343
+
344
+ describe "with :command_prefix set" do
345
+
346
+ before { config[:command_prefix] = "my_prefix" }
347
+
348
+ it "prepends the command with the prefix" do
349
+ verifier.send(:prefix_command, "my_command").must_equal("my_prefix my_command")
350
+ end
351
+ end
352
+
353
+ describe "with :command_prefix unset" do
354
+
355
+ before { config[:command_prefix] = nil }
356
+
357
+ it "returns an unaltered command" do
358
+ verifier.send(:prefix_command, "my_command").must_equal("my_command")
359
+ end
360
+ end
361
+ end
336
362
  end
@@ -101,7 +101,9 @@ describe Kitchen::Verifier::Busser do
101
101
 
102
102
  describe "for unix operating systems" do
103
103
 
104
- before { platform.stubs(:os_type).returns("unix") }
104
+ before {
105
+ platform.stubs(:os_type).returns("unix")
106
+ }
105
107
 
106
108
  it ":ruby_bindir defaults the an Omnibus Chef installation" do
107
109
  verifier[:ruby_bindir].must_equal "/opt/chef/embedded/bin"
@@ -210,6 +212,26 @@ describe Kitchen::Verifier::Busser do
210
212
 
211
213
  describe "with suite test files" do
212
214
 
215
+ describe "common behavior" do
216
+
217
+ before do
218
+ platform.stubs(:shell_type).returns("fake")
219
+ create_test_files
220
+ end
221
+
222
+ it "prefixs the whole command with the command_prefix if set" do
223
+ config[:command_prefix] = "my_prefix"
224
+
225
+ cmd.must_match(/\Amy_prefix /)
226
+ end
227
+
228
+ it "does not prefix the command if command_prefix is not set" do
229
+ config[:command_prefix] = nil
230
+
231
+ cmd.wont_match(/\Amy_prefix /)
232
+ end
233
+ end
234
+
213
235
  describe "for bourne shells" do
214
236
 
215
237
  before do
@@ -237,7 +259,9 @@ describe Kitchen::Verifier::Busser do
237
259
 
238
260
  it "sets gem install arguments" do
239
261
  cmd.must_match regexify(
240
- %{gem_install_args="busser --no-rdoc --no-ri"})
262
+ "gem_install_args=\"busser --no-rdoc --no-ri --no-format-executable" \
263
+ " -n /r/bin --no-user-install\""
264
+ )
241
265
  end
242
266
 
243
267
  it "prepends sudo for busser binstub command when :sudo is set" do
@@ -284,7 +308,9 @@ describe Kitchen::Verifier::Busser do
284
308
 
285
309
  it "sets gem install arguments" do
286
310
  cmd.must_match regexify(
287
- %{$gem_install_args = "busser --no-rdoc --no-ri"})
311
+ "$gem_install_args = \"busser --no-rdoc --no-ri --no-format-executable" \
312
+ " -n \\r\\bin --no-user-install\""
313
+ )
288
314
  end
289
315
 
290
316
  it "sets path to busser binstub command" do
@@ -329,6 +355,26 @@ describe Kitchen::Verifier::Busser do
329
355
 
330
356
  describe "with suite test files" do
331
357
 
358
+ describe "common behavior" do
359
+
360
+ before do
361
+ platform.stubs(:shell_type).returns("fake")
362
+ create_test_files
363
+ end
364
+
365
+ it "prefixs the whole command with the command_prefix if set" do
366
+ config[:command_prefix] = "my_prefix"
367
+
368
+ cmd.must_match(/\Amy_prefix /)
369
+ end
370
+
371
+ it "does not prefix the command if command_prefix is not set" do
372
+ config[:command_prefix] = nil
373
+
374
+ cmd.wont_match(/\Amy_prefix /)
375
+ end
376
+ end
377
+
332
378
  describe "for bourne shells" do
333
379
 
334
380
  before do
@@ -407,6 +453,26 @@ describe Kitchen::Verifier::Busser do
407
453
 
408
454
  describe "with suite test files" do
409
455
 
456
+ describe "common behavior" do
457
+
458
+ before do
459
+ platform.stubs(:shell_type).returns("fake")
460
+ create_test_files
461
+ end
462
+
463
+ it "prefixs the whole command with the command_prefix if set" do
464
+ config[:command_prefix] = "my_prefix"
465
+
466
+ cmd.must_match(/\Amy_prefix /)
467
+ end
468
+
469
+ it "does not prefix the command if command_prefix is not set" do
470
+ config[:command_prefix] = nil
471
+
472
+ cmd.wont_match(/\Amy_prefix /)
473
+ end
474
+ end
475
+
410
476
  describe "for bourne shells" do
411
477
 
412
478
  before do
@@ -0,0 +1,157 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
4
+ #
5
+ # Copyright (C) 2015, HiganWorks LLC
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 "logger"
22
+ require "stringio"
23
+
24
+ require "kitchen/verifier/shell"
25
+
26
+ describe Kitchen::Verifier::Shell do
27
+
28
+ let(:logged_output) { StringIO.new }
29
+ let(:logger) { Logger.new(logged_output) }
30
+ let(:platform) { stub(:os_type => nil, :shell_type => nil, :name => "coolbeans") }
31
+ let(:suite) { stub(:name => "fries") }
32
+ let(:state) { Hash.new }
33
+
34
+ let(:config) do
35
+ { :test_base_path => "/basist", :kitchen_root => "/rooty" }
36
+ end
37
+
38
+ let(:instance) do
39
+ stub(
40
+ :name => [platform.name, suite.name].join("-"),
41
+ :to_str => "instance",
42
+ :logger => logger,
43
+ :suite => suite,
44
+ :platform => platform
45
+ )
46
+ end
47
+
48
+ let(:verifier) do
49
+ Kitchen::Verifier::Shell.new(config).finalize_config!(instance)
50
+ end
51
+
52
+ it "verifier api_version is 1" do
53
+ verifier.diagnose_plugin[:api_version].must_equal 1
54
+ end
55
+
56
+ it "plugin_version is set to Kitchen::VERSION" do
57
+ verifier.diagnose_plugin[:version].must_equal Kitchen::VERSION
58
+ end
59
+
60
+ describe "configuration" do
61
+
62
+ it "sets :sleep to 0 by default" do
63
+ verifier[:sleep].must_equal 0
64
+ end
65
+
66
+ it "sets :command to 'true' by default" do
67
+ verifier[:command].must_equal "true"
68
+ end
69
+
70
+ it "sets :live_stream to stdout by default" do
71
+ verifier[:live_stream].must_equal $stdout
72
+ end
73
+ end
74
+
75
+ describe "#call" do
76
+
77
+ describe "#shell_out" do
78
+ it "calls sleep if :sleep value is greater than 0" do
79
+ config[:sleep] = 3
80
+ verifier.expects(:sleep).with(1).returns(true).at_least(3)
81
+
82
+ verifier.call(state)
83
+ end
84
+
85
+ it "states are set to environment" do
86
+ state[:hostname] = "testhost"
87
+ state[:server_id] = "i-xxxxxx"
88
+ verifier.call(state)
89
+ config[:shellout_opts][:environment]["KITCHEN_HOSTNAME"].must_equal "testhost"
90
+ config[:shellout_opts][:environment]["KITCHEN_SERVER_ID"].must_equal "i-xxxxxx"
91
+ config[:shellout_opts][:environment]["KITCHEN_INSTANCE"].must_equal "coolbeans-fries"
92
+ config[:shellout_opts][:environment]["KITCHEN_PLATFORM"].must_equal "coolbeans"
93
+ config[:shellout_opts][:environment]["KITCHEN_SUITE"].must_equal "fries"
94
+ end
95
+
96
+ it "raises ActionFailed if set false to :command" do
97
+ config[:command] = "false"
98
+
99
+ proc { verifier.call(state) }.must_raise Kitchen::ActionFailed
100
+ end
101
+
102
+ it "logs a converge event to INFO" do
103
+ verifier.call(state)
104
+
105
+ logged_output.string.must_match(/^.+ INFO .+ \[Shell\] Verify on .+$/)
106
+ end
107
+ end
108
+
109
+ describe "remote_exec" do
110
+ let(:transport) do
111
+ t = mock("transport")
112
+ t.responds_like_instance_of(Kitchen::Transport::Ssh)
113
+ t
114
+ end
115
+
116
+ let(:connection) do
117
+ c = mock("transport_connection")
118
+ c.responds_like_instance_of(Kitchen::Transport::Ssh::Connection)
119
+ c
120
+ end
121
+
122
+ let(:instance) do
123
+ stub(
124
+ :name => "coolbeans",
125
+ :to_str => "instance",
126
+ :logger => logger,
127
+ :platform => platform,
128
+ :suite => suite,
129
+ :transport => transport
130
+ )
131
+ end
132
+
133
+ before do
134
+ transport.stubs(:connection).yields(connection)
135
+ connection.stubs(:execute)
136
+ end
137
+
138
+ it "execute command onto instance." do
139
+ config[:remote_exec] = true
140
+
141
+ transport.expects(:connection).with(state).yields(connection)
142
+ verifier.call(state)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#run_command" do
148
+ it "execute localy and returns nil" do
149
+ verifier.run_command
150
+ end
151
+
152
+ it "returns string when remote_exec" do
153
+ config[:remote_exec] = true
154
+ verifier.run_command.must_equal "true"
155
+ end
156
+ end
157
+ end