test-kitchen 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +1 -1
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +20 -9
  5. data/CHANGELOG.md +219 -108
  6. data/Gemfile +10 -6
  7. data/Guardfile +38 -9
  8. data/README.md +11 -1
  9. data/Rakefile +21 -37
  10. data/bin/kitchen +4 -4
  11. data/features/kitchen_action_commands.feature +161 -0
  12. data/features/kitchen_console_command.feature +34 -0
  13. data/features/kitchen_diagnose_command.feature +64 -0
  14. data/features/kitchen_init_command.feature +29 -17
  15. data/features/kitchen_list_command.feature +2 -2
  16. data/features/kitchen_login_command.feature +56 -0
  17. data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
  18. data/features/kitchen_test_command.feature +88 -0
  19. data/features/step_definitions/gem_steps.rb +8 -6
  20. data/features/step_definitions/git_steps.rb +4 -2
  21. data/features/step_definitions/output_steps.rb +5 -0
  22. data/features/support/env.rb +12 -9
  23. data/lib/kitchen.rb +60 -38
  24. data/lib/kitchen/base64_stream.rb +55 -0
  25. data/lib/kitchen/busser.rb +124 -58
  26. data/lib/kitchen/cli.rb +121 -38
  27. data/lib/kitchen/collection.rb +3 -3
  28. data/lib/kitchen/color.rb +4 -4
  29. data/lib/kitchen/command.rb +78 -11
  30. data/lib/kitchen/command/action.rb +3 -2
  31. data/lib/kitchen/command/console.rb +12 -5
  32. data/lib/kitchen/command/diagnose.rb +17 -3
  33. data/lib/kitchen/command/driver_discover.rb +26 -7
  34. data/lib/kitchen/command/exec.rb +41 -0
  35. data/lib/kitchen/command/list.rb +44 -14
  36. data/lib/kitchen/command/login.rb +2 -1
  37. data/lib/kitchen/command/sink.rb +2 -1
  38. data/lib/kitchen/command/test.rb +5 -4
  39. data/lib/kitchen/config.rb +146 -14
  40. data/lib/kitchen/configurable.rb +314 -0
  41. data/lib/kitchen/data_munger.rb +522 -18
  42. data/lib/kitchen/diagnostic.rb +43 -4
  43. data/lib/kitchen/driver.rb +4 -4
  44. data/lib/kitchen/driver/base.rb +80 -115
  45. data/lib/kitchen/driver/dummy.rb +34 -6
  46. data/lib/kitchen/driver/proxy.rb +14 -3
  47. data/lib/kitchen/driver/ssh_base.rb +61 -7
  48. data/lib/kitchen/errors.rb +109 -9
  49. data/lib/kitchen/generator/driver_create.rb +39 -5
  50. data/lib/kitchen/generator/init.rb +130 -45
  51. data/lib/kitchen/instance.rb +162 -28
  52. data/lib/kitchen/lazy_hash.rb +79 -7
  53. data/lib/kitchen/loader/yaml.rb +159 -27
  54. data/lib/kitchen/logger.rb +267 -21
  55. data/lib/kitchen/logging.rb +30 -3
  56. data/lib/kitchen/login_command.rb +11 -2
  57. data/lib/kitchen/metadata_chopper.rb +2 -2
  58. data/lib/kitchen/provisioner.rb +4 -4
  59. data/lib/kitchen/provisioner/base.rb +107 -103
  60. data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
  61. data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
  62. data/lib/kitchen/provisioner/chef_base.rb +206 -167
  63. data/lib/kitchen/provisioner/chef_solo.rb +25 -7
  64. data/lib/kitchen/provisioner/chef_zero.rb +105 -29
  65. data/lib/kitchen/provisioner/dummy.rb +1 -1
  66. data/lib/kitchen/provisioner/shell.rb +21 -6
  67. data/lib/kitchen/rake_tasks.rb +8 -3
  68. data/lib/kitchen/shell_out.rb +15 -18
  69. data/lib/kitchen/ssh.rb +122 -27
  70. data/lib/kitchen/state_file.rb +24 -7
  71. data/lib/kitchen/thor_tasks.rb +9 -4
  72. data/lib/kitchen/util.rb +43 -118
  73. data/lib/kitchen/version.rb +1 -1
  74. data/lib/vendor/hash_recursive_merge.rb +10 -2
  75. data/spec/kitchen/base64_stream_spec.rb +77 -0
  76. data/spec/kitchen/busser_spec.rb +490 -0
  77. data/spec/kitchen/collection_spec.rb +10 -10
  78. data/spec/kitchen/color_spec.rb +2 -2
  79. data/spec/kitchen/config_spec.rb +234 -62
  80. data/spec/kitchen/configurable_spec.rb +490 -0
  81. data/spec/kitchen/data_munger_spec.rb +1070 -862
  82. data/spec/kitchen/diagnostic_spec.rb +79 -0
  83. data/spec/kitchen/driver/base_spec.rb +80 -85
  84. data/spec/kitchen/driver/dummy_spec.rb +43 -14
  85. data/spec/kitchen/driver/proxy_spec.rb +134 -0
  86. data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
  87. data/spec/kitchen/driver_spec.rb +15 -15
  88. data/spec/kitchen/errors_spec.rb +309 -0
  89. data/spec/kitchen/instance_spec.rb +143 -46
  90. data/spec/kitchen/lazy_hash_spec.rb +36 -9
  91. data/spec/kitchen/loader/yaml_spec.rb +237 -226
  92. data/spec/kitchen/logger_spec.rb +419 -0
  93. data/spec/kitchen/logging_spec.rb +59 -0
  94. data/spec/kitchen/login_command_spec.rb +49 -0
  95. data/spec/kitchen/metadata_chopper_spec.rb +82 -0
  96. data/spec/kitchen/platform_spec.rb +4 -4
  97. data/spec/kitchen/provisioner/base_spec.rb +65 -125
  98. data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
  99. data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
  100. data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
  101. data/spec/kitchen/provisioner/shell_spec.rb +269 -0
  102. data/spec/kitchen/provisioner_spec.rb +6 -6
  103. data/spec/kitchen/shell_out_spec.rb +143 -0
  104. data/spec/kitchen/ssh_spec.rb +683 -0
  105. data/spec/kitchen/state_file_spec.rb +28 -21
  106. data/spec/kitchen/suite_spec.rb +7 -7
  107. data/spec/kitchen/util_spec.rb +68 -10
  108. data/spec/kitchen_spec.rb +107 -0
  109. data/spec/spec_helper.rb +18 -13
  110. data/support/chef-client-zero.rb +10 -9
  111. data/support/chef_helpers.sh +16 -0
  112. data/support/download_helpers.sh +109 -0
  113. data/test-kitchen.gemspec +42 -33
  114. metadata +107 -33
