test-kitchen 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
@@ -1,1419 +1,1419 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2012, 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
- require "stringio"
21
-
22
- require "kitchen/logging"
23
- require "kitchen/instance"
24
- require "kitchen/driver"
25
- require "kitchen/driver/dummy"
26
- require "kitchen/platform"
27
- require "kitchen/provisioner"
28
- require "kitchen/provisioner/dummy"
29
- require "kitchen/suite"
30
- require "kitchen/transport/dummy"
31
- require "kitchen/verifier/dummy"
32
-
33
- class DummyStateFile
34
-
35
- def initialize(*); end
36
-
37
- def read
38
- @_state = Hash.new unless @_state
39
- @_state.dup
40
- end
41
-
42
- def write(state)
43
- @_state = state.dup
44
- end
45
-
46
- def destroy
47
- @_state = nil
48
- end
49
-
50
- def diagnose
51
- Hash.new
52
- end
53
- end
54
-
55
- class SerialDummyDriver < Kitchen::Driver::Dummy
56
-
57
- no_parallel_for :create, :destroy
58
-
59
- attr_reader :action_in_mutex
60
-
61
- def track_locked(action)
62
- @action_in_mutex = Hash.new unless @action_in_mutex
63
- @action_in_mutex[action] = Kitchen::Instance.mutexes[self.class].locked?
64
- end
65
-
66
- def create(state)
67
- track_locked(:create)
68
- super
69
- end
70
-
71
- def destroy(state)
72
- track_locked(:destroy)
73
- super
74
- end
75
- end
76
-
77
- class LegacyDriver < Kitchen::Driver::SSHBase
78
-
79
- attr_reader :called_converge, :called_setup, :called_verify
80
-
81
- def converge(_)
82
- @called_converge
83
- end
84
-
85
- def setup(_)
86
- @called_setup
87
- end
88
-
89
- def verify(_)
90
- @called_verify
91
- end
92
- end
93
-
94
- describe Kitchen::Instance do
95
-
96
- let(:driver) { Kitchen::Driver::Dummy.new({}) }
97
- let(:logger_io) { StringIO.new }
98
- let(:logger) { Kitchen::Logger.new(:logdev => logger_io) }
99
- let(:instance) { Kitchen::Instance.new(opts) }
100
- let(:provisioner) { Kitchen::Provisioner::Dummy.new({}) }
101
- let(:state_file) { DummyStateFile.new }
102
- let(:transport) { Kitchen::Transport::Dummy.new({}) }
103
- let(:verifier) { Kitchen::Verifier::Dummy.new({}) }
104
-
105
- let(:opts) do
106
- { :suite => suite, :platform => platform, :driver => driver,
107
- :provisioner => provisioner, :verifier => verifier,
108
- :logger => logger, :state_file => state_file, :transport => transport }
109
- end
110
-
111
- def suite(name = "suite")
112
- @suite ||= Kitchen::Suite.new(:name => name)
113
- end
114
-
115
- def platform(name = "platform")
116
- @platform ||= Kitchen::Platform.new(:name => name)
117
- end
118
-
119
- describe ".name_for" do
120
-
121
- it "combines the suite and platform names with a dash" do
122
- Kitchen::Instance.name_for(suite("suite"), platform("platform")).
123
- must_equal "suite-platform"
124
- end
125
-
126
- it "squashes periods in suite name" do
127
- Kitchen::Instance.name_for(suite("suite.ness"), platform("platform")).
128
- must_equal "suiteness-platform"
129
- end
130
-
131
- it "squashes periods in platform name" do
132
- Kitchen::Instance.name_for(suite("suite"), platform("platform.s")).
133
- must_equal "suite-platforms"
134
- end
135
-
136
- it "squashes periods in suite and platform names" do
137
- Kitchen::Instance.name_for(suite("s.s"), platform("p.p")).
138
- must_equal "ss-pp"
139
- end
140
-
141
- it "transforms underscores to dashes in suite name" do
142
- Kitchen::Instance.name_for(suite("suite_ness"), platform("platform")).
143
- must_equal "suite-ness-platform"
144
- end
145
-
146
- it "transforms underscores to dashes in platform name" do
147
- Kitchen::Instance.name_for(suite("suite"), platform("platform_s")).
148
- must_equal "suite-platform-s"
149
- end
150
-
151
- it "transforms underscores to dashes in suite and platform names" do
152
- Kitchen::Instance.name_for(suite("_s__s_"), platform("pp_")).
153
- must_equal "-s--s--pp-"
154
- end
155
-
156
- it "transforms forward slashes to dashes in suite name" do
157
- Kitchen::Instance.name_for(suite("suite/ness"), platform("platform")).
158
- must_equal "suite-ness-platform"
159
- end
160
-
161
- it "transforms forward slashes to dashes in platform name" do
162
- Kitchen::Instance.name_for(suite("suite"), platform("platform/s")).
163
- must_equal "suite-platform-s"
164
- end
165
-
166
- it "transforms forward slashes to dashes in suite and platform names" do
167
- Kitchen::Instance.name_for(suite("/s//s/"), platform("pp/")).
168
- must_equal "-s--s--pp-"
169
- end
170
- end
171
-
172
- describe "#suite" do
173
-
174
- it "returns its suite" do
175
- instance.suite.must_equal suite
176
- end
177
-
178
- it "raises an ArgumentError if missing" do
179
- opts.delete(:suite)
180
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
181
- end
182
- end
183
-
184
- describe "#platform" do
185
-
186
- it "returns its platform" do
187
- instance.platform.must_equal platform
188
- end
189
-
190
- it "raises an ArgumentError if missing" do
191
- opts.delete(:platform)
192
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
193
- end
194
- end
195
-
196
- describe "#driver" do
197
-
198
- it "returns its driver" do
199
- instance.driver.must_equal driver
200
- end
201
-
202
- it "raises an ArgumentError if missing" do
203
- opts.delete(:driver)
204
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
205
- end
206
-
207
- it "sets Driver#instance to itself" do
208
- # it's mind-bottling
209
- instance.driver.instance.must_equal instance
210
- end
211
- end
212
-
213
- describe "#logger" do
214
-
215
- it "returns its logger" do
216
- instance.logger.must_equal logger
217
- end
218
-
219
- it "uses Kitchen.logger by default" do
220
- opts.delete(:logger)
221
- instance.logger.must_equal Kitchen.logger
222
- end
223
- end
224
-
225
- describe "#provisioner" do
226
-
227
- it "returns its provisioner" do
228
- instance.provisioner.must_equal provisioner
229
- end
230
-
231
- it "raises an ArgumentError if missing" do
232
- opts.delete(:provisioner)
233
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
234
- end
235
-
236
- it "sets Provisioner#instance to itself" do
237
- # it's mind-bottling
238
- instance.provisioner.instance.must_equal instance
239
- end
240
- end
241
-
242
- describe "#transport" do
243
-
244
- it "returns its transport" do
245
- instance.transport.must_equal transport
246
- end
247
-
248
- it "raises an ArgumentError if missing" do
249
- opts.delete(:transport)
250
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
251
- end
252
-
253
- it "sets Transport#instance to itself" do
254
- # it's mind-bottling
255
- instance.transport.instance.must_equal instance
256
- end
257
- end
258
-
259
- describe "#verifier" do
260
-
261
- it "returns its verifier" do
262
- instance.verifier.must_equal verifier
263
- end
264
-
265
- it "raises and ArgumentError if missing" do
266
- opts.delete(:verifier)
267
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
268
- end
269
-
270
- it "sets Verifier#instance to itself" do
271
- # it's mind-bottling
272
- instance.verifier.instance.must_equal instance
273
- end
274
- end
275
-
276
- describe "#state_file" do
277
-
278
- it "raises an ArgumentError if missing" do
279
- opts.delete(:state_file)
280
- proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
281
- end
282
- end
283
-
284
- it "#name returns it name" do
285
- instance.name.must_equal "suite-platform"
286
- end
287
-
288
- it "#to_str returns a string representation with its name" do
289
- instance.to_str.must_equal "<suite-platform>"
290
- end
291
-
292
- it "#login executes the transport's login_command" do
293
- conn = stub("connection")
294
- state_file.write(:last_action => "create")
295
- transport.stubs(:connection).with(:last_action => "create").
296
- returns(conn)
297
- conn.stubs(:login_command).
298
- returns(Kitchen::LoginCommand.new("echo", ["hello"], :purple => true))
299
- Kernel.expects(:exec).with("echo", "hello", :purple => true)
300
-
301
- instance.login
302
- end
303
-
304
- it "#login raises a UserError if the instance is not created" do
305
- state_file.write({})
306
-
307
- proc { instance.login }.must_raise Kitchen::UserError
308
- end
309
-
310
- describe "#diagnose" do
311
-
312
- it "returns a hash" do
313
- instance.diagnose.must_be_instance_of Hash
314
- end
315
-
316
- it "sets :platform key to platform's diagnose info" do
317
- platform.stubs(:diagnose).returns(:a => "b")
318
-
319
- instance.diagnose[:platform].must_equal(:a => "b")
320
- end
321
-
322
- it "sets :platform key to :unknown if obj can't respond to #diagnose" do
323
- opts[:platform] = Class.new(platform.class) {
324
- undef_method :diagnose
325
- }.new(:name => "whoop")
326
-
327
- instance.diagnose[:platform].must_equal :unknown
328
- end
329
-
330
- it "sets :state_file key to state_file's diganose info" do
331
- state_file.stubs(:diagnose).returns(:a => "b")
332
-
333
- instance.diagnose[:state_file].must_equal(:a => "b")
334
- end
335
-
336
- it "sets :state_file key to :unknown if obj can't respond to #diagnose" do
337
- opts[:state_file] = Class.new(state_file.class) {
338
- undef_method :diagnose
339
- }.new
340
-
341
- instance.diagnose[:state_file].must_equal :unknown
342
- end
343
-
344
- it "sets :provisioner key to provisioner's diganose info" do
345
- provisioner.stubs(:diagnose).returns(:a => "b")
346
-
347
- instance.diagnose[:provisioner].must_equal(:a => "b")
348
- end
349
-
350
- it "sets :provisioner key to :unknown if obj can't respond to #diagnose" do
351
- opts[:provisioner] = Class.new(provisioner.class) {
352
- undef_method :diagnose
353
- }.new
354
-
355
- instance.diagnose[:provisioner].must_equal :unknown
356
- end
357
-
358
- it "sets :verifier key to verifier's diganose info" do
359
- verifier.stubs(:diagnose).returns(:a => "b")
360
-
361
- instance.diagnose[:verifier].must_equal(:a => "b")
362
- end
363
-
364
- it "sets :verifier key to :unknown if obj can't respond to #diagnose" do
365
- opts[:verifier] = Class.new(verifier.class) {
366
- undef_method :diagnose
367
- }.new({})
368
-
369
- instance.diagnose[:verifier].must_equal :unknown
370
- end
371
-
372
- it "sets :transport key to transport's diganose info" do
373
- transport.stubs(:diagnose).returns(:a => "b")
374
-
375
- instance.diagnose[:transport].must_equal(:a => "b")
376
- end
377
-
378
- it "sets :transport key to :unknown if obj can't respond to #diagnose" do
379
- opts[:transport] = Class.new(transport.class) {
380
- undef_method :diagnose
381
- }.new
382
-
383
- instance.diagnose[:transport].must_equal :unknown
384
- end
385
- end
386
-
387
- describe "#diagnose_plugins" do
388
-
389
- it "returns a hash" do
390
- instance.diagnose_plugins.must_be_instance_of Hash
391
- end
392
-
393
- it "sets :driver key to driver's plugin_diagnose info" do
394
- driver.class.stubs(:diagnose).returns(:a => "b")
395
-
396
- instance.diagnose_plugins[:driver].must_equal(
397
- :name => "Dummy",
398
- :a => "b"
399
- )
400
- end
401
-
402
- it "sets :driver key to :unknown if class doesn't have #diagnose" do
403
- opts[:driver] = Class.new(driver.class) {
404
- undef_method :diagnose_plugin
405
- }.new({})
406
-
407
- instance.diagnose_plugins[:driver].must_equal(:unknown)
408
- end
409
-
410
- it "sets :provisioner key to provisioner's plugin_diagnose info" do
411
- provisioner.class.stubs(:diagnose).returns(:a => "b")
412
-
413
- instance.diagnose_plugins[:provisioner].must_equal(
414
- :name => "Dummy",
415
- :a => "b"
416
- )
417
- end
418
-
419
- it "sets :provisioner key to :unknown if class doesn't have #diagnose" do
420
- opts[:provisioner] = Class.new(driver.class) {
421
- undef_method :diagnose_plugin
422
- }.new({})
423
-
424
- instance.diagnose_plugins[:provisioner].must_equal(:unknown)
425
- end
426
-
427
- it "sets :verifier key to verifier's plugin_diagnose info" do
428
- verifier.class.stubs(:diagnose).returns(:a => "b")
429
-
430
- instance.diagnose_plugins[:verifier].must_equal(
431
- :name => "Dummy",
432
- :a => "b"
433
- )
434
- end
435
-
436
- it "sets :verifier key to :unknown if class doesn't have #diagnose" do
437
- opts[:verifier] = Class.new(verifier.class) {
438
- undef_method :diagnose_plugin
439
- }.new({})
440
-
441
- instance.diagnose_plugins[:verifier].must_equal(:unknown)
442
- end
443
-
444
- it "sets :transport key to transport's plugin_diagnose info" do
445
- transport.class.stubs(:diagnose).returns(:a => "b")
446
-
447
- instance.diagnose_plugins[:transport].must_equal(
448
- :name => "Dummy",
449
- :a => "b"
450
- )
451
- end
452
-
453
- it "sets :transport key to :unknown if class doesn't have #diagnose" do
454
- opts[:transport] = Class.new(transport.class) {
455
- undef_method :diagnose_plugin
456
- }.new({})
457
-
458
- instance.diagnose_plugins[:transport].must_equal(:unknown)
459
- end
460
- end
461
-
462
- describe "performing actions" do
463
-
464
- describe "#create" do
465
-
466
- describe "with no state" do
467
-
468
- it "calls Driver#create with empty state hash" do
469
- driver.expects(:create).with(Hash.new)
470
-
471
- instance.create
472
- end
473
-
474
- it "writes the state file with last_action" do
475
- instance.create
476
-
477
- state_file.read[:last_action].must_equal "create"
478
- end
479
-
480
- it "logs the action start" do
481
- instance.create
482
-
483
- logger_io.string.must_match regex_for("Creating #{instance.to_str}")
484
- end
485
-
486
- it "logs the action finish" do
487
- instance.create
488
-
489
- logger_io.string.
490
- must_match regex_for("Finished creating #{instance.to_str}")
491
- end
492
-
493
- end
494
-
495
- describe "with last_action of create" do
496
-
497
- before { state_file.write(:last_action => "create") }
498
-
499
- it "calls Driver#create with state hash" do
500
- driver.expects(:create).
501
- with { |state| state[:last_action] == "create" }
502
-
503
- instance.create
504
- end
505
-
506
- it "writes the state file with last_action" do
507
- instance.create
508
-
509
- state_file.read[:last_action].must_equal "create"
510
- end
511
- end
512
- end
513
-
514
- describe "#converge" do
515
-
516
- describe "with no state" do
517
-
518
- it "calls Driver#create and Provisioner#call with empty state hash" do
519
- driver.expects(:create).with(Hash.new)
520
- provisioner.expects(:call).
521
- with { |state| state[:last_action] == "create" }
522
-
523
- instance.converge
524
- end
525
-
526
- it "writes the state file with last_action" do
527
- instance.converge
528
-
529
- state_file.read[:last_action].must_equal "converge"
530
- end
531
-
532
- it "logs the action start" do
533
- instance.converge
534
-
535
- logger_io.string.must_match regex_for("Converging #{instance.to_str}")
536
- end
537
-
538
- it "logs the action finish" do
539
- instance.converge
540
-
541
- logger_io.string.
542
- must_match regex_for("Finished converging #{instance.to_str}")
543
- end
544
- end
545
-
546
- describe "with last action of create" do
547
-
548
- before { state_file.write(:last_action => "create") }
549
-
550
- it "calls Provisioner#call with state hash" do
551
- provisioner.expects(:call).
552
- with { |state| state[:last_action] == "create" }
553
-
554
- instance.converge
555
- end
556
-
557
- it "writes the state file with last_action" do
558
- instance.converge
559
-
560
- state_file.read[:last_action].must_equal "converge"
561
- end
562
- end
563
-
564
- describe "with last action of converge" do
565
-
566
- before { state_file.write(:last_action => "converge") }
567
-
568
- it "calls Provisioner#call with state hash" do
569
- provisioner.expects(:call).
570
- with { |state| state[:last_action] == "converge" }
571
-
572
- instance.converge
573
- end
574
-
575
- it "writes the state file with last_action" do
576
- instance.converge
577
-
578
- state_file.read[:last_action].must_equal "converge"
579
- end
580
- end
581
- end
582
-
583
- describe "#setup" do
584
-
585
- describe "with no state" do
586
-
587
- it "calls create and converge with empty state hash" do
588
- driver.expects(:create).with(Hash.new)
589
- provisioner.expects(:call).
590
- with { |state| state[:last_action] == "create" }
591
- driver.expects(:setup).
592
- with { |state| state[:last_action] == "converge" }.
593
- never
594
-
595
- instance.setup
596
- end
597
-
598
- it "writes the state file with last_action" do
599
- instance.setup
600
-
601
- state_file.read[:last_action].must_equal "setup"
602
- end
603
-
604
- it "logs the action start" do
605
- instance.setup
606
-
607
- logger_io.string.must_match regex_for("Setting up #{instance.to_str}")
608
- end
609
-
610
- it "logs the action finish" do
611
- instance.setup
612
-
613
- logger_io.string.
614
- must_match regex_for("Finished setting up #{instance.to_str}")
615
- end
616
- end
617
-
618
- describe "with last action of create" do
619
-
620
- before { state_file.write(:last_action => "create") }
621
-
622
- it "calls Provisioner#call with state hash" do
623
- provisioner.expects(:call).
624
- with { |state| state[:last_action] == "create" }
625
- driver.expects(:setup).
626
- with { |state| state[:last_action] == "converge" }.
627
- never
628
-
629
- instance.setup
630
- end
631
-
632
- it "writes the state file with last_action" do
633
- instance.setup
634
-
635
- state_file.read[:last_action].must_equal "setup"
636
- end
637
- end
638
-
639
- describe "with last action of converge" do
640
-
641
- before { state_file.write(:last_action => "converge") }
642
-
643
- it "calls nothing with state hash" do
644
- driver.expects(:setup).
645
- with { |state| state[:last_action] == "converge" }.
646
- never
647
-
648
- instance.setup
649
- end
650
-
651
- it "writes the state file with last_action" do
652
- instance.setup
653
-
654
- state_file.read[:last_action].must_equal "setup"
655
- end
656
- end
657
-
658
- describe "with last action of setup" do
659
-
660
- before { state_file.write(:last_action => "setup") }
661
-
662
- it "calls nothing with state hash" do
663
- driver.expects(:setup).
664
- with { |state| state[:last_action] == "setup" }.
665
- never
666
-
667
- instance.setup
668
- end
669
-
670
- it "writes the state file with last_action" do
671
- instance.setup
672
-
673
- state_file.read[:last_action].must_equal "setup"
674
- end
675
- end
676
- end
677
-
678
- describe "#verify" do
679
-
680
- describe "with no state" do
681
-
682
- it "calls create, converge, and verify with empty state hash" do
683
- driver.expects(:create).with(Hash.new)
684
- provisioner.expects(:call).
685
- with { |state| state[:last_action] == "create" }
686
- driver.expects(:setup).
687
- with { |state| state[:last_action] == "converge" }.
688
- never
689
- verifier.expects(:call).
690
- with { |state| state[:last_action] == "setup" }
691
-
692
- instance.verify
693
- end
694
-
695
- it "writes the state file with last_action" do
696
- instance.verify
697
-
698
- state_file.read[:last_action].must_equal "verify"
699
- end
700
-
701
- it "logs the action start" do
702
- instance.verify
703
-
704
- logger_io.string.must_match regex_for("Verifying #{instance.to_str}")
705
- end
706
-
707
- it "logs the action finish" do
708
- instance.verify
709
-
710
- logger_io.string.
711
- must_match regex_for("Finished verifying #{instance.to_str}")
712
- end
713
- end
714
-
715
- describe "with last of create" do
716
-
717
- before { state_file.write(:last_action => "create") }
718
-
719
- it "calls converge, and verify with state hash" do
720
- provisioner.expects(:call).
721
- with { |state| state[:last_action] == "create" }
722
- driver.expects(:setup).
723
- with { |state| state[:last_action] == "converge" }.
724
- never
725
- verifier.expects(:call).
726
- with { |state| state[:last_action] == "setup" }
727
-
728
- instance.verify
729
- end
730
-
731
- it "writes the state file with last_action" do
732
- instance.verify
733
-
734
- state_file.read[:last_action].must_equal "verify"
735
- end
736
- end
737
-
738
- describe "with last of converge" do
739
-
740
- before { state_file.write(:last_action => "converge") }
741
-
742
- it "calls Verifier#call with state hash" do
743
- driver.expects(:setup).
744
- with { |state| state[:last_action] == "converge" }.
745
- never
746
- verifier.expects(:call).
747
- with { |state| state[:last_action] == "setup" }
748
-
749
- instance.verify
750
- end
751
-
752
- it "writes the state file with last_action" do
753
- instance.verify
754
-
755
- state_file.read[:last_action].must_equal "verify"
756
- end
757
- end
758
-
759
- describe "with last of setup" do
760
-
761
- before { state_file.write(:last_action => "setup") }
762
-
763
- it "calls Verifier#call with state hash" do
764
- verifier.expects(:call).
765
- with { |state| state[:last_action] == "setup" }
766
-
767
- instance.verify
768
- end
769
-
770
- it "writes the state file with last_action" do
771
- instance.verify
772
-
773
- state_file.read[:last_action].must_equal "verify"
774
- end
775
- end
776
-
777
- describe "with last of verify" do
778
-
779
- before { state_file.write(:last_action => "verify") }
780
-
781
- it "calls Verifier#call with state hash" do
782
- verifier.expects(:call).
783
- with { |state| state[:last_action] == "verify" }
784
-
785
- instance.verify
786
- end
787
-
788
- it "writes the state file with last_action" do
789
- instance.verify
790
-
791
- state_file.read[:last_action].must_equal "verify"
792
- end
793
- end
794
- end
795
-
796
- describe "#destroy" do
797
-
798
- describe "with no state" do
799
-
800
- it "calls Driver#destroy with empty state hash" do
801
- driver.expects(:destroy).with(Hash.new)
802
-
803
- instance.destroy
804
- end
805
-
806
- it "destroys the state file" do
807
- state_file.expects(:destroy)
808
-
809
- instance.destroy
810
- end
811
-
812
- it "logs the action start" do
813
- instance.destroy
814
-
815
- logger_io.string.
816
- must_match regex_for("Destroying #{instance.to_str}")
817
- end
818
-
819
- it "logs the create finish" do
820
- instance.destroy
821
-
822
- logger_io.string.
823
- must_match regex_for("Finished destroying #{instance.to_str}")
824
- end
825
- end
826
-
827
- [:create, :converge, :setup, :verify].each do |action|
828
-
829
- describe "with last_action of #{action}" do
830
-
831
- before { state_file.write(:last_action => action) }
832
-
833
- it "calls Driver#create with state hash" do
834
- driver.expects(:destroy).
835
- with { |state| state[:last_action] == action }
836
-
837
- instance.destroy
838
- end
839
-
840
- it "destroys the state file" do
841
- state_file.expects(:destroy)
842
-
843
- instance.destroy
844
- end
845
- end
846
- end
847
- end
848
-
849
- describe "#test" do
850
-
851
- describe "with no state" do
852
-
853
- it "calls destroy, create, converge, setup, verify, destroy" do
854
- driver.expects(:destroy)
855
- driver.expects(:create)
856
- provisioner.expects(:call)
857
- verifier.expects(:call)
858
- driver.expects(:destroy)
859
-
860
- instance.test
861
- end
862
-
863
- it "logs the action start" do
864
- instance.test
865
-
866
- logger_io.string.must_match regex_for("Testing #{instance.to_str}")
867
- end
868
-
869
- it "logs the action finish" do
870
- instance.test
871
-
872
- logger_io.string.
873
- must_match regex_for("Finished testing #{instance.to_str}")
874
- end
875
- end
876
-
877
- [:create, :converge, :setup, :verify].each do |action|
878
-
879
- describe "with last action of #{action}" do
880
-
881
- before { state_file.write(:last_action => action) }
882
-
883
- it "calls destroy, create, converge, setup, verify, destroy" do
884
- driver.expects(:destroy)
885
- driver.expects(:create)
886
- provisioner.expects(:call)
887
- verifier.expects(:call)
888
- driver.expects(:destroy)
889
-
890
- instance.test
891
- end
892
- end
893
- end
894
-
895
- describe "with destroy mode of never" do
896
-
897
- it "calls destroy, create, converge, setup, verify" do
898
- driver.expects(:destroy).once
899
- driver.expects(:create)
900
- provisioner.expects(:call)
901
- verifier.expects(:call)
902
-
903
- instance.test(:never)
904
- end
905
- end
906
-
907
- describe "with destroy mode of always" do
908
-
909
- it "calls destroy at even when action fails" do
910
- driver.expects(:destroy)
911
- driver.expects(:create)
912
- provisioner.expects(:call).raises(Kitchen::ActionFailed)
913
- driver.expects(:destroy)
914
-
915
- begin
916
- instance.test(:always)
917
- rescue # rubocop:disable Lint/HandleExceptions
918
- end
919
- end
920
- end
921
-
922
- describe "with destroy mode of passing" do
923
-
924
- it "doesn't call Driver#destroy at when action fails" do
925
- driver.stubs(:create).raises(Kitchen::ActionFailed)
926
-
927
- driver.expects(:destroy).once
928
-
929
- begin
930
- instance.test(:passing)
931
- rescue # rubocop:disable Lint/HandleExceptions
932
- end
933
- end
934
- end
935
- end
936
-
937
- describe "#remote_exec" do
938
-
939
- before { state_file.write(:last_action => "create") }
940
-
941
- it "calls Transport#execute with command" do
942
- connection = mock("connection")
943
- connection.expects(:execute).with("uptime")
944
- transport.stubs(:connection).yields(connection)
945
-
946
- instance.remote_exec("uptime")
947
- end
948
- end
949
-
950
- [:create, :converge, :setup, :verify, :test].each do |action|
951
-
952
- describe "#{action} on driver crash with ActionFailed" do
953
-
954
- before do
955
- driver.stubs(:create).raises(Kitchen::ActionFailed, "death")
956
- end
957
-
958
- it "write the state file with last action" do
959
- begin
960
- instance.public_send(action)
961
- rescue Kitchen::Error
962
- true # no need to act here
963
- end
964
-
965
- state_file.read[:last_action].must_be_nil
966
- end
967
-
968
- it "raises an InstanceFailure" do
969
- proc { instance.public_send(action) }.
970
- must_raise Kitchen::InstanceFailure
971
- end
972
-
973
- it "populates the InstanceFailure message" do
974
- begin
975
- instance.public_send(action)
976
- rescue Kitchen::Error => e
977
- e.message.must_match regex_for(
978
- "Create failed on instance #{instance.to_str}")
979
- end
980
- end
981
-
982
- it "logs the failure" do
983
- begin
984
- instance.public_send(action)
985
- rescue Kitchen::Error
986
- true # no need to act here
987
- end
988
-
989
- logger_io.string.must_match regex_for(
990
- "Create failed on instance #{instance.to_str}")
991
- end
992
- end
993
-
994
- describe "on driver crash with unexpected exception class" do
995
-
996
- before do
997
- driver.stubs(:create).raises(RuntimeError, "watwat")
998
- end
999
-
1000
- it "write the state file with last action" do
1001
- begin
1002
- instance.public_send(action)
1003
- rescue Kitchen::Error
1004
- true # no need to act here
1005
- end
1006
-
1007
- state_file.read[:last_action].must_be_nil
1008
- end
1009
-
1010
- it "raises an ActionFailed" do
1011
- proc { instance.public_send(action) }.
1012
- must_raise Kitchen::ActionFailed
1013
- end
1014
-
1015
- it "populates the ActionFailed message" do
1016
- begin
1017
- instance.public_send(action)
1018
- rescue Kitchen::Error => e
1019
- e.message.must_match regex_for(
1020
- "Failed to complete #create action: [watwat]")
1021
- end
1022
- end
1023
-
1024
- it "logs the failure" do
1025
- begin
1026
- instance.public_send(action)
1027
- rescue Kitchen::Error
1028
- true # no need to act here
1029
- end
1030
-
1031
- logger_io.string.must_match regex_for(
1032
- "Create failed on instance #{instance.to_str}")
1033
- end
1034
- end
1035
- end
1036
-
1037
- describe "crashes preserve last action for desired verify action" do
1038
-
1039
- before do
1040
- verifier.stubs(:call).raises(Kitchen::ActionFailed, "death")
1041
- end
1042
-
1043
- [:create, :converge, :setup].each do |action|
1044
-
1045
- it "for last state #{action}" do
1046
- state_file.write(:last_action => action.to_s)
1047
- begin
1048
- instance.verify
1049
- rescue Kitchen::Error
1050
- true # no need to act here
1051
- end
1052
-
1053
- state_file.read[:last_action].must_equal "setup"
1054
- end
1055
- end
1056
-
1057
- it "for last state verify" do
1058
- state_file.write(:last_action => "verify")
1059
- begin
1060
- instance.verify
1061
- rescue Kitchen::Error
1062
- true # no need to act here
1063
- end
1064
-
1065
- state_file.read[:last_action].must_equal "verify"
1066
- end
1067
- end
1068
-
1069
- describe "on drivers with serial actions" do
1070
-
1071
- let(:driver) { SerialDummyDriver.new({}) }
1072
-
1073
- it "runs in a synchronized block for serial actions" do
1074
- instance.test
1075
-
1076
- driver.action_in_mutex[:create].must_equal true
1077
- driver.action_in_mutex[:destroy].must_equal true
1078
- end
1079
- end
1080
-
1081
- describe "with legacy Driver::SSHBase subclasses" do
1082
-
1083
- let(:driver) { LegacyDriver.new({}) }
1084
-
1085
- describe "#converge" do
1086
-
1087
- describe "with no state" do
1088
-
1089
- it "calls Driver#create and Driver#converge with empty state hash" do
1090
- driver.expects(:create).with(Hash.new)
1091
- driver.expects(:converge).
1092
- with { |state| state[:last_action] == "create" }
1093
-
1094
- instance.converge
1095
- end
1096
- end
1097
-
1098
- describe "with last action of create" do
1099
-
1100
- before { state_file.write(:last_action => "create") }
1101
-
1102
- it "calls Driver#converge with state hash" do
1103
- driver.expects(:converge).
1104
- with { |state| state[:last_action] == "create" }
1105
-
1106
- instance.converge
1107
- end
1108
- end
1109
-
1110
- describe "with last action of converge" do
1111
-
1112
- before { state_file.write(:last_action => "converge") }
1113
-
1114
- it "calls Driver#converge with state hash" do
1115
- driver.expects(:converge).
1116
- with { |state| state[:last_action] == "converge" }
1117
-
1118
- instance.converge
1119
- end
1120
- end
1121
- end
1122
-
1123
- describe "#setup" do
1124
-
1125
- describe "with no state" do
1126
-
1127
- it "calls create, converge, and setup with empty state hash" do
1128
- driver.expects(:create).with(Hash.new)
1129
- driver.expects(:converge).
1130
- with { |state| state[:last_action] == "create" }
1131
- driver.expects(:setup).
1132
- with { |state| state[:last_action] == "converge" }
1133
-
1134
- instance.setup
1135
- end
1136
- end
1137
-
1138
- describe "with last action of create" do
1139
-
1140
- before { state_file.write(:last_action => "create") }
1141
-
1142
- it "calls Provisioner#call and setup with state hash" do
1143
- driver.expects(:converge).
1144
- with { |state| state[:last_action] == "create" }
1145
- driver.expects(:setup).
1146
- with { |state| state[:last_action] == "converge" }
1147
-
1148
- instance.setup
1149
- end
1150
- end
1151
-
1152
- describe "with last action of converge" do
1153
-
1154
- before { state_file.write(:last_action => "converge") }
1155
-
1156
- it "calls Driver#setup with state hash" do
1157
- driver.expects(:setup).
1158
- with { |state| state[:last_action] == "converge" }
1159
-
1160
- instance.setup
1161
- end
1162
- end
1163
-
1164
- describe "with last action of setup" do
1165
-
1166
- before { state_file.write(:last_action => "setup") }
1167
-
1168
- it "calls Driver#setup with state hash" do
1169
- driver.expects(:setup).
1170
- with { |state| state[:last_action] == "setup" }
1171
-
1172
- instance.setup
1173
- end
1174
- end
1175
- end
1176
-
1177
- describe "#verify" do
1178
-
1179
- describe "with no state" do
1180
-
1181
- it "calls create, converge, setup, and verify with empty state hash" do
1182
- driver.expects(:create).with(Hash.new)
1183
- driver.expects(:converge).
1184
- with { |state| state[:last_action] == "create" }
1185
- driver.expects(:setup).
1186
- with { |state| state[:last_action] == "converge" }
1187
- driver.expects(:verify).
1188
- with { |state| state[:last_action] == "setup" }
1189
-
1190
- instance.verify
1191
- end
1192
- end
1193
-
1194
- describe "with last of create" do
1195
-
1196
- before { state_file.write(:last_action => "create") }
1197
-
1198
- it "calls converge, setup, and verify with state hash" do
1199
- driver.expects(:converge).
1200
- with { |state| state[:last_action] == "create" }
1201
- driver.expects(:setup).
1202
- with { |state| state[:last_action] == "converge" }
1203
- driver.expects(:verify).
1204
- with { |state| state[:last_action] == "setup" }
1205
-
1206
- instance.verify
1207
- end
1208
- end
1209
-
1210
- describe "with last of converge" do
1211
-
1212
- before { state_file.write(:last_action => "converge") }
1213
-
1214
- it "calls Driver#setup, and verify with state hash" do
1215
- driver.expects(:setup).
1216
- with { |state| state[:last_action] == "converge" }
1217
- driver.expects(:verify).
1218
- with { |state| state[:last_action] == "setup" }
1219
-
1220
- instance.verify
1221
- end
1222
- end
1223
-
1224
- describe "with last of setup" do
1225
-
1226
- before { state_file.write(:last_action => "setup") }
1227
-
1228
- it "calls Driver#verify with state hash" do
1229
- driver.expects(:verify).
1230
- with { |state| state[:last_action] == "setup" }
1231
-
1232
- instance.verify
1233
- end
1234
- end
1235
-
1236
- describe "with last of verify" do
1237
-
1238
- before { state_file.write(:last_action => "verify") }
1239
-
1240
- it "calls Driver#verify with state hash" do
1241
- driver.expects(:verify).
1242
- with { |state| state[:last_action] == "verify" }
1243
-
1244
- instance.verify
1245
- end
1246
- end
1247
- end
1248
-
1249
- describe "#test" do
1250
-
1251
- describe "with no state" do
1252
-
1253
- it "calls destroy, create, converge, setup, verify, destroy" do
1254
- driver.expects(:destroy)
1255
- driver.expects(:create)
1256
- driver.expects(:converge)
1257
- driver.expects(:setup)
1258
- driver.expects(:verify)
1259
- driver.expects(:destroy)
1260
-
1261
- instance.test
1262
- end
1263
- end
1264
-
1265
- [:create, :converge, :setup, :verify].each do |action|
1266
-
1267
- describe "with last action of #{action}" do
1268
-
1269
- before { state_file.write(:last_action => action) }
1270
-
1271
- it "calls destroy, create, converge, setup, verify, destroy" do
1272
- driver.expects(:destroy)
1273
- driver.expects(:create)
1274
- driver.expects(:converge)
1275
- driver.expects(:setup)
1276
- driver.expects(:verify)
1277
- driver.expects(:destroy)
1278
-
1279
- instance.test
1280
- end
1281
- end
1282
- end
1283
-
1284
- describe "with destroy mode of never" do
1285
-
1286
- it "calls destroy, create, converge, setup, verify" do
1287
- driver.expects(:destroy).once
1288
- driver.expects(:create)
1289
- driver.expects(:converge)
1290
- driver.expects(:setup)
1291
- driver.expects(:verify)
1292
-
1293
- instance.test(:never)
1294
- end
1295
- end
1296
-
1297
- describe "with destroy mode of always" do
1298
-
1299
- it "calls destroy at even when action fails" do
1300
- driver.expects(:destroy)
1301
- driver.expects(:create)
1302
- driver.expects(:converge).raises(Kitchen::ActionFailed)
1303
- driver.expects(:destroy)
1304
-
1305
- begin
1306
- instance.test(:always)
1307
- rescue # rubocop:disable Lint/HandleExceptions
1308
- end
1309
- end
1310
- end
1311
- end
1312
-
1313
- it "#login executes the driver's login_command" do
1314
- state_file.write(:last_action => "create")
1315
- driver.stubs(:login_command).with(:last_action => "create").
1316
- returns(Kitchen::LoginCommand.new("echo", ["hello"], :purple => true))
1317
- Kernel.expects(:exec).with("echo", "hello", :purple => true)
1318
-
1319
- instance.login
1320
- end
1321
- end
1322
- end
1323
-
1324
- describe Kitchen::Instance::FSM do
1325
-
1326
- let(:fsm) { Kitchen::Instance::FSM }
1327
-
1328
- describe ".actions" do
1329
-
1330
- it "passing nils returns destroy" do
1331
- fsm.actions(nil, nil).must_equal [:destroy]
1332
- end
1333
-
1334
- it "accepts a string for desired argument" do
1335
- fsm.actions(nil, "create").must_equal [:create]
1336
- end
1337
-
1338
- it "accepts a symbol for desired argument" do
1339
- fsm.actions(nil, :create).must_equal [:create]
1340
- end
1341
-
1342
- it "starting from no state to create returns create" do
1343
- fsm.actions(nil, :create).must_equal [:create]
1344
- end
1345
-
1346
- it "starting from :create to create returns create" do
1347
- fsm.actions(:create, :create).must_equal [:create]
1348
- end
1349
-
1350
- it "starting from no state to converge returns create, converge" do
1351
- fsm.actions(nil, :converge).must_equal [:create, :converge]
1352
- end
1353
-
1354
- it "starting from create to converge returns converge" do
1355
- fsm.actions(:create, :converge).must_equal [:converge]
1356
- end
1357
-
1358
- it "starting from converge to converge returns converge" do
1359
- fsm.actions(:converge, :converge).must_equal [:converge]
1360
- end
1361
-
1362
- it "starting from no state to setup returns create, converge, setup" do
1363
- fsm.actions(nil, :setup).must_equal [:create, :converge, :setup]
1364
- end
1365
-
1366
- it "starting from create to setup returns converge, setup" do
1367
- fsm.actions(:create, :setup).must_equal [:converge, :setup]
1368
- end
1369
-
1370
- it "starting from converge to setup returns setup" do
1371
- fsm.actions(:converge, :setup).must_equal [:setup]
1372
- end
1373
-
1374
- it "starting from setup to setup return setup" do
1375
- fsm.actions(:setup, :setup).must_equal [:setup]
1376
- end
1377
-
1378
- it "starting from no state to verify returns create, converge, setup, verify" do
1379
- fsm.actions(nil, :verify).must_equal [:create, :converge, :setup, :verify]
1380
- end
1381
-
1382
- it "starting from create to verify returns converge, setup, verify" do
1383
- fsm.actions(:create, :verify).must_equal [:converge, :setup, :verify]
1384
- end
1385
-
1386
- it "starting from converge to verify returns setup, verify" do
1387
- fsm.actions(:converge, :verify).must_equal [:setup, :verify]
1388
- end
1389
-
1390
- it "starting from setup to verify returns verify" do
1391
- fsm.actions(:setup, :verify).must_equal [:verify]
1392
- end
1393
-
1394
- it "starting from verify to verify returns verify" do
1395
- fsm.actions(:verify, :verify).must_equal [:verify]
1396
- end
1397
-
1398
- [:verify, :setup, :converge].each do |s|
1399
- it "starting from #{s} to create returns create" do
1400
- fsm.actions(s, :create).must_equal [:create]
1401
- end
1402
- end
1403
-
1404
- [:verify, :setup].each do |s|
1405
- it "starting from #{s} to converge returns converge" do
1406
- fsm.actions(s, :converge).must_equal [:converge]
1407
- end
1408
- end
1409
-
1410
- it "starting from verify to setup returns setup" do
1411
- fsm.actions(:verify, :setup).must_equal [:setup]
1412
- end
1413
- end
1414
- end
1415
-
1416
- def regex_for(string)
1417
- Regexp.new(Regexp.escape(string))
1418
- end
1419
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, 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
+ require "stringio"
21
+
22
+ require "kitchen/logging"
23
+ require "kitchen/instance"
24
+ require "kitchen/driver"
25
+ require "kitchen/driver/dummy"
26
+ require "kitchen/platform"
27
+ require "kitchen/provisioner"
28
+ require "kitchen/provisioner/dummy"
29
+ require "kitchen/suite"
30
+ require "kitchen/transport/dummy"
31
+ require "kitchen/verifier/dummy"
32
+
33
+ class DummyStateFile
34
+
35
+ def initialize(*); end
36
+
37
+ def read
38
+ @_state = Hash.new unless @_state
39
+ @_state.dup
40
+ end
41
+
42
+ def write(state)
43
+ @_state = state.dup
44
+ end
45
+
46
+ def destroy
47
+ @_state = nil
48
+ end
49
+
50
+ def diagnose
51
+ Hash.new
52
+ end
53
+ end
54
+
55
+ class SerialDummyDriver < Kitchen::Driver::Dummy
56
+
57
+ no_parallel_for :create, :destroy
58
+
59
+ attr_reader :action_in_mutex
60
+
61
+ def track_locked(action)
62
+ @action_in_mutex = Hash.new unless @action_in_mutex
63
+ @action_in_mutex[action] = Kitchen::Instance.mutexes[self.class].locked?
64
+ end
65
+
66
+ def create(state)
67
+ track_locked(:create)
68
+ super
69
+ end
70
+
71
+ def destroy(state)
72
+ track_locked(:destroy)
73
+ super
74
+ end
75
+ end
76
+
77
+ class LegacyDriver < Kitchen::Driver::SSHBase
78
+
79
+ attr_reader :called_converge, :called_setup, :called_verify
80
+
81
+ def converge(_)
82
+ @called_converge
83
+ end
84
+
85
+ def setup(_)
86
+ @called_setup
87
+ end
88
+
89
+ def verify(_)
90
+ @called_verify
91
+ end
92
+ end
93
+
94
+ describe Kitchen::Instance do
95
+
96
+ let(:driver) { Kitchen::Driver::Dummy.new({}) }
97
+ let(:logger_io) { StringIO.new }
98
+ let(:logger) { Kitchen::Logger.new(:logdev => logger_io) }
99
+ let(:instance) { Kitchen::Instance.new(opts) }
100
+ let(:provisioner) { Kitchen::Provisioner::Dummy.new({}) }
101
+ let(:state_file) { DummyStateFile.new }
102
+ let(:transport) { Kitchen::Transport::Dummy.new({}) }
103
+ let(:verifier) { Kitchen::Verifier::Dummy.new({}) }
104
+
105
+ let(:opts) do
106
+ { :suite => suite, :platform => platform, :driver => driver,
107
+ :provisioner => provisioner, :verifier => verifier,
108
+ :logger => logger, :state_file => state_file, :transport => transport }
109
+ end
110
+
111
+ def suite(name = "suite")
112
+ @suite ||= Kitchen::Suite.new(:name => name)
113
+ end
114
+
115
+ def platform(name = "platform")
116
+ @platform ||= Kitchen::Platform.new(:name => name)
117
+ end
118
+
119
+ describe ".name_for" do
120
+
121
+ it "combines the suite and platform names with a dash" do
122
+ Kitchen::Instance.name_for(suite("suite"), platform("platform")).
123
+ must_equal "suite-platform"
124
+ end
125
+
126
+ it "squashes periods in suite name" do
127
+ Kitchen::Instance.name_for(suite("suite.ness"), platform("platform")).
128
+ must_equal "suiteness-platform"
129
+ end
130
+
131
+ it "squashes periods in platform name" do
132
+ Kitchen::Instance.name_for(suite("suite"), platform("platform.s")).
133
+ must_equal "suite-platforms"
134
+ end
135
+
136
+ it "squashes periods in suite and platform names" do
137
+ Kitchen::Instance.name_for(suite("s.s"), platform("p.p")).
138
+ must_equal "ss-pp"
139
+ end
140
+
141
+ it "transforms underscores to dashes in suite name" do
142
+ Kitchen::Instance.name_for(suite("suite_ness"), platform("platform")).
143
+ must_equal "suite-ness-platform"
144
+ end
145
+
146
+ it "transforms underscores to dashes in platform name" do
147
+ Kitchen::Instance.name_for(suite("suite"), platform("platform_s")).
148
+ must_equal "suite-platform-s"
149
+ end
150
+
151
+ it "transforms underscores to dashes in suite and platform names" do
152
+ Kitchen::Instance.name_for(suite("_s__s_"), platform("pp_")).
153
+ must_equal "-s--s--pp-"
154
+ end
155
+
156
+ it "transforms forward slashes to dashes in suite name" do
157
+ Kitchen::Instance.name_for(suite("suite/ness"), platform("platform")).
158
+ must_equal "suite-ness-platform"
159
+ end
160
+
161
+ it "transforms forward slashes to dashes in platform name" do
162
+ Kitchen::Instance.name_for(suite("suite"), platform("platform/s")).
163
+ must_equal "suite-platform-s"
164
+ end
165
+
166
+ it "transforms forward slashes to dashes in suite and platform names" do
167
+ Kitchen::Instance.name_for(suite("/s//s/"), platform("pp/")).
168
+ must_equal "-s--s--pp-"
169
+ end
170
+ end
171
+
172
+ describe "#suite" do
173
+
174
+ it "returns its suite" do
175
+ instance.suite.must_equal suite
176
+ end
177
+
178
+ it "raises an ArgumentError if missing" do
179
+ opts.delete(:suite)
180
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
181
+ end
182
+ end
183
+
184
+ describe "#platform" do
185
+
186
+ it "returns its platform" do
187
+ instance.platform.must_equal platform
188
+ end
189
+
190
+ it "raises an ArgumentError if missing" do
191
+ opts.delete(:platform)
192
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
193
+ end
194
+ end
195
+
196
+ describe "#driver" do
197
+
198
+ it "returns its driver" do
199
+ instance.driver.must_equal driver
200
+ end
201
+
202
+ it "raises an ArgumentError if missing" do
203
+ opts.delete(:driver)
204
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
205
+ end
206
+
207
+ it "sets Driver#instance to itself" do
208
+ # it's mind-bottling
209
+ instance.driver.instance.must_equal instance
210
+ end
211
+ end
212
+
213
+ describe "#logger" do
214
+
215
+ it "returns its logger" do
216
+ instance.logger.must_equal logger
217
+ end
218
+
219
+ it "uses Kitchen.logger by default" do
220
+ opts.delete(:logger)
221
+ instance.logger.must_equal Kitchen.logger
222
+ end
223
+ end
224
+
225
+ describe "#provisioner" do
226
+
227
+ it "returns its provisioner" do
228
+ instance.provisioner.must_equal provisioner
229
+ end
230
+
231
+ it "raises an ArgumentError if missing" do
232
+ opts.delete(:provisioner)
233
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
234
+ end
235
+
236
+ it "sets Provisioner#instance to itself" do
237
+ # it's mind-bottling
238
+ instance.provisioner.instance.must_equal instance
239
+ end
240
+ end
241
+
242
+ describe "#transport" do
243
+
244
+ it "returns its transport" do
245
+ instance.transport.must_equal transport
246
+ end
247
+
248
+ it "raises an ArgumentError if missing" do
249
+ opts.delete(:transport)
250
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
251
+ end
252
+
253
+ it "sets Transport#instance to itself" do
254
+ # it's mind-bottling
255
+ instance.transport.instance.must_equal instance
256
+ end
257
+ end
258
+
259
+ describe "#verifier" do
260
+
261
+ it "returns its verifier" do
262
+ instance.verifier.must_equal verifier
263
+ end
264
+
265
+ it "raises and ArgumentError if missing" do
266
+ opts.delete(:verifier)
267
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
268
+ end
269
+
270
+ it "sets Verifier#instance to itself" do
271
+ # it's mind-bottling
272
+ instance.verifier.instance.must_equal instance
273
+ end
274
+ end
275
+
276
+ describe "#state_file" do
277
+
278
+ it "raises an ArgumentError if missing" do
279
+ opts.delete(:state_file)
280
+ proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
281
+ end
282
+ end
283
+
284
+ it "#name returns it name" do
285
+ instance.name.must_equal "suite-platform"
286
+ end
287
+
288
+ it "#to_str returns a string representation with its name" do
289
+ instance.to_str.must_equal "<suite-platform>"
290
+ end
291
+
292
+ it "#login executes the transport's login_command" do
293
+ conn = stub("connection")
294
+ state_file.write(:last_action => "create")
295
+ transport.stubs(:connection).with(:last_action => "create").
296
+ returns(conn)
297
+ conn.stubs(:login_command).
298
+ returns(Kitchen::LoginCommand.new("echo", ["hello"], :purple => true))
299
+ Kernel.expects(:exec).with("echo", "hello", :purple => true)
300
+
301
+ instance.login
302
+ end
303
+
304
+ it "#login raises a UserError if the instance is not created" do
305
+ state_file.write({})
306
+
307
+ proc { instance.login }.must_raise Kitchen::UserError
308
+ end
309
+
310
+ describe "#diagnose" do
311
+
312
+ it "returns a hash" do
313
+ instance.diagnose.must_be_instance_of Hash
314
+ end
315
+
316
+ it "sets :platform key to platform's diagnose info" do
317
+ platform.stubs(:diagnose).returns(:a => "b")
318
+
319
+ instance.diagnose[:platform].must_equal(:a => "b")
320
+ end
321
+
322
+ it "sets :platform key to :unknown if obj can't respond to #diagnose" do
323
+ opts[:platform] = Class.new(platform.class) {
324
+ undef_method :diagnose
325
+ }.new(:name => "whoop")
326
+
327
+ instance.diagnose[:platform].must_equal :unknown
328
+ end
329
+
330
+ it "sets :state_file key to state_file's diganose info" do
331
+ state_file.stubs(:diagnose).returns(:a => "b")
332
+
333
+ instance.diagnose[:state_file].must_equal(:a => "b")
334
+ end
335
+
336
+ it "sets :state_file key to :unknown if obj can't respond to #diagnose" do
337
+ opts[:state_file] = Class.new(state_file.class) {
338
+ undef_method :diagnose
339
+ }.new
340
+
341
+ instance.diagnose[:state_file].must_equal :unknown
342
+ end
343
+
344
+ it "sets :provisioner key to provisioner's diganose info" do
345
+ provisioner.stubs(:diagnose).returns(:a => "b")
346
+
347
+ instance.diagnose[:provisioner].must_equal(:a => "b")
348
+ end
349
+
350
+ it "sets :provisioner key to :unknown if obj can't respond to #diagnose" do
351
+ opts[:provisioner] = Class.new(provisioner.class) {
352
+ undef_method :diagnose
353
+ }.new
354
+
355
+ instance.diagnose[:provisioner].must_equal :unknown
356
+ end
357
+
358
+ it "sets :verifier key to verifier's diganose info" do
359
+ verifier.stubs(:diagnose).returns(:a => "b")
360
+
361
+ instance.diagnose[:verifier].must_equal(:a => "b")
362
+ end
363
+
364
+ it "sets :verifier key to :unknown if obj can't respond to #diagnose" do
365
+ opts[:verifier] = Class.new(verifier.class) {
366
+ undef_method :diagnose
367
+ }.new({})
368
+
369
+ instance.diagnose[:verifier].must_equal :unknown
370
+ end
371
+
372
+ it "sets :transport key to transport's diganose info" do
373
+ transport.stubs(:diagnose).returns(:a => "b")
374
+
375
+ instance.diagnose[:transport].must_equal(:a => "b")
376
+ end
377
+
378
+ it "sets :transport key to :unknown if obj can't respond to #diagnose" do
379
+ opts[:transport] = Class.new(transport.class) {
380
+ undef_method :diagnose
381
+ }.new
382
+
383
+ instance.diagnose[:transport].must_equal :unknown
384
+ end
385
+ end
386
+
387
+ describe "#diagnose_plugins" do
388
+
389
+ it "returns a hash" do
390
+ instance.diagnose_plugins.must_be_instance_of Hash
391
+ end
392
+
393
+ it "sets :driver key to driver's plugin_diagnose info" do
394
+ driver.class.stubs(:diagnose).returns(:a => "b")
395
+
396
+ instance.diagnose_plugins[:driver].must_equal(
397
+ :name => "Dummy",
398
+ :a => "b"
399
+ )
400
+ end
401
+
402
+ it "sets :driver key to :unknown if class doesn't have #diagnose" do
403
+ opts[:driver] = Class.new(driver.class) {
404
+ undef_method :diagnose_plugin
405
+ }.new({})
406
+
407
+ instance.diagnose_plugins[:driver].must_equal(:unknown)
408
+ end
409
+
410
+ it "sets :provisioner key to provisioner's plugin_diagnose info" do
411
+ provisioner.class.stubs(:diagnose).returns(:a => "b")
412
+
413
+ instance.diagnose_plugins[:provisioner].must_equal(
414
+ :name => "Dummy",
415
+ :a => "b"
416
+ )
417
+ end
418
+
419
+ it "sets :provisioner key to :unknown if class doesn't have #diagnose" do
420
+ opts[:provisioner] = Class.new(driver.class) {
421
+ undef_method :diagnose_plugin
422
+ }.new({})
423
+
424
+ instance.diagnose_plugins[:provisioner].must_equal(:unknown)
425
+ end
426
+
427
+ it "sets :verifier key to verifier's plugin_diagnose info" do
428
+ verifier.class.stubs(:diagnose).returns(:a => "b")
429
+
430
+ instance.diagnose_plugins[:verifier].must_equal(
431
+ :name => "Dummy",
432
+ :a => "b"
433
+ )
434
+ end
435
+
436
+ it "sets :verifier key to :unknown if class doesn't have #diagnose" do
437
+ opts[:verifier] = Class.new(verifier.class) {
438
+ undef_method :diagnose_plugin
439
+ }.new({})
440
+
441
+ instance.diagnose_plugins[:verifier].must_equal(:unknown)
442
+ end
443
+
444
+ it "sets :transport key to transport's plugin_diagnose info" do
445
+ transport.class.stubs(:diagnose).returns(:a => "b")
446
+
447
+ instance.diagnose_plugins[:transport].must_equal(
448
+ :name => "Dummy",
449
+ :a => "b"
450
+ )
451
+ end
452
+
453
+ it "sets :transport key to :unknown if class doesn't have #diagnose" do
454
+ opts[:transport] = Class.new(transport.class) {
455
+ undef_method :diagnose_plugin
456
+ }.new({})
457
+
458
+ instance.diagnose_plugins[:transport].must_equal(:unknown)
459
+ end
460
+ end
461
+
462
+ describe "performing actions" do
463
+
464
+ describe "#create" do
465
+
466
+ describe "with no state" do
467
+
468
+ it "calls Driver#create with empty state hash" do
469
+ driver.expects(:create).with(Hash.new)
470
+
471
+ instance.create
472
+ end
473
+
474
+ it "writes the state file with last_action" do
475
+ instance.create
476
+
477
+ state_file.read[:last_action].must_equal "create"
478
+ end
479
+
480
+ it "logs the action start" do
481
+ instance.create
482
+
483
+ logger_io.string.must_match regex_for("Creating #{instance.to_str}")
484
+ end
485
+
486
+ it "logs the action finish" do
487
+ instance.create
488
+
489
+ logger_io.string.
490
+ must_match regex_for("Finished creating #{instance.to_str}")
491
+ end
492
+
493
+ end
494
+
495
+ describe "with last_action of create" do
496
+
497
+ before { state_file.write(:last_action => "create") }
498
+
499
+ it "calls Driver#create with state hash" do
500
+ driver.expects(:create).
501
+ with { |state| state[:last_action] == "create" }
502
+
503
+ instance.create
504
+ end
505
+
506
+ it "writes the state file with last_action" do
507
+ instance.create
508
+
509
+ state_file.read[:last_action].must_equal "create"
510
+ end
511
+ end
512
+ end
513
+
514
+ describe "#converge" do
515
+
516
+ describe "with no state" do
517
+
518
+ it "calls Driver#create and Provisioner#call with empty state hash" do
519
+ driver.expects(:create).with(Hash.new)
520
+ provisioner.expects(:call).
521
+ with { |state| state[:last_action] == "create" }
522
+
523
+ instance.converge
524
+ end
525
+
526
+ it "writes the state file with last_action" do
527
+ instance.converge
528
+
529
+ state_file.read[:last_action].must_equal "converge"
530
+ end
531
+
532
+ it "logs the action start" do
533
+ instance.converge
534
+
535
+ logger_io.string.must_match regex_for("Converging #{instance.to_str}")
536
+ end
537
+
538
+ it "logs the action finish" do
539
+ instance.converge
540
+
541
+ logger_io.string.
542
+ must_match regex_for("Finished converging #{instance.to_str}")
543
+ end
544
+ end
545
+
546
+ describe "with last action of create" do
547
+
548
+ before { state_file.write(:last_action => "create") }
549
+
550
+ it "calls Provisioner#call with state hash" do
551
+ provisioner.expects(:call).
552
+ with { |state| state[:last_action] == "create" }
553
+
554
+ instance.converge
555
+ end
556
+
557
+ it "writes the state file with last_action" do
558
+ instance.converge
559
+
560
+ state_file.read[:last_action].must_equal "converge"
561
+ end
562
+ end
563
+
564
+ describe "with last action of converge" do
565
+
566
+ before { state_file.write(:last_action => "converge") }
567
+
568
+ it "calls Provisioner#call with state hash" do
569
+ provisioner.expects(:call).
570
+ with { |state| state[:last_action] == "converge" }
571
+
572
+ instance.converge
573
+ end
574
+
575
+ it "writes the state file with last_action" do
576
+ instance.converge
577
+
578
+ state_file.read[:last_action].must_equal "converge"
579
+ end
580
+ end
581
+ end
582
+
583
+ describe "#setup" do
584
+
585
+ describe "with no state" do
586
+
587
+ it "calls create and converge with empty state hash" do
588
+ driver.expects(:create).with(Hash.new)
589
+ provisioner.expects(:call).
590
+ with { |state| state[:last_action] == "create" }
591
+ driver.expects(:setup).
592
+ with { |state| state[:last_action] == "converge" }.
593
+ never
594
+
595
+ instance.setup
596
+ end
597
+
598
+ it "writes the state file with last_action" do
599
+ instance.setup
600
+
601
+ state_file.read[:last_action].must_equal "setup"
602
+ end
603
+
604
+ it "logs the action start" do
605
+ instance.setup
606
+
607
+ logger_io.string.must_match regex_for("Setting up #{instance.to_str}")
608
+ end
609
+
610
+ it "logs the action finish" do
611
+ instance.setup
612
+
613
+ logger_io.string.
614
+ must_match regex_for("Finished setting up #{instance.to_str}")
615
+ end
616
+ end
617
+
618
+ describe "with last action of create" do
619
+
620
+ before { state_file.write(:last_action => "create") }
621
+
622
+ it "calls Provisioner#call with state hash" do
623
+ provisioner.expects(:call).
624
+ with { |state| state[:last_action] == "create" }
625
+ driver.expects(:setup).
626
+ with { |state| state[:last_action] == "converge" }.
627
+ never
628
+
629
+ instance.setup
630
+ end
631
+
632
+ it "writes the state file with last_action" do
633
+ instance.setup
634
+
635
+ state_file.read[:last_action].must_equal "setup"
636
+ end
637
+ end
638
+
639
+ describe "with last action of converge" do
640
+
641
+ before { state_file.write(:last_action => "converge") }
642
+
643
+ it "calls nothing with state hash" do
644
+ driver.expects(:setup).
645
+ with { |state| state[:last_action] == "converge" }.
646
+ never
647
+
648
+ instance.setup
649
+ end
650
+
651
+ it "writes the state file with last_action" do
652
+ instance.setup
653
+
654
+ state_file.read[:last_action].must_equal "setup"
655
+ end
656
+ end
657
+
658
+ describe "with last action of setup" do
659
+
660
+ before { state_file.write(:last_action => "setup") }
661
+
662
+ it "calls nothing with state hash" do
663
+ driver.expects(:setup).
664
+ with { |state| state[:last_action] == "setup" }.
665
+ never
666
+
667
+ instance.setup
668
+ end
669
+
670
+ it "writes the state file with last_action" do
671
+ instance.setup
672
+
673
+ state_file.read[:last_action].must_equal "setup"
674
+ end
675
+ end
676
+ end
677
+
678
+ describe "#verify" do
679
+
680
+ describe "with no state" do
681
+
682
+ it "calls create, converge, and verify with empty state hash" do
683
+ driver.expects(:create).with(Hash.new)
684
+ provisioner.expects(:call).
685
+ with { |state| state[:last_action] == "create" }
686
+ driver.expects(:setup).
687
+ with { |state| state[:last_action] == "converge" }.
688
+ never
689
+ verifier.expects(:call).
690
+ with { |state| state[:last_action] == "setup" }
691
+
692
+ instance.verify
693
+ end
694
+
695
+ it "writes the state file with last_action" do
696
+ instance.verify
697
+
698
+ state_file.read[:last_action].must_equal "verify"
699
+ end
700
+
701
+ it "logs the action start" do
702
+ instance.verify
703
+
704
+ logger_io.string.must_match regex_for("Verifying #{instance.to_str}")
705
+ end
706
+
707
+ it "logs the action finish" do
708
+ instance.verify
709
+
710
+ logger_io.string.
711
+ must_match regex_for("Finished verifying #{instance.to_str}")
712
+ end
713
+ end
714
+
715
+ describe "with last of create" do
716
+
717
+ before { state_file.write(:last_action => "create") }
718
+
719
+ it "calls converge, and verify with state hash" do
720
+ provisioner.expects(:call).
721
+ with { |state| state[:last_action] == "create" }
722
+ driver.expects(:setup).
723
+ with { |state| state[:last_action] == "converge" }.
724
+ never
725
+ verifier.expects(:call).
726
+ with { |state| state[:last_action] == "setup" }
727
+
728
+ instance.verify
729
+ end
730
+
731
+ it "writes the state file with last_action" do
732
+ instance.verify
733
+
734
+ state_file.read[:last_action].must_equal "verify"
735
+ end
736
+ end
737
+
738
+ describe "with last of converge" do
739
+
740
+ before { state_file.write(:last_action => "converge") }
741
+
742
+ it "calls Verifier#call with state hash" do
743
+ driver.expects(:setup).
744
+ with { |state| state[:last_action] == "converge" }.
745
+ never
746
+ verifier.expects(:call).
747
+ with { |state| state[:last_action] == "setup" }
748
+
749
+ instance.verify
750
+ end
751
+
752
+ it "writes the state file with last_action" do
753
+ instance.verify
754
+
755
+ state_file.read[:last_action].must_equal "verify"
756
+ end
757
+ end
758
+
759
+ describe "with last of setup" do
760
+
761
+ before { state_file.write(:last_action => "setup") }
762
+
763
+ it "calls Verifier#call with state hash" do
764
+ verifier.expects(:call).
765
+ with { |state| state[:last_action] == "setup" }
766
+
767
+ instance.verify
768
+ end
769
+
770
+ it "writes the state file with last_action" do
771
+ instance.verify
772
+
773
+ state_file.read[:last_action].must_equal "verify"
774
+ end
775
+ end
776
+
777
+ describe "with last of verify" do
778
+
779
+ before { state_file.write(:last_action => "verify") }
780
+
781
+ it "calls Verifier#call with state hash" do
782
+ verifier.expects(:call).
783
+ with { |state| state[:last_action] == "verify" }
784
+
785
+ instance.verify
786
+ end
787
+
788
+ it "writes the state file with last_action" do
789
+ instance.verify
790
+
791
+ state_file.read[:last_action].must_equal "verify"
792
+ end
793
+ end
794
+ end
795
+
796
+ describe "#destroy" do
797
+
798
+ describe "with no state" do
799
+
800
+ it "calls Driver#destroy with empty state hash" do
801
+ driver.expects(:destroy).with(Hash.new)
802
+
803
+ instance.destroy
804
+ end
805
+
806
+ it "destroys the state file" do
807
+ state_file.expects(:destroy)
808
+
809
+ instance.destroy
810
+ end
811
+
812
+ it "logs the action start" do
813
+ instance.destroy
814
+
815
+ logger_io.string.
816
+ must_match regex_for("Destroying #{instance.to_str}")
817
+ end
818
+
819
+ it "logs the create finish" do
820
+ instance.destroy
821
+
822
+ logger_io.string.
823
+ must_match regex_for("Finished destroying #{instance.to_str}")
824
+ end
825
+ end
826
+
827
+ [:create, :converge, :setup, :verify].each do |action|
828
+
829
+ describe "with last_action of #{action}" do
830
+
831
+ before { state_file.write(:last_action => action) }
832
+
833
+ it "calls Driver#create with state hash" do
834
+ driver.expects(:destroy).
835
+ with { |state| state[:last_action] == action }
836
+
837
+ instance.destroy
838
+ end
839
+
840
+ it "destroys the state file" do
841
+ state_file.expects(:destroy)
842
+
843
+ instance.destroy
844
+ end
845
+ end
846
+ end
847
+ end
848
+
849
+ describe "#test" do
850
+
851
+ describe "with no state" do
852
+
853
+ it "calls destroy, create, converge, setup, verify, destroy" do
854
+ driver.expects(:destroy)
855
+ driver.expects(:create)
856
+ provisioner.expects(:call)
857
+ verifier.expects(:call)
858
+ driver.expects(:destroy)
859
+
860
+ instance.test
861
+ end
862
+
863
+ it "logs the action start" do
864
+ instance.test
865
+
866
+ logger_io.string.must_match regex_for("Testing #{instance.to_str}")
867
+ end
868
+
869
+ it "logs the action finish" do
870
+ instance.test
871
+
872
+ logger_io.string.
873
+ must_match regex_for("Finished testing #{instance.to_str}")
874
+ end
875
+ end
876
+
877
+ [:create, :converge, :setup, :verify].each do |action|
878
+
879
+ describe "with last action of #{action}" do
880
+
881
+ before { state_file.write(:last_action => action) }
882
+
883
+ it "calls destroy, create, converge, setup, verify, destroy" do
884
+ driver.expects(:destroy)
885
+ driver.expects(:create)
886
+ provisioner.expects(:call)
887
+ verifier.expects(:call)
888
+ driver.expects(:destroy)
889
+
890
+ instance.test
891
+ end
892
+ end
893
+ end
894
+
895
+ describe "with destroy mode of never" do
896
+
897
+ it "calls destroy, create, converge, setup, verify" do
898
+ driver.expects(:destroy).once
899
+ driver.expects(:create)
900
+ provisioner.expects(:call)
901
+ verifier.expects(:call)
902
+
903
+ instance.test(:never)
904
+ end
905
+ end
906
+
907
+ describe "with destroy mode of always" do
908
+
909
+ it "calls destroy at even when action fails" do
910
+ driver.expects(:destroy)
911
+ driver.expects(:create)
912
+ provisioner.expects(:call).raises(Kitchen::ActionFailed)
913
+ driver.expects(:destroy)
914
+
915
+ begin
916
+ instance.test(:always)
917
+ rescue # rubocop:disable Lint/HandleExceptions
918
+ end
919
+ end
920
+ end
921
+
922
+ describe "with destroy mode of passing" do
923
+
924
+ it "doesn't call Driver#destroy at when action fails" do
925
+ driver.stubs(:create).raises(Kitchen::ActionFailed)
926
+
927
+ driver.expects(:destroy).once
928
+
929
+ begin
930
+ instance.test(:passing)
931
+ rescue # rubocop:disable Lint/HandleExceptions
932
+ end
933
+ end
934
+ end
935
+ end
936
+
937
+ describe "#remote_exec" do
938
+
939
+ before { state_file.write(:last_action => "create") }
940
+
941
+ it "calls Transport#execute with command" do
942
+ connection = mock("connection")
943
+ connection.expects(:execute).with("uptime")
944
+ transport.stubs(:connection).yields(connection)
945
+
946
+ instance.remote_exec("uptime")
947
+ end
948
+ end
949
+
950
+ [:create, :converge, :setup, :verify, :test].each do |action|
951
+
952
+ describe "#{action} on driver crash with ActionFailed" do
953
+
954
+ before do
955
+ driver.stubs(:create).raises(Kitchen::ActionFailed, "death")
956
+ end
957
+
958
+ it "write the state file with last action" do
959
+ begin
960
+ instance.public_send(action)
961
+ rescue Kitchen::Error
962
+ true # no need to act here
963
+ end
964
+
965
+ state_file.read[:last_action].must_be_nil
966
+ end
967
+
968
+ it "raises an InstanceFailure" do
969
+ proc { instance.public_send(action) }.
970
+ must_raise Kitchen::InstanceFailure
971
+ end
972
+
973
+ it "populates the InstanceFailure message" do
974
+ begin
975
+ instance.public_send(action)
976
+ rescue Kitchen::Error => e
977
+ e.message.must_match regex_for(
978
+ "Create failed on instance #{instance.to_str}")
979
+ end
980
+ end
981
+
982
+ it "logs the failure" do
983
+ begin
984
+ instance.public_send(action)
985
+ rescue Kitchen::Error
986
+ true # no need to act here
987
+ end
988
+
989
+ logger_io.string.must_match regex_for(
990
+ "Create failed on instance #{instance.to_str}")
991
+ end
992
+ end
993
+
994
+ describe "on driver crash with unexpected exception class" do
995
+
996
+ before do
997
+ driver.stubs(:create).raises(RuntimeError, "watwat")
998
+ end
999
+
1000
+ it "write the state file with last action" do
1001
+ begin
1002
+ instance.public_send(action)
1003
+ rescue Kitchen::Error
1004
+ true # no need to act here
1005
+ end
1006
+
1007
+ state_file.read[:last_action].must_be_nil
1008
+ end
1009
+
1010
+ it "raises an ActionFailed" do
1011
+ proc { instance.public_send(action) }.
1012
+ must_raise Kitchen::ActionFailed
1013
+ end
1014
+
1015
+ it "populates the ActionFailed message" do
1016
+ begin
1017
+ instance.public_send(action)
1018
+ rescue Kitchen::Error => e
1019
+ e.message.must_match regex_for(
1020
+ "Failed to complete #create action: [watwat]")
1021
+ end
1022
+ end
1023
+
1024
+ it "logs the failure" do
1025
+ begin
1026
+ instance.public_send(action)
1027
+ rescue Kitchen::Error
1028
+ true # no need to act here
1029
+ end
1030
+
1031
+ logger_io.string.must_match regex_for(
1032
+ "Create failed on instance #{instance.to_str}")
1033
+ end
1034
+ end
1035
+ end
1036
+
1037
+ describe "crashes preserve last action for desired verify action" do
1038
+
1039
+ before do
1040
+ verifier.stubs(:call).raises(Kitchen::ActionFailed, "death")
1041
+ end
1042
+
1043
+ [:create, :converge, :setup].each do |action|
1044
+
1045
+ it "for last state #{action}" do
1046
+ state_file.write(:last_action => action.to_s)
1047
+ begin
1048
+ instance.verify
1049
+ rescue Kitchen::Error
1050
+ true # no need to act here
1051
+ end
1052
+
1053
+ state_file.read[:last_action].must_equal "setup"
1054
+ end
1055
+ end
1056
+
1057
+ it "for last state verify" do
1058
+ state_file.write(:last_action => "verify")
1059
+ begin
1060
+ instance.verify
1061
+ rescue Kitchen::Error
1062
+ true # no need to act here
1063
+ end
1064
+
1065
+ state_file.read[:last_action].must_equal "verify"
1066
+ end
1067
+ end
1068
+
1069
+ describe "on drivers with serial actions" do
1070
+
1071
+ let(:driver) { SerialDummyDriver.new({}) }
1072
+
1073
+ it "runs in a synchronized block for serial actions" do
1074
+ instance.test
1075
+
1076
+ driver.action_in_mutex[:create].must_equal true
1077
+ driver.action_in_mutex[:destroy].must_equal true
1078
+ end
1079
+ end
1080
+
1081
+ describe "with legacy Driver::SSHBase subclasses" do
1082
+
1083
+ let(:driver) { LegacyDriver.new({}) }
1084
+
1085
+ describe "#converge" do
1086
+
1087
+ describe "with no state" do
1088
+
1089
+ it "calls Driver#create and Driver#converge with empty state hash" do
1090
+ driver.expects(:create).with(Hash.new)
1091
+ driver.expects(:converge).
1092
+ with { |state| state[:last_action] == "create" }
1093
+
1094
+ instance.converge
1095
+ end
1096
+ end
1097
+
1098
+ describe "with last action of create" do
1099
+
1100
+ before { state_file.write(:last_action => "create") }
1101
+
1102
+ it "calls Driver#converge with state hash" do
1103
+ driver.expects(:converge).
1104
+ with { |state| state[:last_action] == "create" }
1105
+
1106
+ instance.converge
1107
+ end
1108
+ end
1109
+
1110
+ describe "with last action of converge" do
1111
+
1112
+ before { state_file.write(:last_action => "converge") }
1113
+
1114
+ it "calls Driver#converge with state hash" do
1115
+ driver.expects(:converge).
1116
+ with { |state| state[:last_action] == "converge" }
1117
+
1118
+ instance.converge
1119
+ end
1120
+ end
1121
+ end
1122
+
1123
+ describe "#setup" do
1124
+
1125
+ describe "with no state" do
1126
+
1127
+ it "calls create, converge, and setup with empty state hash" do
1128
+ driver.expects(:create).with(Hash.new)
1129
+ driver.expects(:converge).
1130
+ with { |state| state[:last_action] == "create" }
1131
+ driver.expects(:setup).
1132
+ with { |state| state[:last_action] == "converge" }
1133
+
1134
+ instance.setup
1135
+ end
1136
+ end
1137
+
1138
+ describe "with last action of create" do
1139
+
1140
+ before { state_file.write(:last_action => "create") }
1141
+
1142
+ it "calls Provisioner#call and setup with state hash" do
1143
+ driver.expects(:converge).
1144
+ with { |state| state[:last_action] == "create" }
1145
+ driver.expects(:setup).
1146
+ with { |state| state[:last_action] == "converge" }
1147
+
1148
+ instance.setup
1149
+ end
1150
+ end
1151
+
1152
+ describe "with last action of converge" do
1153
+
1154
+ before { state_file.write(:last_action => "converge") }
1155
+
1156
+ it "calls Driver#setup with state hash" do
1157
+ driver.expects(:setup).
1158
+ with { |state| state[:last_action] == "converge" }
1159
+
1160
+ instance.setup
1161
+ end
1162
+ end
1163
+
1164
+ describe "with last action of setup" do
1165
+
1166
+ before { state_file.write(:last_action => "setup") }
1167
+
1168
+ it "calls Driver#setup with state hash" do
1169
+ driver.expects(:setup).
1170
+ with { |state| state[:last_action] == "setup" }
1171
+
1172
+ instance.setup
1173
+ end
1174
+ end
1175
+ end
1176
+
1177
+ describe "#verify" do
1178
+
1179
+ describe "with no state" do
1180
+
1181
+ it "calls create, converge, setup, and verify with empty state hash" do
1182
+ driver.expects(:create).with(Hash.new)
1183
+ driver.expects(:converge).
1184
+ with { |state| state[:last_action] == "create" }
1185
+ driver.expects(:setup).
1186
+ with { |state| state[:last_action] == "converge" }
1187
+ driver.expects(:verify).
1188
+ with { |state| state[:last_action] == "setup" }
1189
+
1190
+ instance.verify
1191
+ end
1192
+ end
1193
+
1194
+ describe "with last of create" do
1195
+
1196
+ before { state_file.write(:last_action => "create") }
1197
+
1198
+ it "calls converge, setup, and verify with state hash" do
1199
+ driver.expects(:converge).
1200
+ with { |state| state[:last_action] == "create" }
1201
+ driver.expects(:setup).
1202
+ with { |state| state[:last_action] == "converge" }
1203
+ driver.expects(:verify).
1204
+ with { |state| state[:last_action] == "setup" }
1205
+
1206
+ instance.verify
1207
+ end
1208
+ end
1209
+
1210
+ describe "with last of converge" do
1211
+
1212
+ before { state_file.write(:last_action => "converge") }
1213
+
1214
+ it "calls Driver#setup, and verify with state hash" do
1215
+ driver.expects(:setup).
1216
+ with { |state| state[:last_action] == "converge" }
1217
+ driver.expects(:verify).
1218
+ with { |state| state[:last_action] == "setup" }
1219
+
1220
+ instance.verify
1221
+ end
1222
+ end
1223
+
1224
+ describe "with last of setup" do
1225
+
1226
+ before { state_file.write(:last_action => "setup") }
1227
+
1228
+ it "calls Driver#verify with state hash" do
1229
+ driver.expects(:verify).
1230
+ with { |state| state[:last_action] == "setup" }
1231
+
1232
+ instance.verify
1233
+ end
1234
+ end
1235
+
1236
+ describe "with last of verify" do
1237
+
1238
+ before { state_file.write(:last_action => "verify") }
1239
+
1240
+ it "calls Driver#verify with state hash" do
1241
+ driver.expects(:verify).
1242
+ with { |state| state[:last_action] == "verify" }
1243
+
1244
+ instance.verify
1245
+ end
1246
+ end
1247
+ end
1248
+
1249
+ describe "#test" do
1250
+
1251
+ describe "with no state" do
1252
+
1253
+ it "calls destroy, create, converge, setup, verify, destroy" do
1254
+ driver.expects(:destroy)
1255
+ driver.expects(:create)
1256
+ driver.expects(:converge)
1257
+ driver.expects(:setup)
1258
+ driver.expects(:verify)
1259
+ driver.expects(:destroy)
1260
+
1261
+ instance.test
1262
+ end
1263
+ end
1264
+
1265
+ [:create, :converge, :setup, :verify].each do |action|
1266
+
1267
+ describe "with last action of #{action}" do
1268
+
1269
+ before { state_file.write(:last_action => action) }
1270
+
1271
+ it "calls destroy, create, converge, setup, verify, destroy" do
1272
+ driver.expects(:destroy)
1273
+ driver.expects(:create)
1274
+ driver.expects(:converge)
1275
+ driver.expects(:setup)
1276
+ driver.expects(:verify)
1277
+ driver.expects(:destroy)
1278
+
1279
+ instance.test
1280
+ end
1281
+ end
1282
+ end
1283
+
1284
+ describe "with destroy mode of never" do
1285
+
1286
+ it "calls destroy, create, converge, setup, verify" do
1287
+ driver.expects(:destroy).once
1288
+ driver.expects(:create)
1289
+ driver.expects(:converge)
1290
+ driver.expects(:setup)
1291
+ driver.expects(:verify)
1292
+
1293
+ instance.test(:never)
1294
+ end
1295
+ end
1296
+
1297
+ describe "with destroy mode of always" do
1298
+
1299
+ it "calls destroy at even when action fails" do
1300
+ driver.expects(:destroy)
1301
+ driver.expects(:create)
1302
+ driver.expects(:converge).raises(Kitchen::ActionFailed)
1303
+ driver.expects(:destroy)
1304
+
1305
+ begin
1306
+ instance.test(:always)
1307
+ rescue # rubocop:disable Lint/HandleExceptions
1308
+ end
1309
+ end
1310
+ end
1311
+ end
1312
+
1313
+ it "#login executes the driver's login_command" do
1314
+ state_file.write(:last_action => "create")
1315
+ driver.stubs(:login_command).with(:last_action => "create").
1316
+ returns(Kitchen::LoginCommand.new("echo", ["hello"], :purple => true))
1317
+ Kernel.expects(:exec).with("echo", "hello", :purple => true)
1318
+
1319
+ instance.login
1320
+ end
1321
+ end
1322
+ end
1323
+
1324
+ describe Kitchen::Instance::FSM do
1325
+
1326
+ let(:fsm) { Kitchen::Instance::FSM }
1327
+
1328
+ describe ".actions" do
1329
+
1330
+ it "passing nils returns destroy" do
1331
+ fsm.actions(nil, nil).must_equal [:destroy]
1332
+ end
1333
+
1334
+ it "accepts a string for desired argument" do
1335
+ fsm.actions(nil, "create").must_equal [:create]
1336
+ end
1337
+
1338
+ it "accepts a symbol for desired argument" do
1339
+ fsm.actions(nil, :create).must_equal [:create]
1340
+ end
1341
+
1342
+ it "starting from no state to create returns create" do
1343
+ fsm.actions(nil, :create).must_equal [:create]
1344
+ end
1345
+
1346
+ it "starting from :create to create returns create" do
1347
+ fsm.actions(:create, :create).must_equal [:create]
1348
+ end
1349
+
1350
+ it "starting from no state to converge returns create, converge" do
1351
+ fsm.actions(nil, :converge).must_equal [:create, :converge]
1352
+ end
1353
+
1354
+ it "starting from create to converge returns converge" do
1355
+ fsm.actions(:create, :converge).must_equal [:converge]
1356
+ end
1357
+
1358
+ it "starting from converge to converge returns converge" do
1359
+ fsm.actions(:converge, :converge).must_equal [:converge]
1360
+ end
1361
+
1362
+ it "starting from no state to setup returns create, converge, setup" do
1363
+ fsm.actions(nil, :setup).must_equal [:create, :converge, :setup]
1364
+ end
1365
+
1366
+ it "starting from create to setup returns converge, setup" do
1367
+ fsm.actions(:create, :setup).must_equal [:converge, :setup]
1368
+ end
1369
+
1370
+ it "starting from converge to setup returns setup" do
1371
+ fsm.actions(:converge, :setup).must_equal [:setup]
1372
+ end
1373
+
1374
+ it "starting from setup to setup return setup" do
1375
+ fsm.actions(:setup, :setup).must_equal [:setup]
1376
+ end
1377
+
1378
+ it "starting from no state to verify returns create, converge, setup, verify" do
1379
+ fsm.actions(nil, :verify).must_equal [:create, :converge, :setup, :verify]
1380
+ end
1381
+
1382
+ it "starting from create to verify returns converge, setup, verify" do
1383
+ fsm.actions(:create, :verify).must_equal [:converge, :setup, :verify]
1384
+ end
1385
+
1386
+ it "starting from converge to verify returns setup, verify" do
1387
+ fsm.actions(:converge, :verify).must_equal [:setup, :verify]
1388
+ end
1389
+
1390
+ it "starting from setup to verify returns verify" do
1391
+ fsm.actions(:setup, :verify).must_equal [:verify]
1392
+ end
1393
+
1394
+ it "starting from verify to verify returns verify" do
1395
+ fsm.actions(:verify, :verify).must_equal [:verify]
1396
+ end
1397
+
1398
+ [:verify, :setup, :converge].each do |s|
1399
+ it "starting from #{s} to create returns create" do
1400
+ fsm.actions(s, :create).must_equal [:create]
1401
+ end
1402
+ end
1403
+
1404
+ [:verify, :setup].each do |s|
1405
+ it "starting from #{s} to converge returns converge" do
1406
+ fsm.actions(s, :converge).must_equal [:converge]
1407
+ end
1408
+ end
1409
+
1410
+ it "starting from verify to setup returns setup" do
1411
+ fsm.actions(:verify, :setup).must_equal [:setup]
1412
+ end
1413
+ end
1414
+ end
1415
+
1416
+ def regex_for(string)
1417
+ Regexp.new(Regexp.escape(string))
1418
+ end
1419
+ end