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
@@ -0,0 +1,316 @@
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/provisioner/chef_solo"
23
+
24
+ describe Kitchen::Provisioner::ChefSolo do
25
+
26
+ let(:logged_output) { StringIO.new }
27
+ let(:logger) { Logger.new(logged_output) }
28
+
29
+ let(:config) do
30
+ { :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
31
+ end
32
+
33
+ let(:suite) do
34
+ stub(:name => "fries")
35
+ end
36
+
37
+ let(:instance) do
38
+ stub(:name => "coolbeans", :logger => logger, :suite => suite)
39
+ end
40
+
41
+ let(:provisioner) do
42
+ Kitchen::Provisioner::ChefSolo.new(config).finalize_config!(instance)
43
+ end
44
+
45
+ describe "default config" do
46
+
47
+ it "sets :solo_rb to an empty Hash" do
48
+ provisioner[:solo_rb].must_equal Hash.new
49
+ end
50
+
51
+ it "sets :chef_solo_path to a path using :chef_omnibus_root" do
52
+ config[:chef_omnibus_root] = "/nice/place"
53
+
54
+ provisioner[:chef_solo_path].must_equal "/nice/place/bin/chef-solo"
55
+ end
56
+ end
57
+
58
+ describe "#create_sandbox" do
59
+
60
+ before do
61
+ @root = Dir.mktmpdir
62
+ config[:kitchen_root] = @root
63
+ end
64
+
65
+ after do
66
+ FileUtils.remove_entry(@root)
67
+ begin
68
+ provisioner.cleanup_sandbox
69
+ rescue # rubocop:disable Lint/HandleExceptions
70
+ end
71
+ end
72
+
73
+ describe "solo.rb file" do
74
+
75
+ let(:file) do
76
+ IO.read(sandbox_path("solo.rb")).lines.map(&:chomp)
77
+ end
78
+
79
+ it "creates a solo.rb" do
80
+ provisioner.create_sandbox
81
+
82
+ sandbox_path("solo.rb").file?.must_equal true
83
+ end
84
+
85
+ it "logs a message on info" do
86
+ provisioner.create_sandbox
87
+
88
+ logged_output.string.must_match info_line("Preparing solo.rb")
89
+ end
90
+
91
+ it "logs a message on debug" do
92
+ provisioner.create_sandbox
93
+
94
+ logged_output.string.
95
+ must_match debug_line_starting_with("Creating solo.rb from {")
96
+ end
97
+
98
+ describe "defaults" do
99
+
100
+ before { provisioner.create_sandbox }
101
+
102
+ it "sets node_name to the instance name" do
103
+ file.must_include %{node_name "#{instance.name}"}
104
+ end
105
+
106
+ it "sets checksum_path" do
107
+ file.must_include %{checksum_path "/tmp/kitchen/checksums"}
108
+ end
109
+
110
+ it "sets file_backup_path" do
111
+ file.must_include %{file_backup_path "/tmp/kitchen/backup"}
112
+ end
113
+
114
+ it "sets cookbook_path" do
115
+ file.must_include %{cookbook_path } +
116
+ %{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
117
+ end
118
+
119
+ it "sets data_bag_path" do
120
+ file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
121
+ end
122
+
123
+ it "sets environment_path" do
124
+ file.must_include %{environment_path "/tmp/kitchen/environments"}
125
+ end
126
+
127
+ it "sets node_path" do
128
+ file.must_include %{node_path "/tmp/kitchen/nodes"}
129
+ end
130
+
131
+ it "sets role_path" do
132
+ file.must_include %{role_path "/tmp/kitchen/roles"}
133
+ end
134
+
135
+ it "sets client_path" do
136
+ file.must_include %{client_path "/tmp/kitchen/clients"}
137
+ end
138
+
139
+ it "sets user_path" do
140
+ file.must_include %{user_path "/tmp/kitchen/users"}
141
+ end
142
+
143
+ it "sets validation_key" do
144
+ file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
145
+ end
146
+
147
+ it "sets client_key" do
148
+ file.must_include %{client_key "/tmp/kitchen/client.pem"}
149
+ end
150
+
151
+ it "sets chef_server_url" do
152
+ file.must_include %{chef_server_url "http://127.0.0.1:8889"}
153
+ end
154
+
155
+ it "sets encrypted_data_bag_secret" do
156
+ file.must_include %{encrypted_data_bag_secret } +
157
+ %{"/tmp/kitchen/encrypted_data_bag_secret"}
158
+ end
159
+ end
160
+
161
+ it "supports overwriting defaults" do
162
+ config[:solo_rb] = {
163
+ :node_name => "eagles",
164
+ :user_path => "/a/b/c/u",
165
+ :client_key => "lol"
166
+ }
167
+ provisioner.create_sandbox
168
+
169
+ file.must_include %{node_name "eagles"}
170
+ file.must_include %{user_path "/a/b/c/u"}
171
+ file.must_include %{client_key "lol"}
172
+ end
173
+
174
+ it " supports adding new configuration" do
175
+ config[:solo_rb] = {
176
+ :dark_secret => "golang"
177
+ }
178
+ provisioner.create_sandbox
179
+
180
+ file.must_include %{dark_secret "golang"}
181
+ end
182
+
183
+ it "formats array values correctly" do
184
+ config[:solo_rb] = {
185
+ :foos => %w[foo1 foo2]
186
+ }
187
+ provisioner.create_sandbox
188
+
189
+ file.must_include %{foos ["foo1", "foo2"]}
190
+ end
191
+
192
+ it "formats integer values correctly" do
193
+ config[:solo_rb] = {
194
+ :foo => 7
195
+ }
196
+ provisioner.create_sandbox
197
+
198
+ file.must_include %{foo 7}
199
+ end
200
+
201
+ it "formats symbol values correctly" do
202
+ config[:solo_rb] = {
203
+ :foo => :bar
204
+ }
205
+ provisioner.create_sandbox
206
+
207
+ file.must_include %{foo :bar}
208
+ end
209
+
210
+ it "formats boolean values correctly" do
211
+ config[:solo_rb] = {
212
+ :foo => false,
213
+ :bar => true
214
+ }
215
+ provisioner.create_sandbox
216
+
217
+ file.must_include %{foo false}
218
+ file.must_include %{bar true}
219
+ end
220
+ end
221
+
222
+ def sandbox_path(path)
223
+ Pathname.new(provisioner.sandbox_path).join(path)
224
+ end
225
+
226
+ end
227
+
228
+ describe "#run_command" do
229
+
230
+ let(:cmd) { provisioner.run_command }
231
+
232
+ it "uses bourne shell" do
233
+ cmd.must_match(/\Ash -c '$/)
234
+ cmd.must_match(/'\Z/)
235
+ end
236
+
237
+ it "uses sudo for chef-solo when configured" do
238
+ config[:chef_omnibus_root] = "/c"
239
+ config[:sudo] = true
240
+
241
+ cmd.must_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
242
+ end
243
+
244
+ it "does not use sudo for chef-solo when configured" do
245
+ config[:chef_omnibus_root] = "/c"
246
+ config[:sudo] = false
247
+
248
+ cmd.must_match regexify("chef-solo ", :partial_line)
249
+ cmd.wont_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
250
+ end
251
+
252
+ it "sets config flag on chef-solo" do
253
+ cmd.must_match regexify(" --config /tmp/kitchen/solo.rb", :partial_line)
254
+ end
255
+
256
+ it "sets config flag for custom root_path" do
257
+ config[:root_path] = "/a/b"
258
+
259
+ cmd.must_match regexify(" --config /a/b/solo.rb", :partial_line)
260
+ end
261
+
262
+ it "sets json attributes flag on chef-solo" do
263
+ cmd.must_match regexify(
264
+ " --json-attributes /tmp/kitchen/dna.json", :partial_line)
265
+ end
266
+
267
+ it "sets json attribtes flag for custom root_path" do
268
+ config[:root_path] = "/booyah"
269
+
270
+ cmd.must_match regexify(
271
+ " --json-attributes /booyah/dna.json", :partial_line)
272
+ end
273
+
274
+ it "sets log level flag on chef-solo to auto by default" do
275
+ cmd.must_match regexify(" --log_level auto", :partial_line)
276
+ end
277
+
278
+ it "set log level flag for custom level" do
279
+ config[:log_level] = :extreme
280
+
281
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
282
+ end
283
+
284
+ it "sets force formatter flag on chef-solo" do
285
+ cmd.must_match regexify(" --force-formatter", :partial_line)
286
+ end
287
+
288
+ it "sets no color flag on chef-solo" do
289
+ cmd.must_match regexify(" --no-color", :partial_line)
290
+ end
291
+
292
+ it "does not set logfile flag by default" do
293
+ cmd.wont_match regexify(" --logfile ", :partial_line)
294
+ end
295
+
296
+ it "sets logfile flag for custom value" do
297
+ config[:log_file] = "/a/out.log"
298
+
299
+ cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
300
+ end
301
+ end
302
+
303
+ def info_line(msg)
304
+ %r{^I, .* : #{Regexp.escape(msg)}$}
305
+ end
306
+
307
+ def debug_line_starting_with(msg)
308
+ %r{^D, .* : #{Regexp.escape(msg)}}
309
+ end
310
+
311
+ def regexify(str, line = :whole_line)
312
+ r = Regexp.escape(str)
313
+ r = "^\s*#{r}$" if line == :whole_line
314
+ Regexp.new(r)
315
+ end
316
+ end
@@ -0,0 +1,624 @@
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/provisioner/chef_zero"
23
+
24
+ describe Kitchen::Provisioner::ChefZero do
25
+
26
+ let(:logged_output) { StringIO.new }
27
+ let(:logger) { Logger.new(logged_output) }
28
+
29
+ let(:config) do
30
+ { :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
31
+ end
32
+
33
+ let(:suite) do
34
+ stub(:name => "fries")
35
+ end
36
+
37
+ let(:instance) do
38
+ stub(:name => "coolbeans", :logger => logger, :suite => suite)
39
+ end
40
+
41
+ let(:provisioner) do
42
+ Kitchen::Provisioner::ChefZero.new(config).finalize_config!(instance)
43
+ end
44
+
45
+ describe "default config" do
46
+
47
+ it "sets :client_rb to an empty Hash" do
48
+ provisioner[:client_rb].must_equal Hash.new
49
+ end
50
+
51
+ it "sets :chef_client_path to a path using :chef_omnibus_root" do
52
+ config[:chef_omnibus_root] = "/nice/place"
53
+
54
+ provisioner[:chef_client_path].must_equal "/nice/place/bin/chef-client"
55
+ end
56
+
57
+ it "sets :ruby_bindir to use an Omnibus Ruby" do
58
+ provisioner[:ruby_bindir].must_equal "/opt/chef/embedded/bin"
59
+ end
60
+
61
+ it "sets :json_attributes to true" do
62
+ provisioner[:json_attributes].must_equal true
63
+ end
64
+
65
+ it "does not set :chef_zero_host" do
66
+ provisioner[:chef_zero_host].must_equal nil
67
+ end
68
+
69
+ it "sets :chef_zero_port to 8889" do
70
+ provisioner[:chef_zero_port].must_equal 8889
71
+ end
72
+ end
73
+
74
+ describe "#create_sandbox" do
75
+
76
+ before do
77
+ @root = Dir.mktmpdir
78
+ config[:kitchen_root] = @root
79
+ end
80
+
81
+ after do
82
+ FileUtils.remove_entry(@root)
83
+ begin
84
+ provisioner.cleanup_sandbox
85
+ rescue # rubocop:disable Lint/HandleExceptions
86
+ end
87
+ end
88
+
89
+ describe "client.rb file" do
90
+
91
+ let(:file) do
92
+ IO.read(sandbox_path("client.rb")).lines.map(&:chomp)
93
+ end
94
+
95
+ it "creates a client.rb" do
96
+ provisioner.create_sandbox
97
+
98
+ sandbox_path("client.rb").file?.must_equal true
99
+ end
100
+
101
+ it "logs a message on info" do
102
+ provisioner.create_sandbox
103
+
104
+ logged_output.string.must_match info_line("Preparing client.rb")
105
+ end
106
+
107
+ it "logs a message on debug" do
108
+ provisioner.create_sandbox
109
+
110
+ logged_output.string.
111
+ must_match debug_line_starting_with("Creating client.rb from {")
112
+ end
113
+
114
+ describe "defaults" do
115
+
116
+ before { provisioner.create_sandbox }
117
+
118
+ it "sets node_name to the instance name" do
119
+ file.must_include %{node_name "#{instance.name}"}
120
+ end
121
+
122
+ it "sets checksum_path" do
123
+ file.must_include %{checksum_path "/tmp/kitchen/checksums"}
124
+ end
125
+
126
+ it "sets file_backup_path" do
127
+ file.must_include %{file_backup_path "/tmp/kitchen/backup"}
128
+ end
129
+
130
+ it "sets cookbook_path" do
131
+ file.must_include %{cookbook_path } +
132
+ %{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
133
+ end
134
+
135
+ it "sets data_bag_path" do
136
+ file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
137
+ end
138
+
139
+ it "sets environment_path" do
140
+ file.must_include %{environment_path "/tmp/kitchen/environments"}
141
+ end
142
+
143
+ it "sets node_path" do
144
+ file.must_include %{node_path "/tmp/kitchen/nodes"}
145
+ end
146
+
147
+ it "sets role_path" do
148
+ file.must_include %{role_path "/tmp/kitchen/roles"}
149
+ end
150
+
151
+ it "sets client_path" do
152
+ file.must_include %{client_path "/tmp/kitchen/clients"}
153
+ end
154
+
155
+ it "sets user_path" do
156
+ file.must_include %{user_path "/tmp/kitchen/users"}
157
+ end
158
+
159
+ it "sets validation_key" do
160
+ file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
161
+ end
162
+
163
+ it "sets client_key" do
164
+ file.must_include %{client_key "/tmp/kitchen/client.pem"}
165
+ end
166
+
167
+ it "sets chef_server_url" do
168
+ file.must_include %{chef_server_url "http://127.0.0.1:8889"}
169
+ end
170
+
171
+ it "sets encrypted_data_bag_secret" do
172
+ file.must_include %{encrypted_data_bag_secret } +
173
+ %{"/tmp/kitchen/encrypted_data_bag_secret"}
174
+ end
175
+ end
176
+
177
+ it "supports overwriting defaults" do
178
+ config[:client_rb] = {
179
+ :node_name => "eagles",
180
+ :user_path => "/a/b/c/u",
181
+ :client_key => "lol"
182
+ }
183
+ provisioner.create_sandbox
184
+
185
+ file.must_include %{node_name "eagles"}
186
+ file.must_include %{user_path "/a/b/c/u"}
187
+ file.must_include %{client_key "lol"}
188
+ end
189
+
190
+ it " supports adding new configuration" do
191
+ config[:client_rb] = {
192
+ :dark_secret => "golang"
193
+ }
194
+ provisioner.create_sandbox
195
+
196
+ file.must_include %{dark_secret "golang"}
197
+ end
198
+
199
+ it "formats array values correctly" do
200
+ config[:client_rb] = {
201
+ :foos => %w[foo1 foo2]
202
+ }
203
+ provisioner.create_sandbox
204
+
205
+ file.must_include %{foos ["foo1", "foo2"]}
206
+ end
207
+
208
+ it "formats integer values correctly" do
209
+ config[:client_rb] = {
210
+ :foo => 7
211
+ }
212
+ provisioner.create_sandbox
213
+
214
+ file.must_include %{foo 7}
215
+ end
216
+
217
+ it "formats symbol values correctly" do
218
+ config[:client_rb] = {
219
+ :foo => :bar
220
+ }
221
+ provisioner.create_sandbox
222
+
223
+ file.must_include %{foo :bar}
224
+ end
225
+
226
+ it "formats boolean values correctly" do
227
+ config[:client_rb] = {
228
+ :foo => false,
229
+ :bar => true
230
+ }
231
+ provisioner.create_sandbox
232
+
233
+ file.must_include %{foo false}
234
+ file.must_include %{bar true}
235
+ end
236
+ end
237
+
238
+ describe "validation.pem file" do
239
+
240
+ it "creates file" do
241
+ provisioner.create_sandbox
242
+
243
+ sandbox_path("validation.pem").file?.must_equal true
244
+ end
245
+
246
+ it "logs a message on info" do
247
+ provisioner.create_sandbox
248
+
249
+ logged_output.string.must_match info_line("Preparing validation.pem")
250
+ end
251
+
252
+ it "logs a message on debug" do
253
+ provisioner.create_sandbox
254
+
255
+ logged_output.string.
256
+ must_match debug_line_starting_with("Using a dummy validation.pem")
257
+ end
258
+ end
259
+
260
+ describe "chef-client-zero.rb file" do
261
+
262
+ describe "for modern Chef versions" do
263
+
264
+ before { config[:require_chef_omnibus] = "11.10" }
265
+
266
+ it "does not create the file" do
267
+ provisioner.create_sandbox
268
+
269
+ sandbox_path("chef-client-zero.rb").file?.must_equal false
270
+ end
271
+ end
272
+
273
+ describe "for old Chef versions" do
274
+
275
+ before { config[:require_chef_omnibus] = "10.20" }
276
+
277
+ it "creates the file when using an old Chef version" do
278
+ provisioner.create_sandbox
279
+
280
+ sandbox_path("chef-client-zero.rb").file?.must_equal true
281
+ end
282
+
283
+ it "logs a message on info" do
284
+ provisioner.create_sandbox
285
+
286
+ logged_output.string.
287
+ must_match info_line("Preparing chef-client-zero.rb")
288
+ end
289
+
290
+ it "logs a message on debug" do
291
+ provisioner.create_sandbox
292
+
293
+ logged_output.string.must_match debug_line_starting_with(
294
+ "Using a vendored chef-client-zero.rb")
295
+ end
296
+ end
297
+ end
298
+
299
+ def sandbox_path(path)
300
+ Pathname.new(provisioner.sandbox_path).join(path)
301
+ end
302
+ end
303
+
304
+ describe "#prepare_command" do
305
+
306
+ let(:cmd) { provisioner.prepare_command }
307
+
308
+ describe "for modern Chef versions" do
309
+
310
+ before { config[:require_chef_omnibus] = "11.10" }
311
+
312
+ it "returns nil" do
313
+ cmd.must_equal nil
314
+ end
315
+ end
316
+
317
+ describe "for old Chef versions" do
318
+
319
+ before do
320
+ config[:require_chef_omnibus] = "10.20"
321
+ config[:ruby_bindir] = "/rbd"
322
+ end
323
+
324
+ it "uses bourne shell" do
325
+ cmd.must_match(/\Ash -c '$/)
326
+ cmd.must_match(/'\Z/)
327
+ end
328
+
329
+ it "sets the CHEF_REPO_PATH environment variable" do
330
+ config[:root_path] = "/r"
331
+
332
+ cmd.must_match regexify(%{CHEF_REPO_PATH="/r" }, :partial_line)
333
+ end
334
+
335
+ it "sets the GEM_HOME environment variable" do
336
+ config[:root_path] = "/r"
337
+
338
+ cmd.must_match regexify(
339
+ %{GEM_HOME="/r/chef-client-zero-gems" }, :partial_line)
340
+ end
341
+
342
+ it "sets the GEM_PATH environment variable" do
343
+ config[:root_path] = "/r"
344
+
345
+ cmd.must_match regexify(
346
+ %{GEM_PATH="/r/chef-client-zero-gems" }, :partial_line)
347
+ end
348
+
349
+ it "sets the GEM_CACHE environment variable" do
350
+ config[:root_path] = "/r"
351
+
352
+ cmd.must_match regexify(
353
+ %{GEM_CACHE="/r/chef-client-zero-gems/cache" }, :partial_line)
354
+ end
355
+
356
+ it "exports all the environment variables" do
357
+ cmd.must_match regexify(
358
+ "export CHEF_REPO_PATH GEM_HOME GEM_PATH GEM_CACHE;", :partial_line)
359
+ end
360
+
361
+ it "checks if chef-zero is installed" do
362
+ cmd.must_match regexify(
363
+ %{if ! sudo -E /rbd/gem list chef-zero -i >/dev/null; then})
364
+ end
365
+
366
+ it "installs the chef gem" do
367
+ cmd.must_match regexify(
368
+ %{sudo -E /rbd/gem install chef --no-ri --no-rdoc --conservative})
369
+ end
370
+ end
371
+ end
372
+
373
+ describe "#run_command" do
374
+
375
+ let(:cmd) { provisioner.run_command }
376
+
377
+ describe "for modern Chef versions" do
378
+
379
+ before { config[:require_chef_omnibus] = "11.10" }
380
+
381
+ it "uses bourne shell" do
382
+ cmd.must_match(/\Ash -c '$/)
383
+ cmd.must_match(/'\Z/)
384
+ end
385
+
386
+ it "uses sudo for chef-client when configured" do
387
+ config[:chef_omnibus_root] = "/c"
388
+ config[:sudo] = true
389
+
390
+ cmd.must_match regexify("sudo -E /c/bin/chef-client ", :partial_line)
391
+ end
392
+
393
+ it "does not use sudo for chef-client when configured" do
394
+ config[:chef_omnibus_root] = "/c"
395
+ config[:sudo] = false
396
+
397
+ cmd.must_match regexify("/c/bin/chef-client ", :partial_line)
398
+ cmd.wont_match regexify("sudo -E /c/bin/chef-client ", :partial_line)
399
+ end
400
+
401
+ it "sets local mode flag on chef-client" do
402
+ cmd.must_match regexify(" --local-mode", :partial_line)
403
+ end
404
+
405
+ it "sets config flag on chef-client" do
406
+ cmd.must_match regexify(
407
+ " --config /tmp/kitchen/client.rb", :partial_line)
408
+ end
409
+
410
+ it "sets config flag for custom root_path" do
411
+ config[:root_path] = "/a/b"
412
+
413
+ cmd.must_match regexify(" --config /a/b/client.rb", :partial_line)
414
+ end
415
+
416
+ it "sets log level flag on chef-client to auto by default" do
417
+ cmd.must_match regexify(" --log_level auto", :partial_line)
418
+ end
419
+
420
+ it "set log level flag for custom level" do
421
+ config[:log_level] = :extreme
422
+
423
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
424
+ end
425
+
426
+ it "sets force formatter flag on chef-solo" do
427
+ cmd.must_match regexify(" --force-formatter", :partial_line)
428
+ end
429
+
430
+ it "sets no color flag on chef-solo" do
431
+ cmd.must_match regexify(" --no-color", :partial_line)
432
+ end
433
+
434
+ it "sets chef zero port flag on chef-client" do
435
+ cmd.must_match regexify(" --chef-zero-port 8889", :partial_line)
436
+ end
437
+
438
+ it "sets chef zero host flag for custom host" do
439
+ config[:chef_zero_host] = "192.168.0.1"
440
+
441
+ cmd.must_match regexify(" --chef-zero-host 192.168.0.1", :partial_line)
442
+ end
443
+
444
+ it "sets chef zero port flag for custom port" do
445
+ config[:chef_zero_port] = 123
446
+
447
+ cmd.must_match regexify(" --chef-zero-port 123", :partial_line)
448
+ end
449
+
450
+ it "does not set chef zero host flag when value is falsey" do
451
+ config[:chef_zero_host] = nil
452
+
453
+ cmd.wont_match regexify(" --chef-zero-host ", :partial_line)
454
+ end
455
+
456
+ it "does not set chef zero port flag when value is falsey" do
457
+ config[:chef_zero_port] = nil
458
+
459
+ cmd.wont_match regexify(" --chef-zero-port ", :partial_line)
460
+ end
461
+
462
+ it "sets json attributes flag on chef-client" do
463
+ cmd.must_match regexify(
464
+ " --json-attributes /tmp/kitchen/dna.json", :partial_line)
465
+ end
466
+
467
+ it "sets json attribtes flag for custom root_path" do
468
+ config[:root_path] = "/booyah"
469
+
470
+ cmd.must_match regexify(
471
+ " --json-attributes /booyah/dna.json", :partial_line)
472
+ end
473
+
474
+ it "does not set json attributes flag if config is falsey" do
475
+ config[:json_attributes] = false
476
+
477
+ cmd.wont_match regexify(" --json-attributes ", :partial_line)
478
+ end
479
+
480
+ it "does not set logfile flag by default" do
481
+ cmd.wont_match regexify(" --logfile ", :partial_line)
482
+ end
483
+
484
+ it "sets logfile flag for custom value" do
485
+ config[:log_file] = "/a/out.log"
486
+
487
+ cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
488
+ end
489
+ end
490
+
491
+ describe "for old Chef versions" do
492
+
493
+ before do
494
+ config[:require_chef_omnibus] = "10.20"
495
+ config[:ruby_bindir] = "/r/bin"
496
+ end
497
+
498
+ it "uses bourne shell" do
499
+ cmd.must_match(/\Ash -c '$/)
500
+ cmd.must_match(/'\Z/)
501
+ end
502
+
503
+ it "uses sudo for ruby when configured" do
504
+ config[:root_path] = "/x"
505
+ config[:sudo] = true
506
+
507
+ cmd.must_match regexify(
508
+ "sudo -E /r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
509
+ end
510
+
511
+ it "does not use sudo for ruby when configured" do
512
+ config[:root_path] = "/x"
513
+ config[:sudo] = false
514
+
515
+ cmd.must_match regexify(
516
+ "/r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
517
+ cmd.wont_match regexify(
518
+ "sudo -E /r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
519
+ end
520
+
521
+ it "does not set local mode flag" do
522
+ cmd.wont_match regexify(" --local-mode", :partial_line)
523
+ end
524
+
525
+ it "sets config flag on chef-client" do
526
+ cmd.must_match regexify(
527
+ " --config /tmp/kitchen/client.rb", :partial_line)
528
+ end
529
+
530
+ it "sets config flag for custom root_path" do
531
+ config[:root_path] = "/a/b"
532
+
533
+ cmd.must_match regexify(" --config /a/b/client.rb", :partial_line)
534
+ end
535
+
536
+ it "sets log level flag on chef-client to auto by default" do
537
+ cmd.must_match regexify(" --log_level auto", :partial_line)
538
+ end
539
+
540
+ it "set log level flag for custom level" do
541
+ config[:log_level] = :extreme
542
+
543
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
544
+ end
545
+
546
+ it "sets force formatter flag on chef-solo" do
547
+ cmd.must_match regexify(" --force-formatter", :partial_line)
548
+ end
549
+
550
+ it "sets no color flag on chef-solo" do
551
+ cmd.must_match regexify(" --no-color", :partial_line)
552
+ end
553
+
554
+ it "sets json attributes flag on chef-client" do
555
+ cmd.must_match regexify(
556
+ " --json-attributes /tmp/kitchen/dna.json", :partial_line)
557
+ end
558
+
559
+ it "sets json attribtes flag for custom root_path" do
560
+ config[:root_path] = "/booyah"
561
+
562
+ cmd.must_match regexify(
563
+ " --json-attributes /booyah/dna.json", :partial_line)
564
+ end
565
+
566
+ it "does not set json attributes flag if config is falsey" do
567
+ config[:json_attributes] = false
568
+
569
+ cmd.wont_match regexify(" --json-attributes ", :partial_line)
570
+ end
571
+
572
+ it "does not set logfile flag by default" do
573
+ cmd.wont_match regexify(" --logfile ", :partial_line)
574
+ end
575
+
576
+ it "sets logfile flag for custom value" do
577
+ config[:log_file] = "/a/out.log"
578
+
579
+ cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
580
+ end
581
+
582
+ it "sets the CHEF_REPO_PATH environment variable" do
583
+ config[:root_path] = "/r"
584
+
585
+ cmd.must_match regexify(%{CHEF_REPO_PATH="/r" }, :partial_line)
586
+ end
587
+
588
+ it "sets the GEM_HOME environment variable" do
589
+ config[:root_path] = "/r"
590
+
591
+ cmd.must_match regexify(
592
+ %{GEM_HOME="/r/chef-client-zero-gems" }, :partial_line)
593
+ end
594
+
595
+ it "sets the GEM_PATH environment variable" do
596
+ config[:root_path] = "/r"
597
+
598
+ cmd.must_match regexify(
599
+ %{GEM_PATH="/r/chef-client-zero-gems" }, :partial_line)
600
+ end
601
+
602
+ it "sets the GEM_CACHE environment variable" do
603
+ config[:root_path] = "/r"
604
+
605
+ cmd.must_match regexify(
606
+ %{GEM_CACHE="/r/chef-client-zero-gems/cache" }, :partial_line)
607
+ end
608
+ end
609
+ end
610
+
611
+ def info_line(msg)
612
+ %r{^I, .* : #{Regexp.escape(msg)}$}
613
+ end
614
+
615
+ def debug_line_starting_with(msg)
616
+ %r{^D, .* : #{Regexp.escape(msg)}}
617
+ end
618
+
619
+ def regexify(str, line = :whole_line)
620
+ r = Regexp.escape(str)
621
+ r = "^\s*#{r}$" if line == :whole_line
622
+ Regexp.new(r)
623
+ end
624
+ end