@@ -16,13 +16,13 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require_relative '../spec_helper'
19
+ require_relative "../spec_helper"
20
20
 
21
- require 'kitchen/errors'
22
- require 'kitchen/logging'
23
- require 'kitchen/shell_out'
24
- require 'kitchen/driver'
25
- require 'kitchen/driver/base'
21
+ require "kitchen/errors"
22
+ require "kitchen/logging"
23
+ require "kitchen/shell_out"
24
+ require "kitchen/driver"
25
+ require "kitchen/driver/base"
26
26
 
27
27
  module Kitchen
28
28
 
@@ -63,28 +63,28 @@ describe Kitchen::Driver do
63
63
  end
64
64
 
65
65
  it "returns a driver object of the correct class" do
66
- driver = Kitchen::Driver.for_plugin('coolbeans', {})
66
+ driver = Kitchen::Driver.for_plugin("coolbeans", {})
67
67
 
68
68
  driver.must_be_kind_of Kitchen::Driver::Coolbeans
69
69
  end
70
70
 
71
71
  it "returns a driver initialized with its config" do
72
- driver = Kitchen::Driver.for_plugin('coolbeans', { :jelly => 'beans' })
72
+ driver = Kitchen::Driver.for_plugin("coolbeans", :jelly => "beans")
73
73
 
74
- driver[:jelly].must_equal 'beans'
74
+ driver[:jelly].must_equal "beans"
75
75
  end
76
76
 
77
77
  it "calls #verify_dependencies on the driver object" do
78
- driver = Kitchen::Driver.for_plugin('it_depends', {})
78
+ driver = Kitchen::Driver.for_plugin("it_depends", {})
79
79
 
