test-kitchen 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
@@ -1,557 +1,557 @@
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
- let(:platform) { stub(:os_type => nil) }
29
- let(:suite) { stub(:name => "fries") }
30
-
31
- let(:config) do
32
- { :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
33
- end
34
-
35
- let(:instance) do
36
- stub(
37
- :name => "coolbeans",
38
- :logger => logger,
39
- :suite => suite,
40
- :platform => platform
41
- )
42
- end
43
-
44
- let(:provisioner) do
45
- Kitchen::Provisioner::ChefSolo.new(config).finalize_config!(instance)
46
- end
47
-
48
- it "provisioner api_version is 2" do
49
- provisioner.diagnose_plugin[:api_version].must_equal 2
50
- end
51
-
52
- it "plugin_version is set to Kitchen::VERSION" do
53
- provisioner.diagnose_plugin[:version].must_equal Kitchen::VERSION
54
- end
55
-
56
- describe "default config" do
57
-
58
- describe "for unix operating systems" do
59
-
60
- before { platform.stubs(:os_type).returns("unix") }
61
-
62
- it "sets :chef_solo_path to a path using :chef_omnibus_root" do
63
- config[:chef_omnibus_root] = "/nice/place"
64
-
65
- provisioner[:chef_solo_path].must_equal "/nice/place/bin/chef-solo"
66
- end
67
- end
68
-
69
- describe "for windows operating systems" do
70
-
71
- before { platform.stubs(:os_type).returns("windows") }
72
-
73
- it "sets :chef_solo_path to a path using :chef_omnibus_root" do
74
- config[:chef_omnibus_root] = "$env:systemdrive\\nice\\place"
75
-
76
- provisioner[:chef_solo_path].
77
- must_equal "$env:systemdrive\\nice\\place\\bin\\chef-solo.bat"
78
- end
79
- end
80
-
81
- it "sets :solo_rb to an empty Hash" do
82
- provisioner[:solo_rb].must_equal Hash.new
83
- end
84
- end
85
-
86
- describe "#create_sandbox" do
87
-
88
- before do
89
- @root = Dir.mktmpdir
90
- config[:kitchen_root] = @root
91
- end
92
-
93
- after do
94
- FileUtils.remove_entry(@root)
95
- begin
96
- provisioner.cleanup_sandbox
97
- rescue # rubocop:disable Lint/HandleExceptions
98
- end
99
- end
100
-
101
- describe "solo.rb file" do
102
-
103
- let(:file) do
104
- IO.read(sandbox_path("solo.rb")).lines.map(&:chomp)
105
- end
106
-
107
- it "creates a solo.rb" do
108
- provisioner.create_sandbox
109
-
110
- sandbox_path("solo.rb").file?.must_equal true
111
- end
112
-
113
- it "logs a message on info" do
114
- provisioner.create_sandbox
115
-
116
- logged_output.string.must_match info_line("Preparing solo.rb")
117
- end
118
-
119
- it "logs a message on debug" do
120
- provisioner.create_sandbox
121
-
122
- logged_output.string.
123
- must_match debug_line_starting_with("Creating solo.rb from {")
124
- end
125
-
126
- describe "defaults" do
127
-
128
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
129
- def self.common_solo_rb_specs
130
- it "sets node_name to the instance name" do
131
- file.must_include %{node_name "#{instance.name}"}
132
- end
133
-
134
- it "sets checksum_path" do
135
- file.must_include %{checksum_path "#{base}checksums"}
136
- end
137
-
138
- it "sets file_backup_path" do
139
- file.must_include %{file_backup_path "#{base}backup"}
140
- end
141
-
142
- it "sets cookbook_path" do
143
- file.must_include %{cookbook_path } +
144
- %{["#{base}cookbooks", "#{base}site-cookbooks"]}
145
- end
146
-
147
- it "sets data_bag_path" do
148
- file.must_include %{data_bag_path "#{base}data_bags"}
149
- end
150
-
151
- it "sets environment_path" do
152
- file.must_include %{environment_path "#{base}environments"}
153
- end
154
-
155
- it "sets node_path" do
156
- file.must_include %{node_path "#{base}nodes"}
157
- end
158
-
159
- it "sets role_path" do
160
- file.must_include %{role_path "#{base}roles"}
161
- end
162
-
163
- it "sets client_path" do
164
- file.must_include %{client_path "#{base}clients"}
165
- end
166
-
167
- it "sets user_path" do
168
- file.must_include %{user_path "#{base}users"}
169
- end
170
-
171
- it "sets validation_key" do
172
- file.must_include %{validation_key "#{base}validation.pem"}
173
- end
174
-
175
- it "sets client_key" do
176
- file.must_include %{client_key "#{base}client.pem"}
177
- end
178
-
179
- it "sets chef_server_url" do
180
- file.must_include %{chef_server_url "http://127.0.0.1:8889"}
181
- end
182
-
183
- it "sets encrypted_data_bag_secret" do
184
- file.must_include %{encrypted_data_bag_secret } +
185
- %{"#{base}encrypted_data_bag_secret"}
186
- end
187
- end
188
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
189
-
190
- describe "for unix os types" do
191
-
192
- before do
193
- platform.stubs(:os_type).returns("unix")
194
- provisioner.create_sandbox
195
- end
196
-
197
- let(:base) { "/tmp/kitchen/" }
198
-
199
- common_solo_rb_specs
200
- end
201
-
202
- describe "for windows os types with full path" do
203
-
204
- before do
205
- platform.stubs(:os_type).returns("windows")
206
- config[:root_path] = "\\a\\b"
207
- provisioner.create_sandbox
208
- end
209
-
210
- let(:base) { "\\\\a\\\\b\\\\" }
211
-
212
- common_solo_rb_specs
213
- end
214
-
215
- describe "for windows os types with $env:TEMP prefixed paths" do
216
-
217
- before do
218
- platform.stubs(:os_type).returns("windows")
219
- config[:root_path] = "$env:TEMP\\a"
220
- provisioner.create_sandbox
221
- end
222
-
223
- let(:base) { "\#{ENV['TEMP']}\\\\a\\\\" }
224
-
225
- common_solo_rb_specs
226
- end
227
- end
228
-
229
- it "supports overwriting defaults" do
230
- config[:solo_rb] = {
231
- :node_name => "eagles",
232
- :user_path => "/a/b/c/u",
233
- :client_key => "lol"
234
- }
235
- provisioner.create_sandbox
236
-
237
- file.must_include %{node_name "eagles"}
238
- file.must_include %{user_path "/a/b/c/u"}
239
- file.must_include %{client_key "lol"}
240
- end
241
-
242
- it "supports adding new configuration" do
243
- config[:solo_rb] = {
244
- :dark_secret => "golang"
245
- }
246
- provisioner.create_sandbox
247
-
248
- file.must_include %{dark_secret "golang"}
249
- end
250
-
251
- it "formats array values correctly" do
252
- config[:solo_rb] = {
253
- :foos => %w[foo1 foo2]
254
- }
255
- provisioner.create_sandbox
256
-
257
- file.must_include %{foos ["foo1", "foo2"]}
258
- end
259
-
260
- it "formats integer values correctly" do
261
- config[:solo_rb] = {
262
- :foo => 7
263
- }
264
- provisioner.create_sandbox
265
-
266
- file.must_include %{foo 7}
267
- end
268
-
269
- it "formats symbol-looking string values correctly" do
270
- config[:solo_rb] = {
271
- :foo => ":bar"
272
- }
273
- provisioner.create_sandbox
274
-
275
- file.must_include %{foo :bar}
276
- end
277
-
278
- it "formats boolean values correctly" do
279
- config[:solo_rb] = {
280
- :foo => false,
281
- :bar => true
282
- }
283
- provisioner.create_sandbox
284
-
285
- file.must_include %{foo false}
286
- file.must_include %{bar true}
287
- end
288
- end
289
-
290
- def sandbox_path(path)
291
- Pathname.new(provisioner.sandbox_path).join(path)
292
- end
293
- end
294
-
295
- describe "#run_command" do
296
-
297
- let(:cmd) { provisioner.run_command }
298
-
299
- describe "common behavior" do
300
-
301
- before { platform.stubs(:shell_type).returns("fake") }
302
-
303
- it "prefixs the whole command with the command_prefix if set" do
304
- config[:command_prefix] = "my_prefix"
305
-
306
- cmd.must_match(/\Amy_prefix /)
307
- end
308
-
309
- it "does not prefix the command if command_prefix is not set" do
310
- config[:command_prefix] = nil
311
-
312
- cmd.wont_match(/\Amy_prefix /)
313
- end
314
- end
315
-
316
- describe "for bourne shells" do
317
-
318
- before { platform.stubs(:shell_type).returns("bourne") }
319
-
320
- it "uses bourne shell" do
321
- cmd.must_match(/\Ash -c '$/)
322
- cmd.must_match(/'\Z/)
323
- end
324
-
325
- it "ends with a single quote" do
326
- cmd.must_match(/'\Z/)
327
- end
328
-
329
- it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
330
- config[:http_proxy] = "http://proxy"
331
-
332
- cmd.lines.to_a[1..2].must_equal([
333
- %{http_proxy="http://proxy"; export http_proxy\n},
334
- %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n}
335
- ])
336
- end
337
-
338
- it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
339
- config[:https_proxy] = "https://proxy"
340
-
341
- cmd.lines.to_a[1..2].must_equal([
342
- %{https_proxy="https://proxy"; export https_proxy\n},
343
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
344
- ])
345
- end
346
-
347
- it "exports all http proxy variables when both are set" do
348
- config[:http_proxy] = "http://proxy"
349
- config[:https_proxy] = "https://proxy"
350
-
351
- cmd.lines.to_a[1..4].must_equal([
352
- %{http_proxy="http://proxy"; export http_proxy\n},
353
- %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
354
- %{https_proxy="https://proxy"; export https_proxy\n},
355
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
356
- ])
357
- end
358
-
359
- it "does no powershell PATH reloading for older chef omnibus packages" do
360
- cmd.wont_match regexify(%{[System.Environment]::})
361
- end
362
-
363
- it "uses sudo for chef-solo when configured" do
364
- config[:chef_omnibus_root] = "/c"
365
- config[:sudo] = true
366
-
367
- cmd.must_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
368
- end
369
-
370
- it "does not use sudo for chef-solo when configured" do
371
- config[:chef_omnibus_root] = "/c"
372
- config[:sudo] = false
373
-
374
- cmd.must_match regexify("chef-solo ", :partial_line)
375
- cmd.wont_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
376
- end
377
-
378
- it "sets config flag on chef-solo" do
379
- cmd.must_match regexify(" --config /tmp/kitchen/solo.rb", :partial_line)
380
- end
381
-
382
- it "sets config flag for custom root_path" do
383
- config[:root_path] = "/a/b"
384
-
385
- cmd.must_match regexify(" --config /a/b/solo.rb", :partial_line)
386
- end
387
-
388
- it "sets json attributes flag on chef-solo" do
389
- cmd.must_match regexify(
390
- " --json-attributes /tmp/kitchen/dna.json", :partial_line)
391
- end
392
-
393
- it "sets json attribtes flag for custom root_path" do
394
- config[:root_path] = "/booyah"
395
-
396
- cmd.must_match regexify(
397
- " --json-attributes /booyah/dna.json", :partial_line)
398
- end
399
-
400
- it "sets log level flag on chef-solo to auto by default" do
401
- cmd.must_match regexify(" --log_level auto", :partial_line)
402
- end
403
-
404
- it "set log level flag for custom level" do
405
- config[:log_level] = :extreme
406
-
407
- cmd.must_match regexify(" --log_level extreme", :partial_line)
408
- end
409
-
410
- it "sets force formatter flag on chef-solo" do
411
- cmd.must_match regexify(" --force-formatter", :partial_line)
412
- end
413
-
414
- it "sets no color flag on chef-solo" do
415
- cmd.must_match regexify(" --no-color", :partial_line)
416
- end
417
-
418
- it "does not set logfile flag by default" do
419
- cmd.wont_match regexify(" --logfile ", :partial_line)
420
- end
421
-
422
- it "sets logfile flag for custom value" do
423
- config[:log_file] = "/a/out.log"
424
-
425
- cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
426
- end
427
-
428
- it "sets profile-ruby flag when config element is set" do
429
- config[:profile_ruby] = true
430
-
431
- cmd.must_match regexify(
432
- " --profile-ruby", :partial_line)
433
- end
434
-
435
- it "does not set profile-ruby flag when config element is falsey" do
436
- config[:profile_ruby] = false
437
-
438
- cmd.wont_match regexify(" --profile-ruby", :partial_line)
439
- end
440
- end
441
-
442
- describe "for powershell shells on windows os types" do
443
-
444
- before do
445
- platform.stubs(:shell_type).returns("powershell")
446
- platform.stubs(:os_type).returns("windows")
447
- end
448
-
449
- it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
450
- config[:http_proxy] = "http://proxy"
451
-
452
- cmd.lines.to_a[0..1].must_equal([
453
- %{$env:http_proxy = "http://proxy"\n},
454
- %{$env:HTTP_PROXY = "http://proxy"\n}
455
- ])
456
- end
457
-
458
- it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
459
- config[:https_proxy] = "https://proxy"
460
-
461
- cmd.lines.to_a[0..1].must_equal([
462
- %{$env:https_proxy = "https://proxy"\n},
463
- %{$env:HTTPS_PROXY = "https://proxy"\n}
464
- ])
465
- end
466
-
467
- it "exports all http proxy variables when both are set" do
468
- config[:http_proxy] = "http://proxy"
469
- config[:https_proxy] = "https://proxy"
470
-
471
- cmd.lines.to_a[0..3].must_equal([
472
- %{$env:http_proxy = "http://proxy"\n},
473
- %{$env:HTTP_PROXY = "http://proxy"\n},
474
- %{$env:https_proxy = "https://proxy"\n},
475
- %{$env:HTTPS_PROXY = "https://proxy"\n}
476
- ])
477
- end
478
-
479
- it "reloads PATH for older chef omnibus packages" do
480
- cmd.must_match regexify("$env:PATH = " +
481
- %{[System.Environment]::GetEnvironmentVariable("PATH","Machine")})
482
- end
483
-
484
- it "calls the chef-solo command from :chef_solo_path" do
485
- config[:chef_solo_path] = "\\r\\chef-solo.bat"
486
-
487
- cmd.must_match regexify("& \\r\\chef-solo.bat ", :partial_line)
488
- end
489
-
490
- it "sets config flag on chef-solo" do
491
- cmd.must_match regexify(
492
- " --config $env:TEMP\\kitchen\\solo.rb", :partial_line)
493
- end
494
-
495
- it "sets config flag for custom root_path" do
496
- config[:root_path] = "\\a\\b"
497
-
498
- cmd.must_match regexify(
499
- " --config \\a\\b\\solo.rb", :partial_line)
500
- end
501
-
502
- it "sets json attributes flag on chef-solo" do
503
- cmd.must_match regexify(
504
- " --json-attributes $env:TEMP\\kitchen\\dna.json", :partial_line)
505
- end
506
-
507
- it "sets json attribtes flag for custom root_path" do
508
- config[:root_path] = "\\booyah"
509
-
510
- cmd.must_match regexify(
511
- " --json-attributes \\booyah\\dna.json", :partial_line)
512
- end
513
-
514
- it "sets log level flag on chef-solo to auto by default" do
515
- cmd.must_match regexify(" --log_level auto", :partial_line)
516
- end
517
-
518
- it "set log level flag for custom level" do
519
- config[:log_level] = :extreme
520
-
521
- cmd.must_match regexify(" --log_level extreme", :partial_line)
522
- end
523
-
524
- it "sets force formatter flag on chef-solo" do
525
- cmd.must_match regexify(" --force-formatter", :partial_line)
526
- end
527
-
528
- it "sets no color flag on chef-solo" do
529
- cmd.must_match regexify(" --no-color", :partial_line)
530
- end
531
-
532
- it "does not set logfile flag by default" do
533
- cmd.wont_match regexify(" --logfile ", :partial_line)
534
- end
535
-
536
- it "sets logfile flag for custom value" do
537
- config[:log_file] = "\\a\\out.log"
538
-
539
- cmd.must_match regexify(" --logfile \\a\\out.log", :partial_line)
540
- end
541
- end
542
- end
543
-
544
- def info_line(msg)
545
- %r{^I, .* : #{Regexp.escape(msg)}$}
546
- end
547
-
548
- def debug_line_starting_with(msg)
549
- %r{^D, .* : #{Regexp.escape(msg)}}
550
- end
551
-
552
- def regexify(str, line = :whole_line)
553
- r = Regexp.escape(str)
554
- r = "^\s*#{r}$" if line == :whole_line
555
- Regexp.new(r)
556
- end
557
- end
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
+ let(:platform) { stub(:os_type => nil) }
29
+ let(:suite) { stub(:name => "fries") }
30
+
31
+ let(:config) do
32
+ { :test_base_path => "/b", :kitchen_root => "/r" }
33
+ end
34
+
35
+ let(:instance) do
36
+ stub(
37
+ :name => "coolbeans",
38
+ :logger => logger,
39
+ :suite => suite,
40
+ :platform => platform
41
+ )
42
+ end
43
+
44
+ let(:provisioner) do
45
+ Kitchen::Provisioner::ChefSolo.new(config).finalize_config!(instance)
46
+ end
47
+
48
+ it "provisioner api_version is 2" do
49
+ provisioner.diagnose_plugin[:api_version].must_equal 2
50
+ end
51
+
52
+ it "plugin_version is set to Kitchen::VERSION" do
53
+ provisioner.diagnose_plugin[:version].must_equal Kitchen::VERSION
54
+ end
55
+
56
+ describe "default config" do
57
+
58
+ describe "for unix operating systems" do
59
+
60
+ before { platform.stubs(:os_type).returns("unix") }
61
+
62
+ it "sets :chef_solo_path to a path using :chef_omnibus_root" do
63
+ config[:chef_omnibus_root] = "/nice/place"
64
+
65
+ provisioner[:chef_solo_path].must_equal "/nice/place/bin/chef-solo"
66
+ end
67
+ end
68
+
69
+ describe "for windows operating systems" do
70
+
71
+ before { platform.stubs(:os_type).returns("windows") }
72
+
73
+ it "sets :chef_solo_path to a path using :chef_omnibus_root" do
74
+ config[:chef_omnibus_root] = "$env:systemdrive\\nice\\place"
75
+
76
+ provisioner[:chef_solo_path].
77
+ must_equal "$env:systemdrive\\nice\\place\\bin\\chef-solo.bat"
78
+ end
79
+ end
80
+
81
+ it "sets :solo_rb to an empty Hash" do
82
+ provisioner[:solo_rb].must_equal Hash.new
83
+ end
84
+ end
85
+
86
+ describe "#create_sandbox" do
87
+
88
+ before do
89
+ @root = Dir.mktmpdir
90
+ config[:kitchen_root] = @root
91
+ end
92
+
93
+ after do
94
+ FileUtils.remove_entry(@root)
95
+ begin
96
+ provisioner.cleanup_sandbox
97
+ rescue # rubocop:disable Lint/HandleExceptions
98
+ end
99
+ end
100
+
101
+ describe "solo.rb file" do
102
+
103
+ let(:file) do
104
+ IO.read(sandbox_path("solo.rb")).lines.map(&:chomp)
105
+ end
106
+
107
+ it "creates a solo.rb" do
108
+ provisioner.create_sandbox
109
+
110
+ sandbox_path("solo.rb").file?.must_equal true
111
+ end
112
+
113
+ it "logs a message on info" do
114
+ provisioner.create_sandbox
115
+
116
+ logged_output.string.must_match info_line("Preparing solo.rb")
117
+ end
118
+
119
+ it "logs a message on debug" do
120
+ provisioner.create_sandbox
121
+
122
+ logged_output.string.
123
+ must_match debug_line_starting_with("Creating solo.rb from {")
124
+ end
125
+
126
+ describe "defaults" do
127
+
128
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
129
+ def self.common_solo_rb_specs
130
+ it "sets node_name to the instance name" do
131
+ file.must_include %{node_name "#{instance.name}"}
132
+ end
133
+
134
+ it "sets checksum_path" do
135
+ file.must_include %{checksum_path "#{base}checksums"}
136
+ end
137
+
138
+ it "sets file_backup_path" do
139
+ file.must_include %{file_backup_path "#{base}backup"}
140
+ end
141
+
142
+ it "sets cookbook_path" do
143
+ file.must_include %{cookbook_path } +
144
+ %{["#{base}cookbooks", "#{base}site-cookbooks"]}
145
+ end
146
+
147
+ it "sets data_bag_path" do
148
+ file.must_include %{data_bag_path "#{base}data_bags"}
149
+ end
150
+
151
+ it "sets environment_path" do
152
+ file.must_include %{environment_path "#{base}environments"}
153
+ end
154
+
155
+ it "sets node_path" do
156
+ file.must_include %{node_path "#{base}nodes"}
157
+ end
158
+
159
+ it "sets role_path" do
160
+ file.must_include %{role_path "#{base}roles"}
161
+ end
162
+
163
+ it "sets client_path" do
164
+ file.must_include %{client_path "#{base}clients"}
165
+ end
166
+
167
+ it "sets user_path" do
168
+ file.must_include %{user_path "#{base}users"}
169
+ end
170
+
171
+ it "sets validation_key" do
172
+ file.must_include %{validation_key "#{base}validation.pem"}
173
+ end
174
+
175
+ it "sets client_key" do
176
+ file.must_include %{client_key "#{base}client.pem"}
177
+ end
178
+
179
+ it "sets chef_server_url" do
180
+ file.must_include %{chef_server_url "http://127.0.0.1:8889"}
181
+ end
182
+
183
+ it "sets encrypted_data_bag_secret" do
184
+ file.must_include %{encrypted_data_bag_secret } +
185
+ %{"#{base}encrypted_data_bag_secret"}
186
+ end
187
+ end
188
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
189
+
190
+ describe "for unix os types" do
191
+
192
+ before do
193
+ platform.stubs(:os_type).returns("unix")
194
+ provisioner.create_sandbox
195
+ end
196
+
197
+ let(:base) { "/tmp/kitchen/" }
198
+
199
+ common_solo_rb_specs
200
+ end
201
+
202
+ describe "for windows os types with full path" do
203
+
204
+ before do
205
+ platform.stubs(:os_type).returns("windows")
206
+ config[:root_path] = "\\a\\b"
207
+ provisioner.create_sandbox
208
+ end
209
+
210
+ let(:base) { "\\\\a\\\\b\\\\" }
211
+
212
+ common_solo_rb_specs
213
+ end
214
+
215
+ describe "for windows os types with $env:TEMP prefixed paths" do
216
+
217
+ before do
218
+ platform.stubs(:os_type).returns("windows")
219
+ config[:root_path] = "$env:TEMP\\a"
220
+ provisioner.create_sandbox
221
+ end
222
+
223
+ let(:base) { "\#{ENV['TEMP']}\\\\a\\\\" }
224
+
225
+ common_solo_rb_specs
226
+ end
227
+ end
228
+
229
+ it "supports overwriting defaults" do
230
+ config[:solo_rb] = {
231
+ :node_name => "eagles",
232
+ :user_path => "/a/b/c/u",
233
+ :client_key => "lol"
234
+ }
235
+ provisioner.create_sandbox
236
+
237
+ file.must_include %{node_name "eagles"}
238
+ file.must_include %{user_path "/a/b/c/u"}
239
+ file.must_include %{client_key "lol"}
240
+ end
241
+
242
+ it "supports adding new configuration" do
243
+ config[:solo_rb] = {
244
+ :dark_secret => "golang"
245
+ }
246
+ provisioner.create_sandbox
247
+
248
+ file.must_include %{dark_secret "golang"}
249
+ end
250
+
251
+ it "formats array values correctly" do
252
+ config[:solo_rb] = {
253
+ :foos => %w[foo1 foo2]
254
+ }
255
+ provisioner.create_sandbox
256
+
257
+ file.must_include %{foos ["foo1", "foo2"]}
258
+ end
259
+
260
+ it "formats integer values correctly" do
261
+ config[:solo_rb] = {
262
+ :foo => 7
263
+ }
264
+ provisioner.create_sandbox
265
+
266
+ file.must_include %{foo 7}
267
+ end
268
+
269
+ it "formats symbol-looking string values correctly" do
270
+ config[:solo_rb] = {
271
+ :foo => ":bar"
272
+ }
273
+ provisioner.create_sandbox
274
+
275
+ file.must_include %{foo :bar}
276
+ end
277
+
278
+ it "formats boolean values correctly" do
279
+ config[:solo_rb] = {
280
+ :foo => false,
281
+ :bar => true
282
+ }
283
+ provisioner.create_sandbox
284
+
285
+ file.must_include %{foo false}
286
+ file.must_include %{bar true}
287
+ end
288
+ end
289
+
290
+ def sandbox_path(path)
291
+ Pathname.new(provisioner.sandbox_path).join(path)
292
+ end
293
+ end
294
+
295
+ describe "#run_command" do
296
+
297
+ let(:cmd) { provisioner.run_command }
298
+
299
+ describe "common behavior" do
300
+
301
+ before { platform.stubs(:shell_type).returns("fake") }
302
+
303
+ it "prefixs the whole command with the command_prefix if set" do
304
+ config[:command_prefix] = "my_prefix"
305
+
306
+ cmd.must_match(/\Amy_prefix /)
307
+ end
308
+
309
+ it "does not prefix the command if command_prefix is not set" do
310
+ config[:command_prefix] = nil
311
+
312
+ cmd.wont_match(/\Amy_prefix /)
313
+ end
314
+ end
315
+
316
+ describe "for bourne shells" do
317
+
318
+ before { platform.stubs(:shell_type).returns("bourne") }
319
+
320
+ it "uses bourne shell" do
321
+ cmd.must_match(/\Ash -c '$/)
322
+ cmd.must_match(/'\Z/)
323
+ end
324
+
325
+ it "ends with a single quote" do
326
+ cmd.must_match(/'\Z/)
327
+ end
328
+
329
+ it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
330
+ config[:http_proxy] = "http://proxy"
331
+
332
+ cmd.lines.to_a[1..2].must_equal([
333
+ %{http_proxy="http://proxy"; export http_proxy\n},
334
+ %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n}
335
+ ])
336
+ end
337
+
338
+ it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
339
+ config[:https_proxy] = "https://proxy"
340
+
341
+ cmd.lines.to_a[1..2].must_equal([
342
+ %{https_proxy="https://proxy"; export https_proxy\n},
343
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
344
+ ])
345
+ end
346
+
347
+ it "exports all http proxy variables when both are set" do
348
+ config[:http_proxy] = "http://proxy"
349
+ config[:https_proxy] = "https://proxy"
350
+
351
+ cmd.lines.to_a[1..4].must_equal([
352
+ %{http_proxy="http://proxy"; export http_proxy\n},
353
+ %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
354
+ %{https_proxy="https://proxy"; export https_proxy\n},
355
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
356
+ ])
357
+ end
358
+
359
+ it "does no powershell PATH reloading for older chef omnibus packages" do
360
+ cmd.wont_match regexify(%{[System.Environment]::})
361
+ end
362
+
363
+ it "uses sudo for chef-solo when configured" do
364
+ config[:chef_omnibus_root] = "/c"
365
+ config[:sudo] = true
366
+
367
+ cmd.must_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
368
+ end
369
+
370
+ it "does not use sudo for chef-solo when configured" do
371
+ config[:chef_omnibus_root] = "/c"
372
+ config[:sudo] = false
373
+
374
+ cmd.must_match regexify("chef-solo ", :partial_line)
375
+ cmd.wont_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
376
+ end
377
+
378
+ it "sets config flag on chef-solo" do
379
+ cmd.must_match regexify(" --config /tmp/kitchen/solo.rb", :partial_line)
380
+ end
381
+
382
+ it "sets config flag for custom root_path" do
383
+ config[:root_path] = "/a/b"
384
+
385
+ cmd.must_match regexify(" --config /a/b/solo.rb", :partial_line)
386
+ end
387
+
388
+ it "sets json attributes flag on chef-solo" do
389
+ cmd.must_match regexify(
390
+ " --json-attributes /tmp/kitchen/dna.json", :partial_line)
391
+ end
392
+
393
+ it "sets json attribtes flag for custom root_path" do
394
+ config[:root_path] = "/booyah"
395
+
396
+ cmd.must_match regexify(
397
+ " --json-attributes /booyah/dna.json", :partial_line)
398
+ end
399
+
400
+ it "sets log level flag on chef-solo to auto by default" do
401
+ cmd.must_match regexify(" --log_level auto", :partial_line)
402
+ end
403
+
404
+ it "set log level flag for custom level" do
405
+ config[:log_level] = :extreme
406
+
407
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
408
+ end
409
+
410
+ it "sets force formatter flag on chef-solo" do
411
+ cmd.must_match regexify(" --force-formatter", :partial_line)
412
+ end
413
+
414
+ it "sets no color flag on chef-solo" do
415
+ cmd.must_match regexify(" --no-color", :partial_line)
416
+ end
417
+
418
+ it "does not set logfile flag by default" do
419
+ cmd.wont_match regexify(" --logfile ", :partial_line)
420
+ end
421
+
422
+ it "sets logfile flag for custom value" do
423
+ config[:log_file] = "/a/out.log"
424
+
425
+ cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
426
+ end
427
+
428
+ it "sets profile-ruby flag when config element is set" do
429
+ config[:profile_ruby] = true
430
+
431
+ cmd.must_match regexify(
432
+ " --profile-ruby", :partial_line)
433
+ end
434
+
435
+ it "does not set profile-ruby flag when config element is falsey" do
436
+ config[:profile_ruby] = false
437
+
438
+ cmd.wont_match regexify(" --profile-ruby", :partial_line)
439
+ end
440
+ end
441
+
442
+ describe "for powershell shells on windows os types" do
443
+
444
+ before do
445
+ platform.stubs(:shell_type).returns("powershell")
446
+ platform.stubs(:os_type).returns("windows")
447
+ end
448
+
449
+ it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
450
+ config[:http_proxy] = "http://proxy"
451
+
452
+ cmd.lines.to_a[0..1].must_equal([
453
+ %{$env:http_proxy = "http://proxy"\n},
454
+ %{$env:HTTP_PROXY = "http://proxy"\n}
455
+ ])
456
+ end
457
+
458
+ it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
459
+ config[:https_proxy] = "https://proxy"
460
+
461
+ cmd.lines.to_a[0..1].must_equal([
462
+ %{$env:https_proxy = "https://proxy"\n},
463
+ %{$env:HTTPS_PROXY = "https://proxy"\n}
464
+ ])
465
+ end
466
+
467
+ it "exports all http proxy variables when both are set" do
468
+ config[:http_proxy] = "http://proxy"
469
+ config[:https_proxy] = "https://proxy"
470
+
471
+ cmd.lines.to_a[0..3].must_equal([
472
+ %{$env:http_proxy = "http://proxy"\n},
473
+ %{$env:HTTP_PROXY = "http://proxy"\n},
474
+ %{$env:https_proxy = "https://proxy"\n},
475
+ %{$env:HTTPS_PROXY = "https://proxy"\n}
476
+ ])
477
+ end
478
+
479
+ it "reloads PATH for older chef omnibus packages" do
480
+ cmd.must_match regexify("$env:PATH = " +
481
+ %{[System.Environment]::GetEnvironmentVariable("PATH","Machine")})
482
+ end
483
+
484
+ it "calls the chef-solo command from :chef_solo_path" do
485
+ config[:chef_solo_path] = "\\r\\chef-solo.bat"
486
+
487
+ cmd.must_match regexify("& \\r\\chef-solo.bat ", :partial_line)
488
+ end
489
+
490
+ it "sets config flag on chef-solo" do
491
+ cmd.must_match regexify(
492
+ " --config $env:TEMP\\kitchen\\solo.rb", :partial_line)
493
+ end
494
+
495
+ it "sets config flag for custom root_path" do
496
+ config[:root_path] = "\\a\\b"
497
+
498
+ cmd.must_match regexify(
499
+ " --config \\a\\b\\solo.rb", :partial_line)
500
+ end
501
+
502
+ it "sets json attributes flag on chef-solo" do
503
+ cmd.must_match regexify(
504
+ " --json-attributes $env:TEMP\\kitchen\\dna.json", :partial_line)
505
+ end
506
+
507
+ it "sets json attribtes flag for custom root_path" do
508
+ config[:root_path] = "\\booyah"
509
+
510
+ cmd.must_match regexify(
511
+ " --json-attributes \\booyah\\dna.json", :partial_line)
512
+ end
513
+
514
+ it "sets log level flag on chef-solo to auto by default" do
515
+ cmd.must_match regexify(" --log_level auto", :partial_line)
516
+ end
517
+
518
+ it "set log level flag for custom level" do
519
+ config[:log_level] = :extreme
520
+
521
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
522
+ end
523
+
524
+ it "sets force formatter flag on chef-solo" do
525
+ cmd.must_match regexify(" --force-formatter", :partial_line)
526
+ end
527
+
528
+ it "sets no color flag on chef-solo" do
529
+ cmd.must_match regexify(" --no-color", :partial_line)
530
+ end
531
+
532
+ it "does not set logfile flag by default" do
533
+ cmd.wont_match regexify(" --logfile ", :partial_line)
534
+ end
535
+
536
+ it "sets logfile flag for custom value" do
537
+ config[:log_file] = "\\a\\out.log"
538
+
539
+ cmd.must_match regexify(" --logfile \\a\\out.log", :partial_line)
540
+ end
541
+ end
542
+ end
543
+
544
+ def info_line(msg)
545
+ %r{^I, .* : #{Regexp.escape(msg)}$}
546
+ end
547
+
548
+ def debug_line_starting_with(msg)
549
+ %r{^D, .* : #{Regexp.escape(msg)}}
550
+ end
551
+
552
+ def regexify(str, line = :whole_line)
553
+ r = Regexp.escape(str)
554
+ r = "^\s*#{r}$" if line == :whole_line
555
+ Regexp.new(r)
556
+ end
557
+ end