test-kitchen 1.7.0 → 1.7.1.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -8
  3. data/.gitattributes +3 -0
  4. data/.github/ISSUE_TEMPLATE.md +55 -55
  5. data/.gitignore +28 -28
  6. data/.kitchen.ci.yml +23 -23
  7. data/.kitchen.proxy.yml +27 -27
  8. data/.rubocop.yml +3 -3
  9. data/.travis.yml +70 -70
  10. data/.yardopts +3 -3
  11. data/Berksfile +3 -3
  12. data/CHANGELOG.md +1090 -1083
  13. data/CONTRIBUTING.md +14 -14
  14. data/Gemfile +19 -19
  15. data/Gemfile.proxy_tests +4 -4
  16. data/Guardfile +42 -42
  17. data/LICENSE +15 -15
  18. data/MAINTAINERS.md +23 -23
  19. data/README.md +135 -135
  20. data/Rakefile +61 -61
  21. data/appveyor.yml +44 -44
  22. data/features/kitchen_action_commands.feature +164 -164
  23. data/features/kitchen_command.feature +16 -16
  24. data/features/kitchen_console_command.feature +34 -34
  25. data/features/kitchen_defaults.feature +38 -38
  26. data/features/kitchen_diagnose_command.feature +96 -96
  27. data/features/kitchen_driver_create_command.feature +64 -64
  28. data/features/kitchen_driver_discover_command.feature +25 -25
  29. data/features/kitchen_help_command.feature +16 -16
  30. data/features/kitchen_init_command.feature +274 -274
  31. data/features/kitchen_list_command.feature +104 -104
  32. data/features/kitchen_login_command.feature +62 -62
  33. data/features/kitchen_sink_command.feature +30 -30
  34. data/features/kitchen_test_command.feature +88 -88
  35. data/features/step_definitions/gem_steps.rb +36 -36
  36. data/features/step_definitions/git_steps.rb +5 -5
  37. data/features/step_definitions/output_steps.rb +5 -5
  38. data/features/support/env.rb +75 -75
  39. data/lib/kitchen.rb +150 -150
  40. data/lib/kitchen/base64_stream.rb +55 -55
  41. data/lib/kitchen/cli.rb +419 -419
  42. data/lib/kitchen/collection.rb +55 -55
  43. data/lib/kitchen/color.rb +65 -65
  44. data/lib/kitchen/command.rb +185 -185
  45. data/lib/kitchen/command/action.rb +45 -45
  46. data/lib/kitchen/command/console.rb +58 -58
  47. data/lib/kitchen/command/diagnose.rb +92 -92
  48. data/lib/kitchen/command/driver_discover.rb +105 -105
  49. data/lib/kitchen/command/exec.rb +41 -41
  50. data/lib/kitchen/command/list.rb +119 -119
  51. data/lib/kitchen/command/login.rb +43 -43
  52. data/lib/kitchen/command/sink.rb +54 -54
  53. data/lib/kitchen/command/test.rb +51 -51
  54. data/lib/kitchen/config.rb +322 -322
  55. data/lib/kitchen/configurable.rb +529 -529
  56. data/lib/kitchen/data_munger.rb +959 -959
  57. data/lib/kitchen/diagnostic.rb +141 -141
  58. data/lib/kitchen/driver.rb +56 -56
  59. data/lib/kitchen/driver/base.rb +134 -134
  60. data/lib/kitchen/driver/dummy.rb +108 -108
  61. data/lib/kitchen/driver/proxy.rb +72 -72
  62. data/lib/kitchen/driver/ssh_base.rb +357 -357
  63. data/lib/kitchen/errors.rb +229 -229
  64. data/lib/kitchen/generator/driver_create.rb +177 -177
  65. data/lib/kitchen/generator/init.rb +296 -296
  66. data/lib/kitchen/instance.rb +662 -662
  67. data/lib/kitchen/lazy_hash.rb +142 -142
  68. data/lib/kitchen/loader/yaml.rb +349 -349
  69. data/lib/kitchen/logger.rb +423 -423
  70. data/lib/kitchen/logging.rb +56 -56
  71. data/lib/kitchen/login_command.rb +52 -52
  72. data/lib/kitchen/metadata_chopper.rb +52 -52
  73. data/lib/kitchen/platform.rb +67 -67
  74. data/lib/kitchen/provisioner.rb +54 -54
  75. data/lib/kitchen/provisioner/base.rb +236 -236
  76. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  77. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  78. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  79. data/lib/kitchen/provisioner/chef_apply.rb +124 -124
  80. data/lib/kitchen/provisioner/chef_base.rb +341 -341
  81. data/lib/kitchen/provisioner/chef_solo.rb +88 -88
  82. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  83. data/lib/kitchen/provisioner/dummy.rb +79 -79
  84. data/lib/kitchen/provisioner/shell.rb +138 -138
  85. data/lib/kitchen/rake_tasks.rb +63 -63
  86. data/lib/kitchen/shell_out.rb +93 -93
  87. data/lib/kitchen/ssh.rb +276 -276
  88. data/lib/kitchen/state_file.rb +120 -120
  89. data/lib/kitchen/suite.rb +51 -51
  90. data/lib/kitchen/thor_tasks.rb +66 -66
  91. data/lib/kitchen/transport.rb +54 -54
  92. data/lib/kitchen/transport/base.rb +176 -176
  93. data/lib/kitchen/transport/dummy.rb +79 -79
  94. data/lib/kitchen/transport/ssh.rb +364 -364
  95. data/lib/kitchen/transport/winrm.rb +486 -486
  96. data/lib/kitchen/util.rb +147 -147
  97. data/lib/kitchen/verifier.rb +55 -55
  98. data/lib/kitchen/verifier/base.rb +235 -235
  99. data/lib/kitchen/verifier/busser.rb +277 -277
  100. data/lib/kitchen/verifier/dummy.rb +79 -79
  101. data/lib/kitchen/verifier/shell.rb +101 -101
  102. data/lib/kitchen/version.rb +21 -21
  103. data/lib/vendor/hash_recursive_merge.rb +82 -82
  104. data/spec/kitchen/base64_stream_spec.rb +77 -77
  105. data/spec/kitchen/cli_spec.rb +56 -56
  106. data/spec/kitchen/collection_spec.rb +80 -80
  107. data/spec/kitchen/color_spec.rb +54 -54
  108. data/spec/kitchen/config_spec.rb +408 -408
  109. data/spec/kitchen/configurable_spec.rb +1095 -1095
  110. data/spec/kitchen/data_munger_spec.rb +2694 -2694
  111. data/spec/kitchen/diagnostic_spec.rb +129 -129
  112. data/spec/kitchen/driver/base_spec.rb +121 -121
  113. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  114. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  115. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  116. data/spec/kitchen/driver_spec.rb +112 -112
  117. data/spec/kitchen/errors_spec.rb +309 -309
  118. data/spec/kitchen/instance_spec.rb +1419 -1419
  119. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  120. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  121. data/spec/kitchen/logger_spec.rb +429 -429
  122. data/spec/kitchen/logging_spec.rb +59 -59
  123. data/spec/kitchen/login_command_spec.rb +68 -68
  124. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  125. data/spec/kitchen/platform_spec.rb +89 -89
  126. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  127. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  128. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1161
  129. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  130. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  131. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  132. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  133. data/spec/kitchen/provisioner_spec.rb +107 -107
  134. data/spec/kitchen/shell_out_spec.rb +150 -150
  135. data/spec/kitchen/ssh_spec.rb +693 -693
  136. data/spec/kitchen/state_file_spec.rb +129 -129
  137. data/spec/kitchen/suite_spec.rb +62 -62
  138. data/spec/kitchen/transport/base_spec.rb +89 -89
  139. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  140. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  141. data/spec/kitchen/transport_spec.rb +112 -112
  142. data/spec/kitchen/util_spec.rb +165 -165
  143. data/spec/kitchen/verifier/base_spec.rb +362 -362
  144. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  145. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  146. data/spec/kitchen/verifier/shell_spec.rb +160 -160
  147. data/spec/kitchen/verifier_spec.rb +120 -120
  148. data/spec/kitchen_spec.rb +114 -114
  149. data/spec/spec_helper.rb +85 -85
  150. data/spec/support/powershell_max_size_spec.rb +40 -40
  151. data/support/busser_install_command.ps1 +14 -14
  152. data/support/busser_install_command.sh +14 -14
  153. data/support/chef-client-zero.rb +77 -77
  154. data/support/chef_base_init_command.ps1 +18 -18
  155. data/support/chef_base_init_command.sh +2 -2
  156. data/support/chef_base_install_command.ps1 +85 -85
  157. data/support/chef_base_install_command.sh +229 -229
  158. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  159. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  160. data/support/download_helpers.sh +109 -109
  161. data/support/dummy-validation.pem +27 -27
  162. data/templates/driver/CHANGELOG.md.erb +3 -3
  163. data/templates/driver/Gemfile.erb +3 -3
  164. data/templates/driver/README.md.erb +64 -64
  165. data/templates/driver/Rakefile.erb +21 -21
  166. data/templates/driver/driver.rb.erb +23 -23
  167. data/templates/driver/gemspec.erb +29 -29
  168. data/templates/driver/gitignore.erb +17 -17
  169. data/templates/driver/license_apachev2.erb +15 -15
  170. data/templates/driver/license_lgplv3.erb +16 -16
  171. data/templates/driver/license_mit.erb +22 -22
  172. data/templates/driver/license_reserved.erb +5 -5
  173. data/templates/driver/tailor.erb +4 -4
  174. data/templates/driver/travis.yml.erb +11 -11
  175. data/templates/driver/version.rb.erb +12 -12
  176. data/templates/init/chefignore.erb +1 -1
  177. data/templates/init/kitchen.yml.erb +18 -18
  178. data/test-kitchen.gemspec +62 -62
  179. data/test/integration/default/default_spec.rb +3 -3
  180. data/testing_windows.md +37 -37
  181. metadata +5 -4
@@ -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