80
80
  driver.verify_call_count.must_equal 1
81
81
  end
82
82
 
83
83
  it "calls #verify_dependencies once per driver require" do
84
84
  Kitchen::Driver.stubs(:require).returns(true, false)
85
- driver1 = Kitchen::Driver.for_plugin('it_depends', {})
85
+ driver1 = Kitchen::Driver.for_plugin("it_depends", {})
86
86
  driver1.verify_call_count.must_equal 1
87
- driver2 = Kitchen::Driver.for_plugin('it_depends', {})
87
+ driver2 = Kitchen::Driver.for_plugin("it_depends", {})
88
88
 
89
89
  driver2.verify_call_count.must_equal 0
90
90
  end
@@ -92,19 +92,19 @@ describe Kitchen::Driver do
92
92
  it "raises ClientError if the driver could not be required" do
93
93
  Kitchen::Driver.stubs(:require).raises(LoadError)
94
94
 
95
- proc { Kitchen::Driver.for_plugin('coolbeans', {}) }.
95
+ proc { Kitchen::Driver.for_plugin("coolbeans", {}) }.
96
96
  must_raise Kitchen::ClientError
97
97
  end
98
98
 
99
99
  it "raises ClientError if the driver's class constant could not be found" do
100
100
  Kitchen::Driver.stubs(:require).returns(true) # pretend require worked
101
101
 
102
- proc { Kitchen::Driver.for_plugin('nope', {}) }.
102
+ proc { Kitchen::Driver.for_plugin("nope", {}) }.
103
103
  must_raise Kitchen::ClientError
104
104
  end
105
105
 
106
106
  it "raises UserError if #verify_dependencies fails" do
107
- proc { Kitchen::Driver.for_plugin('unstable_depends', {}) }.
107
+ proc { Kitchen::Driver.for_plugin("unstable_depends", {}) }.
108
108
  must_raise Kitchen::UserError
109
109
  end
110
110
  end
@@ -0,0 +1,309 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2014, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../spec_helper"
20
+
21
+ require "kitchen"
22
+ require "kitchen/errors"
23
+
24
+ describe Kitchen::Error do
25
+
26
+ let(:exception) { Kitchen::StandardError.new("shoot") }
27
+
28
+ describe ".formatted_exception" do
29
+
30
+ it "returns an array of a formatted message" do
31
+ Kitchen::Error.formatted_exception(exception).must_equal([
32
+ "------Exception-------",
33
+ "Class: Kitchen::StandardError",
34
+ "Message: shoot",
35
+ "----------------------"
36
+ ])
37
+ end
38
+
39
+ it "takes a customized title" do
40
+ Kitchen::Error.formatted_exception(exception, "Trouble").first.
41
+ must_equal("-------Trouble--------")
42
+ end
43
+ end
44
+
45
+ describe ".formatted_exception" do
46
+
47
+ it "returns an array of a formatted message with a nil backtrace" do
48
+ Kitchen::Error.formatted_trace(exception).must_equal([
49
+ "------Exception-------",
50
+ "Class: Kitchen::StandardError",
51
+ "Message: shoot",
52
+ "------Backtrace-------",
53
+ nil,
54
+ "----------------------"
55
+ ])
56
+ end
57
+
58
+ it "returns an array containing the exception's backtrace" do
59
+ begin
60
+ raise Kitchen::StandardError, "shoot"
61
+ rescue => e
62
+ Kitchen::Error.formatted_trace(e)[4...-1].must_equal e.backtrace
63
+ end
64
+ end
65
+
66
+ it "returns an array containing a nested exception, if given" do
67
+ begin
68
+ raise IOError, "no disk, yo"
69
+ rescue
70
+ e = Kitchen::StandardError.new("shoot")
71
+
72
+ Kitchen::Error.formatted_trace(e).must_equal([
73
+ "------Exception-------",
74
+ "Class: Kitchen::StandardError",
75
+ "Message: shoot",
76
+ "---Nested Exception---",
77
+ "Class: IOError",
78
+ "Message: no disk, yo",
79
+ "------Backtrace-------",
80
+ nil,
81
+ "----------------------"
82
+ ])
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ describe Kitchen::StandardError do
89
+
90
+ it "is a kind of Kitchen::Error" do
91
+ Kitchen::StandardError.new("oops").must_be_kind_of Kitchen::Error
92
+ end
93
+
94
+ it "by default, sets original exception to the last raised exception" do
95
+ begin
96
+ raise IOError, "crap"
97
+ rescue
98
+ original = Kitchen::StandardError.new("oops").original
99
+ original.must_be_kind_of IOError
100
+ original.message.must_equal "crap"
101
+ end
102
+ end
103
+
104
+ it "can embed an exception when constructing" do
105
+ original = Kitchen::StandardError.new("durn", IOError.new("ack")).original
106
+ original.must_be_kind_of IOError
107
+ original.message.must_equal "ack"
108
+ end
109
+ end
110
+
111
+ [
112
+ Kitchen::UserError, Kitchen::ClientError, Kitchen::TransientFailure
113
+ ].each do |klass|
114
+ describe klass do
115
+
116
+ it "is a kind of Kitchen::StandardError" do
117
+ klass.new("oops").must_be_kind_of Kitchen::StandardError
118
+ end
119
+ end
120
+ end
121
+
122
+ [
123
+ Kitchen::ActionFailed, Kitchen::InstanceFailure
124
+ ].each do |klass|
125
+ describe klass do
126
+
127
+ it "is a kind of Kitchen::TransientFailure" do
128
+ klass.new("oops").must_be_kind_of Kitchen::TransientFailure
129
+ end
130
+ end
131
+ end
132
+
133
+ describe Kitchen do
134
+
135
+ describe ".with_friendly_errors" do
136
+
137
+ let(:logger_io) { StringIO.new }
138
+ let(:logger) { Kitchen::Logger.new(:logdev => logger_io) }
139
+
140
+ before do
141
+ Kitchen.stubs(:tty?).returns(true)
142
+ @orig_stderr = $stderr
143
+ $stderr = StringIO.new
144
+ @orig_logger = Kitchen.logger
145
+ Kitchen.logger = logger
146
+ end
147
+
148
+ after do
149
+ $stderr = @orig_stderr
150
+ Kitchen.logger = @orig_logger
151
+ end
152
+
153
+ describe "for instance failures" do
154
+
155
+ def go_boom
156
+ Kitchen.with_friendly_errors do
157
+ begin
158
+ raise IOError, "no stuff"
159
+ rescue
160
+ raise Kitchen::InstanceFailure, "cannot do that"
161
+ end
162
+ end
163
+ end
164
+
165
+ it "exits with 10" do
166
+ begin
167
+ go_boom
168
+ rescue SystemExit => e
169
+ e.status.must_equal 10
170
+ end
171
+ end
172
+
173
+ it "prints a message on STDERR" do
174
+ output = [
175
+ ">>>>>> cannot do that",
176
+ ">>>>>> ------Exception-------",
177
+ ">>>>>> Class: IOError",
178
+ ">>>>>> Message: no stuff",
179
+ ">>>>>> ----------------------"
180
+ ].map { |l| Kitchen::Color.colorize(l, :red) }.join("\n").concat("\n")
181
+
182
+ begin
183
+ go_boom
184
+ rescue SystemExit
185
+ $stderr.string.must_equal output
186
+ end
187
+ end
188
+
189
+ it "prints a message on STDERR without color" do
190
+ Kitchen.stubs(:tty?).returns(false)
191
+ output = [
192
+ ">>>>>> cannot do that",
193
+ ">>>>>> ------Exception-------",
194
+ ">>>>>> Class: IOError",
195
+ ">>>>>> Message: no stuff",
196
+ ">>>>>> ----------------------"
197
+ ].join("\n").concat("\n")
198
+
199
+ begin
200
+ go_boom
201
+ rescue SystemExit
202
+ $stderr.string.must_equal output
203
+ end
204
+ end
205
+
206
+ it "logs the exception message on the common logger's error severity" do
207
+ begin
208
+ go_boom
209
+ rescue SystemExit
210
+ logger_io.string.must_match(/ERROR -- Kitchen: cannot do that$/)
211
+ end
212
+ end
213
+
214
+ it "logs the exception message on debug, if set" do
215
+ logger.level = ::Logger::DEBUG
216
+
217
+ begin
218
+ go_boom
219
+ rescue SystemExit
220
+ logger_io.string.must_match(/DEBUG -- Kitchen: cannot do that$/)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "for unexpected failures" do
226
+
227
+ def go_boom
228
+ Kitchen.with_friendly_errors do
229
+ begin
230
+ raise IOError, "wtf?"
231
+ rescue
232
+ raise Kitchen::StandardError, "ah crap"
233
+ end
234
+ end
235
+ end
236
+
237
+ it "exits with 20" do
238
+ begin
239
+ go_boom
240
+ rescue SystemExit => e
241
+ e.status.must_equal 20
242
+ end
243
+ end
244
+
245
+ it "prints a message on STDERR" do
246
+ output = [
247
+ ">>>>>> ------Exception-------",
248
+ ">>>>>> Class: Kitchen::StandardError",
249
+ ">>>>>> Message: ah crap",
250
+ ">>>>>> ----------------------",
251
+ ">>>>>> Please see .kitchen/logs/kitchen.log for more details",
252
+ ">>>>>> Also try running `kitchen diagnose --all` for configuration\n"
253
+ ].map { |l| Kitchen::Color.colorize(l, :red) }.join("\n").concat("\n")
254
+
255
+ begin
256
+ go_boom
257
+ rescue SystemExit
258
+ $stderr.string.must_equal output
259
+ end
260
+ end
261
+
262
+ it "prints a message on STDERR without color" do
263
+ Kitchen.stubs(:tty?).returns(false)
264
+ output = [
265
+ ">>>>>> ------Exception-------",
266
+ ">>>>>> Class: Kitchen::StandardError",
267
+ ">>>>>> Message: ah crap",
268
+ ">>>>>> ----------------------",
269
+ ">>>>>> Please see .kitchen/logs/kitchen.log for more details",
270
+ ">>>>>> Also try running `kitchen diagnose --all` for configuration"
271
+ ].join("\n").concat("\n")
272
+
273
+ begin
274
+ go_boom
275
+ rescue SystemExit
276
+ $stderr.string.must_equal output
277
+ end
278
+ end
279
+
280
+ it "logs the exception message on the common logger's error severity" do
281
+ begin
282
+ go_boom
283
+ rescue SystemExit
284
+ logger_io.string.
285
+ must_match(/ERROR -- Kitchen: ------Exception-------$/)
286
+ logger_io.string.
287
+ must_match(/ERROR -- Kitchen: Class: Kitchen::StandardError$/)
288
+ logger_io.string.
289
+ must_match(/ERROR -- Kitchen: ------Backtrace-------$/)
290
+ end
291
+ end
292
+
293
+ it "logs the exception message on debug, if set" do
294
+ logger.level = ::Logger::DEBUG
295
+
296
+ begin
297
+ go_boom
298
+ rescue SystemExit
299
+ logger_io.string.
300
+ must_match(/DEBUG -- Kitchen: ------Exception-------$/)
301
+ logger_io.string.
302
+ must_match(/DEBUG -- Kitchen: Class: Kitchen::StandardError$/)
303
+ logger_io.string.
304
+ must_match(/DEBUG -- Kitchen: ------Backtrace-------$/)
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
@@ -16,21 +16,21 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
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'
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
30
 
31
31
  class DummyStateFile
32
32
 
33
- def initialize(*args) ; end
33
+ def initialize(*); end
34
34
 
35
35
  def read
36
36
  @_state = Hash.new unless @_state
@@ -44,6 +44,10 @@ class DummyStateFile
44
44
  def destroy
45
45
  @_state = nil
46
46
  end
47
+
48
+ def diagnose
49
+ Hash.new
50
+ end
47
51
  end
48
52
 
49
53
  class SerialDummyDriver < Kitchen::Driver::Dummy
@@ -100,11 +104,11 @@ describe Kitchen::Instance do
100
104
  end
101
105
 
102
106
  def suite(name = "suite")
103
- @suite ||= Kitchen::Suite.new({ :name => name })
107
+ @suite ||= Kitchen::Suite.new(:name => name)
104
108
  end
105
109
 
106
110
  def platform(name = "platform")
107
- @platform ||= Kitchen::Platform.new({ :name => name })
111
+ @platform ||= Kitchen::Platform.new(:name => name)
108
112
  end
109
113
 
110
114
  describe ".name_for" do
@@ -143,6 +147,21 @@ describe Kitchen::Instance do
143
147
  Kitchen::Instance.name_for(suite("_s__s_"), platform("pp_")).
144
148
  must_equal "-s--s--pp-"
145
149
  end
150
+
151
+ it "transforms forward slashes to dashes in suite name" do
152
+ Kitchen::Instance.name_for(suite("suite/ness"), platform("platform")).
153
+ must_equal "suite-ness-platform"
154
+ end
155
+
156
+ it "transforms forward slashes to dashes in platform name" do
157
+ Kitchen::Instance.name_for(suite("suite"), platform("platform/s")).
158
+ must_equal "suite-platform-s"
159
+ end
160
+
161
+ it "transforms forward slashes to dashes in suite and platform names" do
162
+ Kitchen::Instance.name_for(suite("/s//s/"), platform("pp/")).
163
+ must_equal "-s--s--pp-"
164
+ end
146
165
  end
147
166
 
148
167
  describe "#suite" do
@@ -244,13 +263,69 @@ describe Kitchen::Instance do
244
263
  end
245
264
 
246
265
  it "#login executes the driver's login_command" do
247
- driver.stubs(:login_command).with(Hash.new).
248
- returns(Kitchen::LoginCommand.new(["echo", "hello"], {:purple => true}))
249
- Kernel.expects(:exec).with("echo", "hello", {:purple => true})
266
+ state_file.write(:last_action => "create")
267
+ driver.stubs(:login_command).with(:last_action => "create").
268
+ returns(Kitchen::LoginCommand.new(%w[echo hello], :purple => true))
269
+ Kernel.expects(:exec).with("echo", "hello", :purple => true)
250
270
 
251
271
  instance.login
252
272
  end
253
273
 
274
+ it "#login raises a UserError if the instance is not created" do
275
+ state_file.write({})
276
+
277
+ proc { instance.login }.must_raise Kitchen::UserError
278
+ end
279
+
280
+ describe "#diagnose" do
281
+
282
+ it "returns a hash" do
283
+ instance.diagnose.must_be_instance_of Hash
284
+ end
285
+
286
+ it "sets :state_file key to state_file's diganose info" do
287
+ state_file.stubs(:diagnose).returns(:a => "b")
288
+
289
+ instance.diagnose[:state_file].must_equal(:a => "b")
290
+ end
291
+
292
+ it "sets :state_file key to :unknown if obj can't respond to #diagnose" do
293
+ opts[:state_file] = Class.new(state_file.class) {
294
+ undef_method :diagnose
295
+ }.new
296
+
297
+ instance.diagnose[:state_file].must_equal :unknown
298
+ end
299
+
300
+ it "sets :provisioner key to provisioner's diganose info" do
301
+ provisioner.stubs(:diagnose).returns(:a => "b")
302
+
303
+ instance.diagnose[:provisioner].must_equal(:a => "b")
304
+ end
305
+
306
+ it "sets :provisioner key to :unknown if obj can't respond to #diagnose" do
307
+ opts[:provisioner] = Class.new(provisioner.class) {
308
+ undef_method :diagnose
309
+ }.new
310
+
311
+ instance.diagnose[:provisioner].must_equal :unknown
312
+ end
313
+
314
+ it "sets :busser key to busser's diganose info" do
315
+ busser.stubs(:diagnose).returns(:a => "b")
316
+
317
+ instance.diagnose[:busser].must_equal(:a => "b")
318
+ end
319
+
320
+ it "sets :busser key to :unknown if obj can't respond to #diagnose" do
321
+ opts[:busser] = Class.new(busser.class) {
322
+ undef_method :diagnose
323
+ }.new(suite.name, {})
324
+
325
+ instance.diagnose[:busser].must_equal :unknown
326
+ end
327
+ end
328
+
254
329
  describe "performing actions" do
255
330
 
256
331
  describe "#create" do
@@ -286,7 +361,7 @@ describe Kitchen::Instance do
286
361
 
287
362
  describe "with last_action of create" do
288
363
 
289
- before { state_file.write({ :last_action => "create"}) }
364
+ before { state_file.write(:last_action => "create") }
290
365
 
291
366
  it "calls Driver#create with state hash" do
292
367
  driver.expects(:create).
@@ -337,7 +412,7 @@ describe Kitchen::Instance do
337
412
 
338
413
  describe "with last action of create" do
339
414
 
340
- before { state_file.write({ :last_action => "create"}) }
415
+ before { state_file.write(:last_action => "create") }
341
416
 
342
417
  it "calls Driver#converge with state hash" do
343
418
  driver.expects(:converge).
@@ -355,7 +430,7 @@ describe Kitchen::Instance do
355
430
 
356
431
  describe "with last action of converge" do
357
432
 
358
- before { state_file.write({ :last_action => "converge"}) }
433
+ before { state_file.write(:last_action => "converge") }
359
434
 
360
435
  it "calls Driver#converge with state hash" do
361
436
  driver.expects(:converge).
@@ -408,7 +483,7 @@ describe Kitchen::Instance do
408
483
 
409
484
  describe "with last action of create" do
410
485
 
411
- before { state_file.write({ :last_action => "create"}) }
486
+ before { state_file.write(:last_action => "create") }
412
487
 
413
488
  it "calls Driver#converge and setup with state hash" do
414
489
  driver.expects(:converge).
@@ -428,7 +503,7 @@ describe Kitchen::Instance do
428
503
 
429
504
  describe "with last action of converge" do
430
505
 
431
- before { state_file.write({ :last_action => "converge"}) }
506
+ before { state_file.write(:last_action => "converge") }
432
507
 
433
508
  it "calls Driver#setup with state hash" do
434
509
  driver.expects(:setup).
@@ -446,7 +521,7 @@ describe Kitchen::Instance do
446
521
 
447
522
  describe "with last action of setup" do
448
523
 
449
- before { state_file.write({ :last_action => "setup"}) }
524
+ before { state_file.write(:last_action => "setup") }
450
525
 
451
526
  it "calls Driver#setup with state hash" do
452
527
  driver.expects(:setup).
@@ -501,7 +576,7 @@ describe Kitchen::Instance do
501
576
 
502
577
  describe "with last of create" do
503
578
 
504
- before { state_file.write({ :last_action => "create"}) }
579
+ before { state_file.write(:last_action => "create") }
505
580
 
506
581
  it "calls Driver#converge, setup, and verify with state hash" do
507
582
  driver.expects(:converge).
@@ -523,7 +598,7 @@ describe Kitchen::Instance do
523
598
 
524
599
  describe "with last of converge" do
525
600
 
526
- before { state_file.write({ :last_action => "converge"}) }
601
+ before { state_file.write(:last_action => "converge") }
527
602
 
528
603
  it "calls Driver#setup, and verify with state hash" do
529
604
  driver.expects(:setup).
@@ -543,7 +618,7 @@ describe Kitchen::Instance do
543
618
 
544
619
  describe "with last of setup" do
545
620
 
546
- before { state_file.write({ :last_action => "setup"}) }
621
+ before { state_file.write(:last_action => "setup") }
547
622
 
548
623
  it "calls Driver#verify with state hash" do
549
624
  driver.expects(:verify).
@@ -561,7 +636,7 @@ describe Kitchen::Instance do
561
636
 
562
637
  describe "with last of verify" do
563
638
 
564
- before { state_file.write({ :last_action => "verify"}) }
639
+ before { state_file.write(:last_action => "verify") }
565
640
 
566
641
  it "calls Driver#verify with state hash" do
567
642
  driver.expects(:verify).
@@ -613,7 +688,7 @@ describe Kitchen::Instance do
613
688
 
614
689
  describe "with last_action of #{action}" do
615
690
 
616
- before { state_file.write({ :last_action => action}) }
691
+ before { state_file.write(:last_action => action) }
617
692
 
618
693
  it "calls Driver#create with state hash" do
619
694
  driver.expects(:destroy).
@@ -664,7 +739,7 @@ describe Kitchen::Instance do
664
739
 
665
740
  describe "with last action of #{action}" do
666
741
 
667
- before { state_file.write({ :last_action => action}) }
742
+ before { state_file.write(:last_action => action) }
668
743
 
669
744
  it "calls Driver#destroy, create, converge, setup, verify, destroy" do
670
745
  driver.expects(:destroy)
@@ -695,28 +770,44 @@ describe Kitchen::Instance do
695
770
  describe "with destroy mode of always" do
696
771
 
697
772
  it "calls Driver#destroy at even when action fails" do
698
- driver.stubs(:converge).raises(Kitchen::ActionFailed)
699
-
700
773
  driver.expects(:destroy)
701
774
  driver.expects(:create)
702
- driver.expects(:converge)
775
+ driver.expects(:converge).raises(Kitchen::ActionFailed)
703
776
  driver.expects(:destroy)
704
777
 
705
- instance.test(:always)
778
+ begin
779
+ instance.test(:always)
780
+ rescue # rubocop:disable Lint/HandleExceptions
781
+ end
706
782
  end
707
783
  end
708
784
 
709
785
  describe "with destroy mode of passing" do
710
786
 
711
787
  it "doesn't call Driver#destroy at when action fails" do
712
- skip "figure this one out"
713
- driver.stubs(:create).raises(Kitchen::ActionFailed, "death")
788
+ driver.stubs(:create).raises(Kitchen::ActionFailed)
714
789
 
715
- driver.expects(:destroy)
716
- driver.expects(:create)
790
+ driver.expects(:destroy).once
717
791
 
718
- instance.test(:passing)
792
+ begin
793
+ instance.test(:passing)
794
+ rescue # rubocop:disable Lint/HandleExceptions
795
+ end
796
+ end
797
+ end
798
+ end
799
+
800
+ describe "#remote_exec" do
801
+
802
+ before { state_file.write(:last_action => "create") }
803
+
804
+ it "calls Driver#remote_command with state and command" do
805
+ driver.expects(:remote_command).with do |state, command|
806
+ state.must_equal(:last_action => "create")
807
+ command.must_equal "uptime"
719
808
  end
809
+
810
+ instance.remote_exec("uptime")
720
811
  end
721
812
  end
722
813
 
@@ -731,7 +822,8 @@ describe Kitchen::Instance do
731
822
  it "write the state file with last action" do
732
823
  begin
733
824
  instance.public_send(action)
734
- rescue Kitchen::Error => e
825
+ rescue Kitchen::Error
826
+ true # no need to act here
735
827
  end
736
828
 
737
829
  state_file.read[:last_action].must_be_nil
@@ -754,7 +846,8 @@ describe Kitchen::Instance do
754
846
  it "logs the failure" do
755
847
  begin
756
848
  instance.public_send(action)
757
- rescue Kitchen::Error => e
849
+ rescue Kitchen::Error
850
+ true # no need to act here
758
851
  end
759
852
 
760
853
  logger_io.string.must_match regex_for(
@@ -771,7 +864,8 @@ describe Kitchen::Instance do
771
864
  it "write the state file with last action" do
772
865
  begin
773
866
  instance.public_send(action)
774
- rescue Kitchen::Error => e
867
+ rescue Kitchen::Error
868
+ true # no need to act here
775
869
  end
776
870
 
777
871
  state_file.read[:last_action].must_be_nil
@@ -794,7 +888,8 @@ describe Kitchen::Instance do
794
888
  it "logs the failure" do
795
889
  begin
796
890
  instance.public_send(action)
797
- rescue Kitchen::Error => e
891
+ rescue Kitchen::Error
892
+ true # no need to act here
798
893
  end
799
894
 
800
895
  logger_io.string.must_match regex_for(
@@ -812,10 +907,11 @@ describe Kitchen::Instance do
812
907
  [:create, :converge, :setup].each do |action|
813
908
 
814
909
  it "for last state #{action}" do
815
- state_file.write({ :last_action => action.to_s })
910
+ state_file.write(:last_action => action.to_s)
816
911
  begin
817
912
  instance.verify
818
- rescue Kitchen::Error => e
913
+ rescue Kitchen::Error
914
+ true # no need to act here
819
915
  end
820
916
 
821
917
  state_file.read[:last_action].must_equal "setup"
@@ -823,10 +919,11 @@ describe Kitchen::Instance do
823
919
  end
824
920
 
825
921
  it "for last state verify" do
826
- state_file.write({ :last_action => "verify" })
922
+ state_file.write(:last_action => "verify")
827
923
  begin
828
924
  instance.verify
829
- rescue Kitchen::Error => e
925
+ rescue Kitchen::Error
926
+ true # no need to act here
830
927
  end
831
928
 
832
929
  state_file.read[:last_action].must_equal "verify"