test-kitchen 1.6.0 → 1.7.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 (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,136 +1,136 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
4
- #
5
- # Copyright (C) 2015, HiganWorks LLC
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_apply"
23
-
24
- describe Kitchen::Provisioner::ChefApply 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::ChefApply.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
- it "sets :chef_apply_path to a path using :chef_omnibus_root" do
59
- config[:chef_omnibus_root] = "/nice/place"
60
-
61
- provisioner[:chef_apply_path].must_equal "/nice/place/bin/chef-apply"
62
- end
63
- end
64
-
65
- describe "#create_sandbox" do
66
-
67
- before do
68
- @root = Dir.mktmpdir
69
- config[:kitchen_root] = @root
70
- end
71
-
72
- after do
73
- FileUtils.remove_entry(@root)
74
- begin
75
- provisioner.cleanup_sandbox
76
- rescue # rubocop:disable Lint/HandleExceptions
77
- end
78
- end
79
- end
80
-
81
- describe "#run_command" do
82
-
83
- before do
84
- config[:run_list] = %w[appry_recipe1 appry_recipe2]
85
- end
86
-
87
- let(:cmd) { provisioner.run_command }
88
-
89
- describe "for bourne shells" do
90
-
91
- before { platform.stubs(:shell_type).returns("bourne") }
92
-
93
- it "uses bourne shell" do
94
- cmd.must_match(/\Ash -c '$/)
95
- cmd.must_match(/'\Z/)
96
- end
97
-
98
- it "uses sudo for chef-apply when configured" do
99
- config[:chef_omnibus_root] = "/c"
100
- config[:sudo] = true
101
-
102
- cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe1.rb ", :partial_line)
103
- cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe2.rb ", :partial_line)
104
- end
105
-
106
- it "does not use sudo for chef-apply when configured" do
107
- config[:chef_omnibus_root] = "/c"
108
- config[:sudo] = false
109
-
110
- cmd.must_match regexify("chef-apply apply/appry_recipe1.rb ", :partial_line)
111
- cmd.must_match regexify("chef-apply apply/appry_recipe2.rb ", :partial_line)
112
- cmd.wont_match regexify("sudo -E /c/bin/chef-apply ")
113
- end
114
-
115
- it "sets log level flag on chef-apply to auto by default" do
116
- cmd.must_match regexify(" --log_level auto", :partial_line)
117
- end
118
-
119
- it "set log level flag for custom level" do
120
- config[:log_level] = :extreme
121
-
122
- cmd.must_match regexify(" --log_level extreme", :partial_line)
123
- end
124
-
125
- it "sets no color flag on chef-apply" do
126
- cmd.must_match regexify(" --no-color", :partial_line)
127
- end
128
- end
129
- end
130
-
131
- def regexify(str, line = :whole_line)
132
- r = Regexp.escape(str)
133
- r = "^\s*#{r}$" if line == :whole_line
134
- Regexp.new(r)
135
- end
136
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
4
+ #
5
+ # Copyright (C) 2015, HiganWorks LLC
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_apply"
23
+
24
+ describe Kitchen::Provisioner::ChefApply 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::ChefApply.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
+ it "sets :chef_apply_path to a path using :chef_omnibus_root" do
59
+ config[:chef_omnibus_root] = "/nice/place"
60
+
61
+ provisioner[:chef_apply_path].must_equal "/nice/place/bin/chef-apply"
62
+ end
63
+ end
64
+
65
+ describe "#create_sandbox" do
66
+
67
+ before do
68
+ @root = Dir.mktmpdir
69
+ config[:kitchen_root] = @root
70
+ end
71
+
72
+ after do
73
+ FileUtils.remove_entry(@root)
74
+ begin
75
+ provisioner.cleanup_sandbox
76
+ rescue # rubocop:disable Lint/HandleExceptions
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#run_command" do
82
+
83
+ before do
84
+ config[:run_list] = %w[appry_recipe1 appry_recipe2]
85
+ end
86
+
87
+ let(:cmd) { provisioner.run_command }
88
+
89
+ describe "for bourne shells" do
90
+
91
+ before { platform.stubs(:shell_type).returns("bourne") }
92
+
93
+ it "uses bourne shell" do
94
+ cmd.must_match(/\Ash -c '$/)
95
+ cmd.must_match(/'\Z/)
96
+ end
97
+
98
+ it "uses sudo for chef-apply when configured" do
99
+ config[:chef_omnibus_root] = "/c"
100
+ config[:sudo] = true
101
+
102
+ cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe1.rb ", :partial_line)
103
+ cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe2.rb ", :partial_line)
104
+ end
105
+
106
+ it "does not use sudo for chef-apply when configured" do
107
+ config[:chef_omnibus_root] = "/c"
108
+ config[:sudo] = false
109
+
110
+ cmd.must_match regexify("chef-apply apply/appry_recipe1.rb ", :partial_line)
111
+ cmd.must_match regexify("chef-apply apply/appry_recipe2.rb ", :partial_line)
112
+ cmd.wont_match regexify("sudo -E /c/bin/chef-apply ")
113
+ end
114
+
115
+ it "sets log level flag on chef-apply to auto by default" do
116
+ cmd.must_match regexify(" --log_level auto", :partial_line)
117
+ end
118
+
119
+ it "set log level flag for custom level" do
120
+ config[:log_level] = :extreme
121
+
122
+ cmd.must_match regexify(" --log_level extreme", :partial_line)
123
+ end
124
+
125
+ it "sets no color flag on chef-apply" do
126
+ cmd.must_match regexify(" --no-color", :partial_line)
127
+ end
128
+ end
129
+ end
130
+
131
+ def regexify(str, line = :whole_line)
132
+ r = Regexp.escape(str)
133
+ r = "^\s*#{r}$" if line == :whole_line
134
+ Regexp.new(r)
135
+ end
136
+ end
@@ -1,1067 +1,1161 @@
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_base"
23
-
24
- describe Kitchen::Provisioner::ChefBase 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
- let(:default_version) { "true" }
31
-
32
- let(:config) do
33
- { :test_base_path => "/basist", :kitchen_root => "/rooty" }
34
- end
35
-
36
- let(:instance) do
37
- stub(
38
- :name => "coolbeans",
39
- :logger => logger,
40
- :suite => suite,
41
- :platform => platform
42
- )
43
- end
44
-
45
- let(:provisioner) do
46
- Class.new(Kitchen::Provisioner::ChefBase) {
47
- def calculate_path(path, _opts = {})
48
- "<calculated>/#{path}"
49
- end
50
- }.new(config).finalize_config!(instance)
51
- end
52
-
53
- describe "configuration" do
54
-
55
- describe "for unix operating systems" do
56
-
57
- before { platform.stubs(:os_type).returns("unix") }
58
-
59
- it ":chef_omnibus_url has a default" do
60
- provisioner[:chef_omnibus_url].
61
- must_equal "https://www.chef.io/chef/install.sh"
62
- end
63
-
64
- it ":chef_metadata_url defaults to nil" do
65
- provisioner[:chef_metadata_url].must_equal(nil)
66
- end
67
- end
68
-
69
- describe "for windows operating systems" do
70
-
71
- before { platform.stubs(:os_type).returns("windows") }
72
-
73
- it ":chef_omnibus_url has a default" do
74
- provisioner[:chef_omnibus_url].
75
- must_equal "https://www.chef.io/chef/install.sh"
76
- end
77
-
78
- end
79
-
80
- it ":require_chef_omnibus defaults to true" do
81
- provisioner[:require_chef_omnibus].must_equal true
82
- end
83
-
84
- it ":chef_omnibus_install_options defaults to nil" do
85
- provisioner[:chef_omnibus_install_options].must_equal nil
86
- end
87
-
88
- it ":run_list defaults to an empty array" do
89
- provisioner[:run_list].must_equal []
90
- end
91
-
92
- it ":attributes defaults to an empty hash" do
93
- provisioner[:attributes].must_equal Hash.new
94
- end
95
-
96
- it ":log_file defaults to nil" do
97
- provisioner[:log_file].must_equal nil
98
- end
99
-
100
- it ":cookbook_files_glob includes recipes" do
101
- provisioner[:cookbook_files_glob].must_match %r{,recipes/}
102
- end
103
-
104
- it ":data_path uses calculate_path and is expanded" do
105
- provisioner[:data_path].
106
- must_equal os_safe_root_path("/rooty/<calculated>/data")
107
- end
108
-
109
- it ":data_bags_path uses calculate_path and is expanded" do
110
- provisioner[:data_bags_path].
111
- must_equal os_safe_root_path("/rooty/<calculated>/data_bags")
112
- end
113
-
114
- it ":environments_path uses calculate_path and is expanded" do
115
- provisioner[:environments_path].
116
- must_equal os_safe_root_path("/rooty/<calculated>/environments")
117
- end
118
-
119
- it ":nodes_path uses calculate_path and is expanded" do
120
- provisioner[:nodes_path].
121
- must_equal os_safe_root_path("/rooty/<calculated>/nodes")
122
- end
123
-
124
- it ":roles_path uses calculate_path and is expanded" do
125
- provisioner[:roles_path].
126
- must_equal os_safe_root_path("/rooty/<calculated>/roles")
127
- end
128
-
129
- it ":clients_path uses calculate_path and is expanded" do
130
- provisioner[:clients_path].
131
- must_equal os_safe_root_path("/rooty/<calculated>/clients")
132
- end
133
-
134
- it "...secret_key_path uses calculate_path and is expanded" do
135
- provisioner[:encrypted_data_bag_secret_key_path].
136
- must_equal os_safe_root_path("/rooty/<calculated>/encrypted_data_bag_secret_key")
137
- end
138
- end
139
-
140
- describe "#install_command" do
141
-
142
- before do
143
- platform.stubs(:shell_type).returns("bourne")
144
- Mixlib::Install.stubs(:new).returns(installer)
145
- end
146
-
147
- let(:installer) { stub(:root => "/rooty", :install_command => "make_it_so") }
148
-
149
- let(:cmd) { provisioner.install_command }
150
-
151
- let(:install_opts) {
152
- { :omnibus_url => "https://www.chef.io/chef/install.sh",
153
- :project => nil, :install_flags => nil, :sudo_command => "sudo -E",
154
- :http_proxy => nil, :https_proxy => nil }
155
- }
156
-
157
- it "returns nil if :require_chef_omnibus is falsey" do
158
- config[:require_chef_omnibus] = false
159
-
160
- installer.expects(:root).never
161
- installer.expects(:install_command).never
162
- cmd.must_equal nil
163
- end
164
-
165
- describe "common behaviour" do
166
- before do
167
- installer.expects(:root).at_least_once.returns("/opt/chef")
168
- installer.expects(:install_command)
169
- end
170
-
171
- it "passes sensible defaults" do
172
- Mixlib::Install.expects(:new).
173
- with(default_version, false, install_opts).returns(installer)
174
- cmd
175
- end
176
-
177
- it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
178
- config[:http_proxy] = "http://proxy"
179
- install_opts[:http_proxy] = "http://proxy"
180
-
181
- Mixlib::Install.expects(:new).
182
- with(default_version, false, install_opts).returns(installer)
183
- cmd
184
- end
185
-
186
- it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
187
- config[:https_proxy] = "https://proxy"
188
- install_opts[:https_proxy] = "https://proxy"
189
-
190
- Mixlib::Install.expects(:new).
191
- with(default_version, false, install_opts).returns(installer)
192
- cmd
193
- end
194
-
195
- it "exports all http proxy variables when both are set" do
196
- config[:http_proxy] = "http://proxy"
197
- config[:https_proxy] = "https://proxy"
198
- install_opts[:http_proxy] = "http://proxy"
199
- install_opts[:https_proxy] = "https://proxy"
200
-
201
- Mixlib::Install.expects(:new).
202
- with(default_version, false, install_opts).returns(installer)
203
- cmd
204
- end
205
-
206
- it "installs chef using :chef_omnibus_url, if necessary" do
207
- config[:chef_omnibus_url] = "FROM_HERE"
208
- install_opts[:omnibus_url] = "FROM_HERE"
209
-
210
- Mixlib::Install.expects(:new).
211
- with(default_version, false, install_opts).returns(installer)
212
- cmd
213
- end
214
-
215
- it "will install a specific version of chef, if necessary" do
216
- config[:require_chef_omnibus] = "1.2.3"
217
-
218
- Mixlib::Install.expects(:new).
219
- with("1.2.3", false, install_opts).returns(installer)
220
- cmd
221
- end
222
-
223
- it "will install a major/minor version of chef, if necessary" do
224
- config[:require_chef_omnibus] = "11.10"
225
-
226
- Mixlib::Install.expects(:new).
227
- with("11.10", false, install_opts).returns(installer)
228
- cmd
229
- end
230
-
231
- it "will install a major version of chef, if necessary" do
232
- config[:require_chef_omnibus] = "12"
233
-
234
- Mixlib::Install.expects(:new).
235
- with("12", false, install_opts).returns(installer)
236
- cmd
237
- end
238
-
239
- it "will install a downcaased version string of chef, if necessary" do
240
- config[:require_chef_omnibus] = "10.1.0.RC.1"
241
-
242
- Mixlib::Install.expects(:new).
243
- with("10.1.0.rc.1", false, install_opts).returns(installer)
244
- cmd
245
- end
246
-
247
- it "will install a nightly, if necessary" do
248
- config[:require_chef_omnibus] =
249
- "12.5.0-current.0+20150721082808.git.14.c91b337-1"
250
-
251
- Mixlib::Install.expects(:new).with(
252
- "12.5.0-current.0+20150721082808.git.14.c91b337-1",
253
- false,
254
- install_opts
255
- ).returns(installer)
256
- cmd
257
- end
258
-
259
- it "will install the latest chef, if necessary" do
260
- config[:require_chef_omnibus] = "latest"
261
-
262
- Mixlib::Install.expects(:new).
263
- with("latest", false, install_opts).returns(installer)
264
- cmd
265
- end
266
-
267
- it "will install a version of chef, unless it exists" do
268
- config[:require_chef_omnibus] = true
269
-
270
- Mixlib::Install.expects(:new).
271
- with(default_version, false, install_opts).returns(installer)
272
- cmd
273
- end
274
-
275
- it "will pass a project, when given" do
276
- config[:chef_omnibus_install_options] = "-P chefdk"
277
- install_opts[:install_flags] = "-P chefdk"
278
- install_opts[:project] = "chefdk"
279
-
280
- Mixlib::Install.expects(:new).
281
- with(default_version, false, install_opts).returns(installer)
282
- cmd
283
- end
284
-
285
- it "will pass install options and version info, when given" do
286
- config[:require_chef_omnibus] = "11"
287
- config[:chef_omnibus_install_options] = "-d /tmp/place"
288
- install_opts[:install_flags] = "-d /tmp/place"
289
-
290
- Mixlib::Install.expects(:new).
291
- with("11", false, install_opts).returns(installer)
292
- cmd
293
- end
294
-
295
- it "will set the install root" do
296
- config[:chef_omnibus_root] = "/tmp/test"
297
- install_opts[:root] = "/tmp/test"
298
-
299
- Mixlib::Install.expects(:new).
300
- with(default_version, false, install_opts).returns(installer)
301
- cmd
302
- end
303
-
304
- it "prefixs the whole command with the command_prefix if set" do
305
- config[:command_prefix] = "my_prefix"
306
-
307
- cmd.must_match(/\Amy_prefix /)
308
- end
309
-
310
- it "does not prefix the command if command_prefix is not set" do
311
- config[:command_prefix] = nil
312
-
313
- cmd.wont_match(/\Amy_prefix /)
314
- end
315
- end
316
-
317
- describe "for bourne shells" do
318
- before do
319
- installer.expects(:root).at_least_once.returns("/opt/chef")
320
- installer.expects(:install_command).returns("my_install_command")
321
- end
322
-
323
- it "prepends sudo for sh commands when :sudo is set" do
324
- config[:sudo] = true
325
- config[:sudo_command] = "my_sudo_command"
326
- install_opts_clone = install_opts.clone
327
- install_opts_clone[:sudo_command] = config[:sudo_command]
328
-
329
- Mixlib::Install.expects(:new).
330
- with(default_version, false, install_opts_clone).returns(installer)
331
- cmd.must_equal "my_sudo_command my_install_command"
332
- end
333
-
334
- it "does not sudo for sh commands when :sudo is falsey" do
335
- config[:sudo] = false
336
-
337
- install_opts_clone = install_opts.clone
338
- install_opts_clone[:sudo_command] = ""
339
- Mixlib::Install.expects(:new).
340
- with(default_version, false, install_opts_clone).returns(installer)
341
- cmd.must_equal "my_install_command"
342
- end
343
- end
344
-
345
- describe "for powershell shells on windows os types" do
346
- before do
347
- installer.expects(:root).at_least_once.returns("/opt/chef")
348
- installer.expects(:install_command)
349
- platform.stubs(:shell_type).returns("powershell")
350
- platform.stubs(:os_type).returns("windows")
351
- end
352
-
353
- it "sets the powershell flag for Mixlib::Install" do
354
- install_opts_clone = install_opts.clone
355
- install_opts_clone[:sudo_command] = ""
356
- Mixlib::Install.expects(:new).
357
- with("", true, install_opts_clone).returns(installer)
358
- cmd
359
- end
360
- end
361
- end
362
-
363
- describe "#init_command" do
364
-
365
- let(:cmd) { provisioner.init_command }
366
-
367
- describe "common behavior" do
368
-
369
- before { platform.stubs(:shell_type).returns("fake") }
370
-
371
- it "prefixs the whole command with the command_prefix if set" do
372
- config[:command_prefix] = "my_prefix"
373
-
374
- cmd.must_match(/\Amy_prefix /)
375
- end
376
-
377
- it "does not prefix the command if command_prefix is not set" do
378
- config[:command_prefix] = nil
379
-
380
- cmd.wont_match(/\Amy_prefix /)
381
- end
382
- end
383
-
384
- describe "for bourne shells" do
385
-
386
- before { platform.stubs(:shell_type).returns("bourne") }
387
-
388
- it "uses bourne shell" do
389
- cmd.must_match(/\Ash -c '$/)
390
- cmd.must_match(/'\Z/)
391
- end
392
-
393
- it "ends with a single quote" do
394
- cmd.must_match(/'\Z/)
395
- end
396
-
397
- it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
398
- config[:http_proxy] = "http://proxy"
399
-
400
- cmd.lines.to_a[1..2].must_equal([
401
- %{http_proxy="http://proxy"; export http_proxy\n},
402
- %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n}
403
- ])
404
- end
405
-
406
- it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
407
- config[:https_proxy] = "https://proxy"
408
-
409
- cmd.lines.to_a[1..2].must_equal([
410
- %{https_proxy="https://proxy"; export https_proxy\n},
411
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
412
- ])
413
- end
414
-
415
- it "exports all http proxy variables when both are set" do
416
- config[:http_proxy] = "http://proxy"
417
- config[:https_proxy] = "https://proxy"
418
-
419
- cmd.lines.to_a[1..4].must_equal([
420
- %{http_proxy="http://proxy"; export http_proxy\n},
421
- %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
422
- %{https_proxy="https://proxy"; export https_proxy\n},
423
- %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
424
- ])
425
- end
426
-
427
- it "prepends sudo for rm when :sudo is set" do
428
- config[:sudo] = true
429
-
430
- cmd.must_match regexify(%{sudo_rm="sudo -E rm"})
431
- end
432
-
433
- it "does not sudo for sh commands when :sudo is falsey" do
434
- config[:sudo] = false
435
-
436
- cmd.must_match regexify(%{sudo_rm="rm"})
437
- end
438
-
439
- it "sets chef component dirs for deletion" do
440
- config[:root_path] = "/route"
441
- dirs = %W[
442
- /route/clients /route/cookbooks /route/data /route/data_bags
443
- /route/encrypted_data_bag_secret /route/environments /route/roles
444
- ].join(" ")
445
-
446
- cmd.must_match regexify(%{dirs="#{dirs}"})
447
- end
448
-
449
- it "sets the root_path from :root_path" do
450
- config[:root_path] = "RIGHT_HERE"
451
-
452
- cmd.must_match regexify(%{root_path="RIGHT_HERE"})
453
- end
454
- end
455
-
456
- describe "for powershell shells on windows os types" do
457
-
458
- before do
459
- platform.stubs(:shell_type).returns("powershell")
460
- platform.stubs(:os_type).returns("windows")
461
- end
462
-
463
- it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
464
- config[:http_proxy] = "http://proxy"
465
-
466
- cmd.lines.to_a[0..1].must_equal([
467
- %{$env:http_proxy = "http://proxy"\n},
468
- %{$env:HTTP_PROXY = "http://proxy"\n}
469
- ])
470
- end
471
-
472
- it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
473
- config[:https_proxy] = "https://proxy"
474
-
475
- cmd.lines.to_a[0..1].must_equal([
476
- %{$env:https_proxy = "https://proxy"\n},
477
- %{$env:HTTPS_PROXY = "https://proxy"\n}
478
- ])
479
- end
480
-
481
- it "exports all http proxy variables when both are set" do
482
- config[:http_proxy] = "http://proxy"
483
- config[:https_proxy] = "https://proxy"
484
-
485
- cmd.lines.to_a[0..3].must_equal([
486
- %{$env:http_proxy = "http://proxy"\n},
487
- %{$env:HTTP_PROXY = "http://proxy"\n},
488
- %{$env:https_proxy = "https://proxy"\n},
489
- %{$env:HTTPS_PROXY = "https://proxy"\n}
490
- ])
491
- end
492
-
493
- it "sets chef component dirs for deletion" do
494
- config[:root_path] = "\\route"
495
- dirs = %W[
496
- "\\route\\clients" "\\route\\cookbooks" "\\route\\data"
497
- "\\route\\data_bags" "\\route\\encrypted_data_bag_secret"
498
- "\\route\\environments" "\\route\\roles"
499
- ].join(", ")
500
-
501
- cmd.must_match regexify(%{$dirs = @(#{dirs})})
502
- end
503
-
504
- it "sets the root_path from :root_path" do
505
- config[:root_path] = "RIGHT_HERE"
506
-
507
- cmd.must_match regexify(%{$root_path = "RIGHT_HERE"})
508
- end
509
- end
510
- end
511
-
512
- describe "#create_sandbox" do
513
-
514
- before do
515
- @root = Dir.mktmpdir
516
- config[:kitchen_root] = @root
517
- end
518
-
519
- after do
520
- FileUtils.remove_entry(@root)
521
- begin
522
- provisioner.cleanup_sandbox
523
- rescue # rubocop:disable Lint/HandleExceptions
524
- end
525
- end
526
-
527
- let(:provisioner) do
528
- Class.new(Kitchen::Provisioner::ChefBase) {
529
- default_config :generic_rb, {}
530
-
531
- def create_sandbox
532
- super
533
-
534
- data = default_config_rb.merge(config[:generic_rb])
535
- File.open(File.join(sandbox_path, "generic.rb"), "wb") do |file|
536
- file.write(format_config_file(data))
537
- end
538
- end
539
- }.new(config).finalize_config!(instance)
540
- end
541
-
542
- describe "json file" do
543
-
544
- let(:json) { JSON.parse(IO.read(sandbox_path("dna.json"))) }
545
-
546
- it "creates a json file with node attributes" do
547
- config[:attributes] = { "one" => { "two" => "three" } }
548
- provisioner.create_sandbox
549
-
550
- json["one"].must_equal("two" => "three")
551
- end
552
-
553
- it "creates a json file with run_list" do
554
- config[:run_list] = %w[alpha bravo charlie]
555
- provisioner.create_sandbox
556
-
557
- json["run_list"].must_equal %w[alpha bravo charlie]
558
- end
559
-
560
- it "creates a json file with an empty run_list" do
561
- config[:run_list] = []
562
- provisioner.create_sandbox
563
-
564
- json["run_list"].must_equal []
565
- end
566
-
567
- it "logs a message on info" do
568
- provisioner.create_sandbox
569
-
570
- logged_output.string.must_match info_line("Preparing dna.json")
571
- end
572
-
573
- it "logs a message on debug" do
574
- config[:run_list] = ["yo"]
575
- provisioner.create_sandbox
576
-
577
- logged_output.string.
578
- must_match debug_line(%|Creating dna.json from {:run_list=>["yo"]}|)
579
- end
580
- end
581
-
582
- it "creates a cache directory" do
583
- provisioner.create_sandbox
584
-
585
- sandbox_path("cache").directory?.must_equal true
586
- end
587
-
588
- %w[data data_bags environments nodes roles clients].each do |thing|
589
- describe "#{thing} files" do
590
-
591
- before do
592
- create_files_under("#{config[:kitchen_root]}/my_#{thing}")
593
- config[:"#{thing}_path"] = "#{config[:kitchen_root]}/my_#{thing}"
594
- end
595
-
596
- it "skips directory creation if :#{thing}_path is not set" do
597
- config[:"#{thing}_path"] = nil
598
- provisioner.create_sandbox
599
-
600
- sandbox_path(thing).directory?.must_equal false
601
- end
602
-
603
- it "copies tree from :#{thing}_path into sandbox" do
604
- provisioner.create_sandbox
605
-
606
- sandbox_path("#{thing}/alpha.txt").file?.must_equal true
607
- IO.read(sandbox_path("#{thing}/alpha.txt")).must_equal "stuff"
608
- sandbox_path("#{thing}/sub").directory?.must_equal true
609
- sandbox_path("#{thing}/sub/bravo.txt").file?.must_equal true
610
- IO.read(sandbox_path("#{thing}/sub/bravo.txt")).must_equal "junk"
611
- end
612
-
613
- it "logs a message on info" do
614
- provisioner.create_sandbox
615
-
616
- logged_output.string.must_match info_line("Preparing #{thing}")
617
- end
618
-
619
- it "logs a message on debug" do
620
- provisioner.create_sandbox
621
-
622
- logged_output.string.must_match debug_line(
623
- "Using #{thing} from #{config[:kitchen_root]}/my_#{thing}")
624
- end
625
- end
626
- end
627
-
628
- describe "secret files" do
629
-
630
- before do
631
- config[:encrypted_data_bag_secret_key_path] =
632
- "#{config[:kitchen_root]}/my_secret"
633
- File.open("#{config[:kitchen_root]}/my_secret", "wb") do |file|
634
- file.write("p@ss")
635
- end
636
- end
637
-
638
- it "skips file if :encrypted_data_bag_secret_key_path is not set" do
639
- config[:encrypted_data_bag_secret_key_path] = nil
640
- provisioner.create_sandbox
641
-
642
- sandbox_path("encrypted_data_bag_secret").file?.must_equal false
643
- end
644
-
645
- it "copies file from :encrypted_data_bag_secret_key_path into sandbox" do
646
- provisioner.create_sandbox
647
-
648
- sandbox_path("encrypted_data_bag_secret").file?.must_equal true
649
- IO.read(sandbox_path("encrypted_data_bag_secret")).must_equal "p@ss"
650
- end
651
-
652
- it "logs a message on info" do
653
- provisioner.create_sandbox
654
-
655
- logged_output.string.must_match info_line("Preparing secret")
656
- end
657
-
658
- it "logs a message on debug" do
659
- provisioner.create_sandbox
660
-
661
- logged_output.string.must_match debug_line(
662
- "Using secret from #{config[:kitchen_root]}/my_secret")
663
- end
664
- end
665
-
666
- describe "cookbooks" do
667
-
668
- let(:kitchen_root) { config[:kitchen_root] }
669
-
670
- describe "with a cookbooks/ directory under kitchen_root" do
671
-
672
- it "copies cookbooks/" do
673
- create_cookbook("#{kitchen_root}/cookbooks/epache")
674
- create_cookbook("#{kitchen_root}/cookbooks/jahva")
675
- provisioner.create_sandbox
676
-
677
- sandbox_path("cookbooks/epache").directory?.must_equal true
678
- sandbox_path("cookbooks/epache/recipes/default.rb").
679
- file?.must_equal true
680
- sandbox_path("cookbooks/jahva").directory?.must_equal true
681
- sandbox_path("cookbooks/jahva/recipes/default.rb").
682
- file?.must_equal true
683
- end
684
-
685
- it "copies from kitchen_root as cookbook if it contains metadata.rb" do
686
- File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
687
- file.write("name 'wat'")
688
- end
689
- create_cookbook("#{kitchen_root}/cookbooks/bk")
690
- provisioner.create_sandbox
691
-
692
- sandbox_path("cookbooks/bk").directory?.must_equal true
693
- sandbox_path("cookbooks/wat").directory?.must_equal true
694
- sandbox_path("cookbooks/wat/metadata.rb").file?.must_equal true
695
- end
696
-
697
- it "copies site-cookbooks/ if it exists" do
698
- create_cookbook("#{kitchen_root}/cookbooks/upstream")
699
- create_cookbook("#{kitchen_root}/site-cookbooks/mine")
700
- provisioner.create_sandbox
701
-
702
- sandbox_path("cookbooks/upstream").directory?.must_equal true
703
- sandbox_path("cookbooks/mine").directory?.must_equal true
704
- sandbox_path("cookbooks/mine/attributes/all.rb").file?.must_equal true
705
- end
706
-
707
- it "logs a message on info for cookbooks/ directory" do
708
- create_cookbook("#{kitchen_root}/cookbooks/epache")
709
- provisioner.create_sandbox
710
-
711
- logged_output.string.must_match info_line(
712
- "Preparing cookbooks from project directory")
713
- end
714
-
715
- it "logs a meesage on debug for cookbooks/ directory" do
716
- create_cookbook("#{kitchen_root}/cookbooks/epache")
717
- provisioner.create_sandbox
718
-
719
- logged_output.string.must_match debug_line(
720
- "Using cookbooks from #{kitchen_root}/cookbooks")
721
- end
722
-
723
- it "logs a message on info for site-cookbooks/ directory" do
724
- create_cookbook("#{kitchen_root}/cookbooks/epache")
725
- create_cookbook("#{kitchen_root}/site-cookbooks/mine")
726
- provisioner.create_sandbox
727
-
728
- logged_output.string.must_match info_line(
729
- "Preparing site-cookbooks from project directory")
730
- end
731
-
732
- it "logs a meesage on debug for site-cookbooks/ directory" do
733
- create_cookbook("#{kitchen_root}/cookbooks/epache")
734
- create_cookbook("#{kitchen_root}/site-cookbooks/mine")
735
- provisioner.create_sandbox
736
-
737
- logged_output.string.must_match debug_line(
738
- "Using cookbooks from #{kitchen_root}/site-cookbooks")
739
- end
740
- end
741
-
742
- describe "with a cookbook as the project" do
743
-
744
- before do
745
- File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
746
- file.write("name 'wat'")
747
- end
748
- end
749
-
750
- it "copies from kitchen_root as cookbook if it contains metadata.rb" do
751
- provisioner.create_sandbox
752
-
753
- sandbox_path("cookbooks/wat").directory?.must_equal true
754
- sandbox_path("cookbooks/wat/metadata.rb").file?.must_equal true
755
- end
756
-
757
- it "logs a message on info" do
758
- provisioner.create_sandbox
759
-
760
- logged_output.string.must_match info_line(
761
- "Preparing current project directory as a cookbook")
762
- end
763
-
764
- it "logs a meesage on debug" do
765
- provisioner.create_sandbox
766
-
767
- logged_output.string.must_match debug_line(
768
- "Using metadata.rb from #{kitchen_root}/metadata.rb")
769
- end
770
-
771
- it "raises a UserError is name cannot be determined from metadata.rb" do
772
- File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
773
- file.write("nameeeeee 'wat'")
774
- end
775
-
776
- proc { provisioner.create_sandbox }.must_raise Kitchen::UserError
777
- end
778
- end
779
-
780
- describe "with no referenced cookbooks" do
781
-
782
- it "makes a fake cookbook" do
783
- name = File.basename(@root)
784
- provisioner.create_sandbox
785
-
786
- sandbox_path("cookbooks/#{name}").directory?.must_equal true
787
- sandbox_path("cookbooks/#{name}/metadata.rb").file?.must_equal true
788
- IO.read(sandbox_path("cookbooks/#{name}/metadata.rb")).
789
- must_equal %{name "#{name}"\n}
790
- end
791
-
792
- it "logs a warning" do
793
- provisioner.create_sandbox
794
-
795
- logged_output.string.must_match regexify(
796
- "Berksfile, Cheffile, cookbooks/, or metadata.rb not found",
797
- :partial_line
798
- )
799
- end
800
- end
801
-
802
- describe "with a Berksfile under kitchen_root" do
803
-
804
- let(:resolver) { stub(:resolve => true) }
805
-
806
- before do
807
- File.open("#{kitchen_root}/Berksfile", "wb") do |file|
808
- file.write("cookbook 'wat'")
809
- end
810
- Kitchen::Provisioner::Chef::Berkshelf.stubs(:new).returns(resolver)
811
- end
812
-
813
- it "raises a UserError if Berkshelf library can't be loaded" do
814
- proc { provisioner }.must_raise Kitchen::UserError
815
- end
816
-
817
- it "logs on debug that Berkshelf is loading" do
818
- Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
819
- provisioner
820
-
821
- logged_output.string.must_match debug_line(
822
- "Berksfile found at #{kitchen_root}/Berksfile, loading Berkshelf")
823
- end
824
-
825
- it "uses Berkshelf" do
826
- Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
827
- resolver.expects(:resolve)
828
-
829
- provisioner.create_sandbox
830
- end
831
-
832
- it "uses Kitchen.mutex for resolving" do
833
- Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
834
- Kitchen.mutex.expects(:synchronize)
835
-
836
- provisioner.create_sandbox
837
- end
838
- end
839
-
840
- describe "with a Cheffile under kitchen_root" do
841
-
842
- let(:resolver) { stub(:resolve => true) }
843
-
844
- before do
845
- File.open("#{kitchen_root}/Cheffile", "wb") do |file|
846
- file.write("cookbook 'wat'")
847
- end
848
- Kitchen::Provisioner::Chef::Librarian.stubs(:new).returns(resolver)
849
- end
850
-
851
- it "raises a UserError if Librarian library can't be loaded" do
852
- proc { provisioner }.must_raise Kitchen::UserError
853
- end
854
-
855
- it "logs on debug that Berkshelf is loading" do
856
- Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
857
- provisioner
858
-
859
- logged_output.string.must_match debug_line(
860
- "Cheffile found at #{kitchen_root}/Cheffile, loading Librarian-Chef"
861
- )
862
- end
863
-
864
- it "uses Librarian" do
865
- Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
866
- resolver.expects(:resolve)
867
-
868
- provisioner.create_sandbox
869
- end
870
-
871
- it "uses Kitchen.mutex for resolving" do
872
- Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
873
- Kitchen.mutex.expects(:synchronize)
874
-
875
- provisioner.create_sandbox
876
- end
877
- end
878
-
879
- describe "filtering cookbooks files" do
880
-
881
- it "retains all useful cookbook files" do
882
- create_full_cookbook("#{kitchen_root}/cookbooks/full")
883
- provisioner.create_sandbox
884
-
885
- full_cookbook_files.each do |file|
886
- sandbox_path("cookbooks/full/#{file}").file?.must_equal true
887
- end
888
- end
889
-
890
- it "strips extra cookbook files" do
891
- extras = %w[
892
- .gitignore tmp/librarian chefignore .git/info/excludes
893
- cookbooks/another/metadata.rb CONTRIBUTING.md metadata.py
894
- ]
895
-
896
- create_full_cookbook("#{kitchen_root}/cookbooks/full")
897
- extras.each do |file|
898
- create_file("#{kitchen_root}/cookbooks/full/#{file}")
899
- end
900
- provisioner.create_sandbox
901
-
902
- extras.each do |file|
903
- sandbox_path("cookbooks/full/#{file}").file?.must_equal false
904
- end
905
- end
906
-
907
- it "logs on info" do
908
- create_full_cookbook("#{kitchen_root}/cookbooks/full")
909
- provisioner.create_sandbox
910
-
911
- logged_output.string.must_match info_line(
912
- "Removing non-cookbook files before transfer")
913
- end
914
- end
915
-
916
- describe "Chef config files" do
917
-
918
- let(:file) do
919
- IO.read(sandbox_path("generic.rb")).lines.map(&:chomp)
920
- end
921
-
922
- it "#create_sanbox creates a generic.rb" do
923
- provisioner.create_sandbox
924
-
925
- sandbox_path("generic.rb").file?.must_equal true
926
- end
927
-
928
- describe "defaults" do
929
-
930
- before { provisioner.create_sandbox }
931
-
932
- it "sets node_name to the instance name" do
933
- file.must_include %{node_name "#{instance.name}"}
934
- end
935
-
936
- it "sets checksum_path" do
937
- file.must_include %{checksum_path "/tmp/kitchen/checksums"}
938
- end
939
-
940
- it "sets file_backup_path" do
941
- file.must_include %{file_backup_path "/tmp/kitchen/backup"}
942
- end
943
-
944
- it "sets cookbook_path" do
945
- file.must_include %{cookbook_path } +
946
- %{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
947
- end
948
-
949
- it "sets data_bag_path" do
950
- file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
951
- end
952
-
953
- it "sets environment_path" do
954
- file.must_include %{environment_path "/tmp/kitchen/environments"}
955
- end
956
-
957
- it "sets node_path" do
958
- file.must_include %{node_path "/tmp/kitchen/nodes"}
959
- end
960
-
961
- it "sets role_path" do
962
- file.must_include %{role_path "/tmp/kitchen/roles"}
963
- end
964
-
965
- it "sets client_path" do
966
- file.must_include %{client_path "/tmp/kitchen/clients"}
967
- end
968
-
969
- it "sets user_path" do
970
- file.must_include %{user_path "/tmp/kitchen/users"}
971
- end
972
-
973
- it "sets validation_key" do
974
- file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
975
- end
976
-
977
- it "sets client_key" do
978
- file.must_include %{client_key "/tmp/kitchen/client.pem"}
979
- end
980
-
981
- it "sets chef_server_url" do
982
- file.must_include %{chef_server_url "http://127.0.0.1:8889"}
983
- end
984
-
985
- it "sets encrypted_data_bag_secret" do
986
- file.must_include %{encrypted_data_bag_secret } +
987
- %{"/tmp/kitchen/encrypted_data_bag_secret"}
988
- end
989
- end
990
-
991
- it "supports overwriting defaults" do
992
- config[:generic_rb] = {
993
- :node_name => "eagles",
994
- :user_path => "/a/b/c/u",
995
- :chef_server_url => "https://whereever.io"
996
- }
997
- provisioner.create_sandbox
998
-
999
- file.must_include %{node_name "eagles"}
1000
- file.must_include %{user_path "/a/b/c/u"}
1001
- file.must_include %{chef_server_url "https://whereever.io"}
1002
- end
1003
-
1004
- it " supports adding new configuration" do
1005
- config[:generic_rb] = {
1006
- :dark_secret => "golang"
1007
- }
1008
- provisioner.create_sandbox
1009
-
1010
- file.must_include %{dark_secret "golang"}
1011
- end
1012
- end
1013
-
1014
- def create_cookbook(path)
1015
- %w[metadata.rb attributes/all.rb recipes/default.rb].each do |file|
1016
- create_file(File.join(path, file))
1017
- end
1018
- end
1019
-
1020
- def full_cookbook_files
1021
- %w[
1022
- README.org metadata.rb attributes/all.rb definitions/def.rb
1023
- files/default/config.conf libraries/one.rb libraries/two.rb
1024
- providers/sweet.rb recipes/default.rb resources/sweet.rb
1025
- templates/ubuntu/12.04/nginx.conf.erb
1026
- ]
1027
- end
1028
-
1029
- def create_full_cookbook(path)
1030
- full_cookbook_files.each { |file| create_file(File.join(path, file)) }
1031
- end
1032
-
1033
- def create_file(path)
1034
- FileUtils.mkdir_p(File.dirname(path))
1035
- File.open(path, "wb") { |f| f.write(path) }
1036
- end
1037
- end
1038
-
1039
- def sandbox_path(path)
1040
- Pathname.new(provisioner.sandbox_path).join(path)
1041
- end
1042
-
1043
- def create_files_under(path)
1044
- FileUtils.mkdir_p(File.join(path, "sub"))
1045
- File.open(File.join(path, "alpha.txt"), "wb") do |file|
1046
- file.write("stuff")
1047
- end
1048
- File.open(File.join(path, "sub", "bravo.txt"), "wb") do |file|
1049
- file.write("junk")
1050
- end
1051
- end
1052
-
1053
- def info_line(msg)
1054
- %r{^I, .* : #{Regexp.escape(msg)}$}
1055
- end
1056
-
1057
- def debug_line(msg)
1058
- %r{^D, .* : #{Regexp.escape(msg)}$}
1059
- end
1060
- end
1061
-
1062
- def regexify(str, line = :whole_line)
1063
- r = Regexp.escape(str)
1064
- r = "^\s*#{r}$" if line == :whole_line
1065
- Regexp.new(r)
1066
- end
1067
- 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_base"
23
+
24
+ describe Kitchen::Provisioner::ChefBase 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
+ let(:default_version) { true }
31
+
32
+ let(:config) do
33
+ { :test_base_path => "/basist", :kitchen_root => "/rooty" }
34
+ end
35
+
36
+ let(:instance) do
37
+ stub(
38
+ :name => "coolbeans",
39
+ :logger => logger,
40
+ :suite => suite,
41
+ :platform => platform
42
+ )
43
+ end
44
+
45
+ let(:provisioner) do
46
+ Class.new(Kitchen::Provisioner::ChefBase) {
47
+ def calculate_path(path, _opts = {})
48
+ "<calculated>/#{path}"
49
+ end
50
+ }.new(config).finalize_config!(instance)
51
+ end
52
+
53
+ describe "configuration" do
54
+
55
+ describe "for unix operating systems" do
56
+
57
+ before { platform.stubs(:os_type).returns("unix") }
58
+
59
+ it ":chef_omnibus_url has a default" do
60
+ provisioner[:chef_omnibus_url].
61
+ must_equal "https://www.chef.io/chef/install.sh"
62
+ end
63
+
64
+ it ":chef_metadata_url defaults to nil" do
65
+ provisioner[:chef_metadata_url].must_equal(nil)
66
+ end
67
+ end
68
+
69
+ describe "for windows operating systems" do
70
+
71
+ before { platform.stubs(:os_type).returns("windows") }
72
+
73
+ it ":chef_omnibus_url has a default" do
74
+ provisioner[:chef_omnibus_url].
75
+ must_equal "https://www.chef.io/chef/install.sh"
76
+ end
77
+
78
+ end
79
+
80
+ it ":require_chef_omnibus defaults to true" do
81
+ provisioner[:require_chef_omnibus].must_equal true
82
+ end
83
+
84
+ it ":chef_omnibus_install_options defaults to nil" do
85
+ provisioner[:chef_omnibus_install_options].must_equal nil
86
+ end
87
+
88
+ it ":run_list defaults to an empty array" do
89
+ provisioner[:run_list].must_equal []
90
+ end
91
+
92
+ it ":attributes defaults to an empty hash" do
93
+ provisioner[:attributes].must_equal Hash.new
94
+ end
95
+
96
+ it ":log_file defaults to nil" do
97
+ provisioner[:log_file].must_equal nil
98
+ end
99
+
100
+ it ":cookbook_files_glob includes recipes" do
101
+ provisioner[:cookbook_files_glob].must_match %r{,recipes/}
102
+ end
103
+
104
+ it ":data_path uses calculate_path and is expanded" do
105
+ provisioner[:data_path].
106
+ must_equal os_safe_root_path("/rooty/<calculated>/data")
107
+ end
108
+
109
+ it ":data_bags_path uses calculate_path and is expanded" do
110
+ provisioner[:data_bags_path].
111
+ must_equal os_safe_root_path("/rooty/<calculated>/data_bags")
112
+ end
113
+
114
+ it ":environments_path uses calculate_path and is expanded" do
115
+ provisioner[:environments_path].
116
+ must_equal os_safe_root_path("/rooty/<calculated>/environments")
117
+ end
118
+
119
+ it ":nodes_path uses calculate_path and is expanded" do
120
+ provisioner[:nodes_path].
121
+ must_equal os_safe_root_path("/rooty/<calculated>/nodes")
122
+ end
123
+
124
+ it ":roles_path uses calculate_path and is expanded" do
125
+ provisioner[:roles_path].
126
+ must_equal os_safe_root_path("/rooty/<calculated>/roles")
127
+ end
128
+
129
+ it ":clients_path uses calculate_path and is expanded" do
130
+ provisioner[:clients_path].
131
+ must_equal os_safe_root_path("/rooty/<calculated>/clients")
132
+ end
133
+
134
+ it "...secret_key_path uses calculate_path and is expanded" do
135
+ provisioner[:encrypted_data_bag_secret_key_path].
136
+ must_equal os_safe_root_path("/rooty/<calculated>/encrypted_data_bag_secret_key")
137
+ end
138
+ end
139
+
140
+ describe "#install_command" do
141
+
142
+ before do
143
+ platform.stubs(:shell_type).returns("bourne")
144
+ Mixlib::Install::ScriptGenerator.stubs(:new).returns(installer)
145
+ end
146
+
147
+ let(:installer) { stub(:root => "/rooty", :install_command => "make_it_so") }
148
+
149
+ let(:cmd) { provisioner.install_command }
150
+
151
+ let(:install_opts) {
152
+ { :omnibus_url => "https://www.chef.io/chef/install.sh",
153
+ :project => nil, :install_flags => nil, :sudo_command => "sudo -E",
154
+ :http_proxy => nil, :https_proxy => nil }
155
+ }
156
+
157
+ it "returns nil if :require_chef_omnibus is falsey" do
158
+ config[:require_chef_omnibus] = false
159
+
160
+ installer.expects(:root).never
161
+ installer.expects(:install_command).never
162
+ cmd.must_equal nil
163
+ end
164
+
165
+ describe "common behaviour" do
166
+ before do
167
+ installer.expects(:root).at_least_once.returns("/opt/chef")
168
+ installer.expects(:install_command)
169
+ end
170
+
171
+ it "passes sensible defaults" do
172
+ Mixlib::Install::ScriptGenerator.expects(:new).
173
+ with(default_version, false, install_opts).returns(installer)
174
+ cmd
175
+ end
176
+
177
+ it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
178
+ config[:http_proxy] = "http://proxy"
179
+ install_opts[:http_proxy] = "http://proxy"
180
+
181
+ Mixlib::Install::ScriptGenerator.expects(:new).
182
+ with(default_version, false, install_opts).returns(installer)
183
+ cmd
184
+ end
185
+
186
+ it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
187
+ config[:https_proxy] = "https://proxy"
188
+ install_opts[:https_proxy] = "https://proxy"
189
+
190
+ Mixlib::Install::ScriptGenerator.expects(:new).
191
+ with(default_version, false, install_opts).returns(installer)
192
+ cmd
193
+ end
194
+
195
+ it "exports all http proxy variables when both are set" do
196
+ config[:http_proxy] = "http://proxy"
197
+ config[:https_proxy] = "https://proxy"
198
+ install_opts[:http_proxy] = "http://proxy"
199
+ install_opts[:https_proxy] = "https://proxy"
200
+
201
+ Mixlib::Install::ScriptGenerator.expects(:new).
202
+ with(default_version, false, install_opts).returns(installer)
203
+ cmd
204
+ end
205
+
206
+ it "installs chef using :chef_omnibus_url, if necessary" do
207
+ config[:chef_omnibus_url] = "FROM_HERE"
208
+ install_opts[:omnibus_url] = "FROM_HERE"
209
+
210
+ Mixlib::Install::ScriptGenerator.expects(:new).
211
+ with(default_version, false, install_opts).returns(installer)
212
+ cmd
213
+ end
214
+
215
+ it "will install a specific version of chef, if necessary" do
216
+ config[:require_chef_omnibus] = "1.2.3"
217
+
218
+ Mixlib::Install::ScriptGenerator.expects(:new).
219
+ with("1.2.3", false, install_opts).returns(installer)
220
+ cmd
221
+ end
222
+
223
+ it "will install a major/minor version of chef, if necessary" do
224
+ config[:require_chef_omnibus] = "11.10"
225
+
226
+ Mixlib::Install::ScriptGenerator.expects(:new).
227
+ with("11.10", false, install_opts).returns(installer)
228
+ cmd
229
+ end
230
+
231
+ it "will install a major version of chef, if necessary" do
232
+ config[:require_chef_omnibus] = "12"
233
+
234
+ Mixlib::Install::ScriptGenerator.expects(:new).
235
+ with("12", false, install_opts).returns(installer)
236
+ cmd
237
+ end
238
+
239
+ it "will install a nightly, if necessary" do
240
+ config[:require_chef_omnibus] =
241
+ "12.5.0-current.0+20150721082808.git.14.c91b337-1"
242
+
243
+ Mixlib::Install::ScriptGenerator.expects(:new).with(
244
+ "12.5.0-current.0+20150721082808.git.14.c91b337-1",
245
+ false,
246
+ install_opts
247
+ ).returns(installer)
248
+ cmd
249
+ end
250
+
251
+ it "will install the latest chef, if necessary" do
252
+ config[:require_chef_omnibus] = "latest"
253
+
254
+ Mixlib::Install::ScriptGenerator.expects(:new).
255
+ with("latest", false, install_opts).returns(installer)
256
+ cmd
257
+ end
258
+
259
+ it "will install a version of chef, unless it exists" do
260
+ config[:require_chef_omnibus] = true
261
+
262
+ Mixlib::Install::ScriptGenerator.expects(:new).
263
+ with(default_version, false, install_opts).returns(installer)
264
+ cmd
265
+ end
266
+
267
+ it "will pass a project, when given" do
268
+ config[:chef_omnibus_install_options] = "-P chefdk"
269
+ install_opts[:install_flags] = "-P chefdk"
270
+ install_opts[:project] = "chefdk"
271
+
272
+ Mixlib::Install::ScriptGenerator.expects(:new).
273
+ with(default_version, false, install_opts).returns(installer)
274
+ cmd
275
+ end
276
+
277
+ it "will pass install options and version info, when given" do
278
+ config[:require_chef_omnibus] = "11"
279
+ config[:chef_omnibus_install_options] = "-d /tmp/place"
280
+ install_opts[:install_flags] = "-d /tmp/place"
281
+
282
+ Mixlib::Install::ScriptGenerator.expects(:new).
283
+ with("11", false, install_opts).returns(installer)
284
+ cmd
285
+ end
286
+
287
+ it "will set the install root" do
288
+ config[:chef_omnibus_root] = "/tmp/test"
289
+ install_opts[:root] = "/tmp/test"
290
+
291
+ Mixlib::Install::ScriptGenerator.expects(:new).
292
+ with(default_version, false, install_opts).returns(installer)
293
+ cmd
294
+ end
295
+
296
+ it "will set the msi url" do
297
+ config[:install_msi_url] = "http://blah/blah.msi"
298
+ install_opts[:install_msi_url] = "http://blah/blah.msi"
299
+
300
+ Mixlib::Install::ScriptGenerator.expects(:new).
301
+ with(default_version, false, install_opts).returns(installer)
302
+ cmd
303
+ end
304
+
305
+ it "prefixs the whole command with the command_prefix if set" do
306
+ config[:command_prefix] = "my_prefix"
307
+
308
+ cmd.must_match(/\Amy_prefix /)
309
+ end
310
+
311
+ it "does not prefix the command if command_prefix is not set" do
312
+ config[:command_prefix] = nil
313
+
314
+ cmd.wont_match(/\Amy_prefix /)
315
+ end
316
+ end
317
+
318
+ describe "for product" do
319
+ before do
320
+ installer.expects(:root).at_least_once.returns("/opt/chef")
321
+ installer.expects(:install_command)
322
+ config[:product_name] = "my_product"
323
+ end
324
+
325
+ it "will set the product name, version and channel" do
326
+ config[:product_version] = "version"
327
+ config[:channel] = "channel"
328
+
329
+ Mixlib::Install.expects(:new).with do |opts|
330
+ opts[:product_name].must_equal "my_product"
331
+ opts[:product_version].must_equal "version"
332
+ opts[:channel].must_equal :channel
333
+ end.returns(installer)
334
+ cmd
335
+ end
336
+
337
+ it "will set the architecture if given" do
338
+ config[:architecture] = "architecture"
339
+
340
+ Mixlib::Install.expects(:new).with do |opts|
341
+ opts[:architecture].must_equal "architecture"
342
+ end.returns(installer)
343
+ cmd
344
+ end
345
+
346
+ it "will set the platform if given" do
347
+ config[:platform] = "platform"
348
+
349
+ Mixlib::Install.expects(:new).with do |opts|
350
+ opts[:platform].must_equal "platform"
351
+ end.returns(installer)
352
+ cmd
353
+ end
354
+
355
+ it "will set the platform_version if given" do
356
+ config[:platform_version] = "platform_version"
357
+
358
+ Mixlib::Install.expects(:new).with do |opts|
359
+ opts[:platform_version].must_equal "platform_version"
360
+ end.returns(installer)
361
+ cmd
362
+ end
363
+
364
+ it "will omit the architecture if not given" do
365
+ Mixlib::Install.expects(:new).with do |opts|
366
+ opts.key?(:architecture).must_equal false
367
+ end.returns(installer)
368
+ cmd
369
+ end
370
+
371
+ it "will omit the platform if not given" do
372
+ Mixlib::Install.expects(:new).with do |opts|
373
+ opts.key?(:platform).must_equal false
374
+ end.returns(installer)
375
+ cmd
376
+ end
377
+
378
+ it "will omit the platform_version if not given" do
379
+ Mixlib::Install.expects(:new).with do |opts|
380
+ opts.key?(:platform_version).must_equal false
381
+ end.returns(installer)
382
+ cmd
383
+ end
384
+
385
+ it "will use stable channel when none specified" do
386
+ Mixlib::Install.expects(:new).with do |opts|
387
+ opts[:channel].must_equal :stable
388
+ end.returns(installer)
389
+ cmd
390
+ end
391
+ end
392
+
393
+ describe "for bourne shells" do
394
+ before do
395
+ installer.expects(:root).at_least_once.returns("/opt/chef")
396
+ installer.expects(:install_command).returns("my_install_command")
397
+ end
398
+
399
+ it "prepends sudo for sh commands when :sudo is set" do
400
+ config[:sudo] = true
401
+ config[:sudo_command] = "my_sudo_command"
402
+ install_opts_clone = install_opts.clone
403
+ install_opts_clone[:sudo_command] = config[:sudo_command]
404
+
405
+ Mixlib::Install::ScriptGenerator.expects(:new).
406
+ with(default_version, false, install_opts_clone).returns(installer)
407
+ cmd.must_equal "my_sudo_command my_install_command"
408
+ end
409
+
410
+ it "does not pass shell type for product based command" do
411
+ config[:product_name] = "product_name"
412
+
413
+ Mixlib::Install.expects(:new).with do |opts|
414
+ opts.key?(:shell_type).must_equal false
415
+ end.returns(installer)
416
+ cmd
417
+ end
418
+
419
+ it "does not sudo for sh commands when :sudo is falsey" do
420
+ config[:sudo] = false
421
+
422
+ install_opts_clone = install_opts.clone
423
+ install_opts_clone[:sudo_command] = ""
424
+ Mixlib::Install::ScriptGenerator.expects(:new).
425
+ with(default_version, false, install_opts_clone).returns(installer)
426
+ cmd.must_equal "my_install_command"
427
+ end
428
+ end
429
+
430
+ describe "for powershell shells on windows os types" do
431
+ before do
432
+ installer.expects(:root).at_least_once.returns("/opt/chef")
433
+ installer.expects(:install_command)
434
+ platform.stubs(:shell_type).returns("powershell")
435
+ platform.stubs(:os_type).returns("windows")
436
+ end
437
+
438
+ it "sets the powershell flag for Mixlib::Install" do
439
+ install_opts_clone = install_opts.clone
440
+ install_opts_clone[:sudo_command] = ""
441
+ Mixlib::Install::ScriptGenerator.expects(:new).
442
+ with(default_version, true, install_opts_clone).returns(installer)
443
+ cmd
444
+ end
445
+
446
+ it "passes ps1 shell type for product based command" do
447
+ config[:product_name] = "product_name"
448
+
449
+ Mixlib::Install.expects(:new).with do |opts|
450
+ opts[:shell_type].must_equal :ps1
451
+ end.returns(installer)
452
+ cmd
453
+ end
454
+ end
455
+ end
456
+
457
+ describe "#init_command" do
458
+
459
+ let(:cmd) { provisioner.init_command }
460
+
461
+ describe "common behavior" do
462
+
463
+ before { platform.stubs(:shell_type).returns("fake") }
464
+
465
+ it "prefixs the whole command with the command_prefix if set" do
466
+ config[:command_prefix] = "my_prefix"
467
+
468
+ cmd.must_match(/\Amy_prefix /)
469
+ end
470
+
471
+ it "does not prefix the command if command_prefix is not set" do
472
+ config[:command_prefix] = nil
473
+
474
+ cmd.wont_match(/\Amy_prefix /)
475
+ end
476
+ end
477
+
478
+ describe "for bourne shells" do
479
+
480
+ before { platform.stubs(:shell_type).returns("bourne") }
481
+
482
+ it "uses bourne shell" do
483
+ cmd.must_match(/\Ash -c '$/)
484
+ cmd.must_match(/'\Z/)
485
+ end
486
+
487
+ it "ends with a single quote" do
488
+ cmd.must_match(/'\Z/)
489
+ end
490
+
491
+ it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
492
+ config[:http_proxy] = "http://proxy"
493
+
494
+ cmd.lines.to_a[1..2].must_equal([
495
+ %{http_proxy="http://proxy"; export http_proxy\n},
496
+ %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n}
497
+ ])
498
+ end
499
+
500
+ it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
501
+ config[:https_proxy] = "https://proxy"
502
+
503
+ cmd.lines.to_a[1..2].must_equal([
504
+ %{https_proxy="https://proxy"; export https_proxy\n},
505
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
506
+ ])
507
+ end
508
+
509
+ it "exports all http proxy variables when both are set" do
510
+ config[:http_proxy] = "http://proxy"
511
+ config[:https_proxy] = "https://proxy"
512
+
513
+ cmd.lines.to_a[1..4].must_equal([
514
+ %{http_proxy="http://proxy"; export http_proxy\n},
515
+ %{HTTP_PROXY="http://proxy"; export HTTP_PROXY\n},
516
+ %{https_proxy="https://proxy"; export https_proxy\n},
517
+ %{HTTPS_PROXY="https://proxy"; export HTTPS_PROXY\n}
518
+ ])
519
+ end
520
+
521
+ it "prepends sudo for rm when :sudo is set" do
522
+ config[:sudo] = true
523
+
524
+ cmd.must_match regexify(%{sudo_rm="sudo -E rm"})
525
+ end
526
+
527
+ it "does not sudo for sh commands when :sudo is falsey" do
528
+ config[:sudo] = false
529
+
530
+ cmd.must_match regexify(%{sudo_rm="rm"})
531
+ end
532
+
533
+ it "sets chef component dirs for deletion" do
534
+ config[:root_path] = "/route"
535
+ dirs = %W[
536
+ /route/clients /route/cookbooks /route/data /route/data_bags
537
+ /route/encrypted_data_bag_secret /route/environments /route/roles
538
+ ].join(" ")
539
+
540
+ cmd.must_match regexify(%{dirs="#{dirs}"})
541
+ end
542
+
543
+ it "sets the root_path from :root_path" do
544
+ config[:root_path] = "RIGHT_HERE"
545
+
546
+ cmd.must_match regexify(%{root_path="RIGHT_HERE"})
547
+ end
548
+ end
549
+
550
+ describe "for powershell shells on windows os types" do
551
+
552
+ before do
553
+ platform.stubs(:shell_type).returns("powershell")
554
+ platform.stubs(:os_type).returns("windows")
555
+ end
556
+
557
+ it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
558
+ config[:http_proxy] = "http://proxy"
559
+
560
+ cmd.lines.to_a[0..1].must_equal([
561
+ %{$env:http_proxy = "http://proxy"\n},
562
+ %{$env:HTTP_PROXY = "http://proxy"\n}
563
+ ])
564
+ end
565
+
566
+ it "exports https_proxy & HTTPS_PROXY when :https_proxy is set" do
567
+ config[:https_proxy] = "https://proxy"
568
+
569
+ cmd.lines.to_a[0..1].must_equal([
570
+ %{$env:https_proxy = "https://proxy"\n},
571
+ %{$env:HTTPS_PROXY = "https://proxy"\n}
572
+ ])
573
+ end
574
+
575
+ it "exports all http proxy variables when both are set" do
576
+ config[:http_proxy] = "http://proxy"
577
+ config[:https_proxy] = "https://proxy"
578
+
579
+ cmd.lines.to_a[0..3].must_equal([
580
+ %{$env:http_proxy = "http://proxy"\n},
581
+ %{$env:HTTP_PROXY = "http://proxy"\n},
582
+ %{$env:https_proxy = "https://proxy"\n},
583
+ %{$env:HTTPS_PROXY = "https://proxy"\n}
584
+ ])
585
+ end
586
+
587
+ it "sets chef component dirs for deletion" do
588
+ config[:root_path] = "\\route"
589
+ dirs = %W[
590
+ "\\route\\clients" "\\route\\cookbooks" "\\route\\data"
591
+ "\\route\\data_bags" "\\route\\encrypted_data_bag_secret"
592
+ "\\route\\environments" "\\route\\roles"
593
+ ].join(", ")
594
+
595
+ cmd.must_match regexify(%{$dirs = @(#{dirs})})
596
+ end
597
+
598
+ it "sets the root_path from :root_path" do
599
+ config[:root_path] = "RIGHT_HERE"
600
+
601
+ cmd.must_match regexify(%{$root_path = "RIGHT_HERE"})
602
+ end
603
+ end
604
+ end
605
+
606
+ describe "#create_sandbox" do
607
+
608
+ before do
609
+ @root = Dir.mktmpdir
610
+ config[:kitchen_root] = @root
611
+ end
612
+
613
+ after do
614
+ FileUtils.remove_entry(@root)
615
+ begin
616
+ provisioner.cleanup_sandbox
617
+ rescue # rubocop:disable Lint/HandleExceptions
618
+ end
619
+ end
620
+
621
+ let(:provisioner) do
622
+ Class.new(Kitchen::Provisioner::ChefBase) {
623
+ default_config :generic_rb, {}
624
+
625
+ def create_sandbox
626
+ super
627
+
628
+ data = default_config_rb.merge(config[:generic_rb])
629
+ File.open(File.join(sandbox_path, "generic.rb"), "wb") do |file|
630
+ file.write(format_config_file(data))
631
+ end
632
+ end
633
+ }.new(config).finalize_config!(instance)
634
+ end
635
+
636
+ describe "json file" do
637
+
638
+ let(:json) { JSON.parse(IO.read(sandbox_path("dna.json"))) }
639
+
640
+ it "creates a json file with node attributes" do
641
+ config[:attributes] = { "one" => { "two" => "three" } }
642
+ provisioner.create_sandbox
643
+
644
+ json["one"].must_equal("two" => "three")
645
+ end
646
+
647
+ it "creates a json file with run_list" do
648
+ config[:run_list] = %w[alpha bravo charlie]
649
+ provisioner.create_sandbox
650
+
651
+ json["run_list"].must_equal %w[alpha bravo charlie]
652
+ end
653
+
654
+ it "creates a json file with an empty run_list" do
655
+ config[:run_list] = []
656
+ provisioner.create_sandbox
657
+
658
+ json["run_list"].must_equal []
659
+ end
660
+
661
+ it "logs a message on info" do
662
+ provisioner.create_sandbox
663
+
664
+ logged_output.string.must_match info_line("Preparing dna.json")
665
+ end
666
+
667
+ it "logs a message on debug" do
668
+ config[:run_list] = ["yo"]
669
+ provisioner.create_sandbox
670
+
671
+ logged_output.string.
672
+ must_match debug_line(%|Creating dna.json from {:run_list=>["yo"]}|)
673
+ end
674
+ end
675
+
676
+ it "creates a cache directory" do
677
+ provisioner.create_sandbox
678
+
679
+ sandbox_path("cache").directory?.must_equal true
680
+ end
681
+
682
+ %w[data data_bags environments nodes roles clients].each do |thing|
683
+ describe "#{thing} files" do
684
+
685
+ before do
686
+ create_files_under("#{config[:kitchen_root]}/my_#{thing}")
687
+ config[:"#{thing}_path"] = "#{config[:kitchen_root]}/my_#{thing}"
688
+ end
689
+
690
+ it "skips directory creation if :#{thing}_path is not set" do
691
+ config[:"#{thing}_path"] = nil
692
+ provisioner.create_sandbox
693
+
694
+ sandbox_path(thing).directory?.must_equal false
695
+ end
696
+
697
+ it "copies tree from :#{thing}_path into sandbox" do
698
+ provisioner.create_sandbox
699
+
700
+ sandbox_path("#{thing}/alpha.txt").file?.must_equal true
701
+ IO.read(sandbox_path("#{thing}/alpha.txt")).must_equal "stuff"
702
+ sandbox_path("#{thing}/sub").directory?.must_equal true
703
+ sandbox_path("#{thing}/sub/bravo.txt").file?.must_equal true
704
+ IO.read(sandbox_path("#{thing}/sub/bravo.txt")).must_equal "junk"
705
+ end
706
+
707
+ it "logs a message on info" do
708
+ provisioner.create_sandbox
709
+
710
+ logged_output.string.must_match info_line("Preparing #{thing}")
711
+ end
712
+
713
+ it "logs a message on debug" do
714
+ provisioner.create_sandbox
715
+
716
+ logged_output.string.must_match debug_line(
717
+ "Using #{thing} from #{config[:kitchen_root]}/my_#{thing}")
718
+ end
719
+ end
720
+ end
721
+
722
+ describe "secret files" do
723
+
724
+ before do
725
+ config[:encrypted_data_bag_secret_key_path] =
726
+ "#{config[:kitchen_root]}/my_secret"
727
+ File.open("#{config[:kitchen_root]}/my_secret", "wb") do |file|
728
+ file.write("p@ss")
729
+ end
730
+ end
731
+
732
+ it "skips file if :encrypted_data_bag_secret_key_path is not set" do
733
+ config[:encrypted_data_bag_secret_key_path] = nil
734
+ provisioner.create_sandbox
735
+
736
+ sandbox_path("encrypted_data_bag_secret").file?.must_equal false
737
+ end
738
+
739
+ it "copies file from :encrypted_data_bag_secret_key_path into sandbox" do
740
+ provisioner.create_sandbox
741
+
742
+ sandbox_path("encrypted_data_bag_secret").file?.must_equal true
743
+ IO.read(sandbox_path("encrypted_data_bag_secret")).must_equal "p@ss"
744
+ end
745
+
746
+ it "logs a message on info" do
747
+ provisioner.create_sandbox
748
+
749
+ logged_output.string.must_match info_line("Preparing secret")
750
+ end
751
+
752
+ it "logs a message on debug" do
753
+ provisioner.create_sandbox
754
+
755
+ logged_output.string.must_match debug_line(
756
+ "Using secret from #{config[:kitchen_root]}/my_secret")
757
+ end
758
+ end
759
+
760
+ describe "cookbooks" do
761
+
762
+ let(:kitchen_root) { config[:kitchen_root] }
763
+
764
+ describe "with a cookbooks/ directory under kitchen_root" do
765
+
766
+ it "copies cookbooks/" do
767
+ create_cookbook("#{kitchen_root}/cookbooks/epache")
768
+ create_cookbook("#{kitchen_root}/cookbooks/jahva")
769
+ provisioner.create_sandbox
770
+
771
+ sandbox_path("cookbooks/epache").directory?.must_equal true
772
+ sandbox_path("cookbooks/epache/recipes/default.rb").
773
+ file?.must_equal true
774
+ sandbox_path("cookbooks/jahva").directory?.must_equal true
775
+ sandbox_path("cookbooks/jahva/recipes/default.rb").
776
+ file?.must_equal true
777
+ end
778
+
779
+ it "copies from kitchen_root as cookbook if it contains metadata.rb" do
780
+ File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
781
+ file.write("name 'wat'")
782
+ end
783
+ create_cookbook("#{kitchen_root}/cookbooks/bk")
784
+ provisioner.create_sandbox
785
+
786
+ sandbox_path("cookbooks/bk").directory?.must_equal true
787
+ sandbox_path("cookbooks/wat").directory?.must_equal true
788
+ sandbox_path("cookbooks/wat/metadata.rb").file?.must_equal true
789
+ end
790
+
791
+ it "copies site-cookbooks/ if it exists" do
792
+ create_cookbook("#{kitchen_root}/cookbooks/upstream")
793
+ create_cookbook("#{kitchen_root}/site-cookbooks/mine")
794
+ provisioner.create_sandbox
795
+
796
+ sandbox_path("cookbooks/upstream").directory?.must_equal true
797
+ sandbox_path("cookbooks/mine").directory?.must_equal true
798
+ sandbox_path("cookbooks/mine/attributes/all.rb").file?.must_equal true
799
+ end
800
+
801
+ it "logs a message on info for cookbooks/ directory" do
802
+ create_cookbook("#{kitchen_root}/cookbooks/epache")
803
+ provisioner.create_sandbox
804
+
805
+ logged_output.string.must_match info_line(
806
+ "Preparing cookbooks from project directory")
807
+ end
808
+
809
+ it "logs a meesage on debug for cookbooks/ directory" do
810
+ create_cookbook("#{kitchen_root}/cookbooks/epache")
811
+ provisioner.create_sandbox
812
+
813
+ logged_output.string.must_match debug_line(
814
+ "Using cookbooks from #{kitchen_root}/cookbooks")
815
+ end
816
+
817
+ it "logs a message on info for site-cookbooks/ directory" do
818
+ create_cookbook("#{kitchen_root}/cookbooks/epache")
819
+ create_cookbook("#{kitchen_root}/site-cookbooks/mine")
820
+ provisioner.create_sandbox
821
+
822
+ logged_output.string.must_match info_line(
823
+ "Preparing site-cookbooks from project directory")
824
+ end
825
+
826
+ it "logs a meesage on debug for site-cookbooks/ directory" do
827
+ create_cookbook("#{kitchen_root}/cookbooks/epache")
828
+ create_cookbook("#{kitchen_root}/site-cookbooks/mine")
829
+ provisioner.create_sandbox
830
+
831
+ logged_output.string.must_match debug_line(
832
+ "Using cookbooks from #{kitchen_root}/site-cookbooks")
833
+ end
834
+ end
835
+
836
+ describe "with a cookbook as the project" do
837
+
838
+ before do
839
+ File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
840
+ file.write("name 'wat'")
841
+ end
842
+ end
843
+
844
+ it "copies from kitchen_root as cookbook if it contains metadata.rb" do
845
+ provisioner.create_sandbox
846
+
847
+ sandbox_path("cookbooks/wat").directory?.must_equal true
848
+ sandbox_path("cookbooks/wat/metadata.rb").file?.must_equal true
849
+ end
850
+
851
+ it "logs a message on info" do
852
+ provisioner.create_sandbox
853
+
854
+ logged_output.string.must_match info_line(
855
+ "Preparing current project directory as a cookbook")
856
+ end
857
+
858
+ it "logs a meesage on debug" do
859
+ provisioner.create_sandbox
860
+
861
+ logged_output.string.must_match debug_line(
862
+ "Using metadata.rb from #{kitchen_root}/metadata.rb")
863
+ end
864
+
865
+ it "raises a UserError is name cannot be determined from metadata.rb" do
866
+ File.open("#{kitchen_root}/metadata.rb", "wb") do |file|
867
+ file.write("nameeeeee 'wat'")
868
+ end
869
+
870
+ proc { provisioner.create_sandbox }.must_raise Kitchen::UserError
871
+ end
872
+ end
873
+
874
+ describe "with no referenced cookbooks" do
875
+
876
+ it "makes a fake cookbook" do
877
+ name = File.basename(@root)
878
+ provisioner.create_sandbox
879
+
880
+ sandbox_path("cookbooks/#{name}").directory?.must_equal true
881
+ sandbox_path("cookbooks/#{name}/metadata.rb").file?.must_equal true
882
+ IO.read(sandbox_path("cookbooks/#{name}/metadata.rb")).
883
+ must_equal %{name "#{name}"\n}
884
+ end
885
+
886
+ it "logs a warning" do
887
+ provisioner.create_sandbox
888
+
889
+ logged_output.string.must_match regexify(
890
+ "Berksfile, Cheffile, cookbooks/, or metadata.rb not found",
891
+ :partial_line
892
+ )
893
+ end
894
+ end
895
+
896
+ describe "with a Berksfile under kitchen_root" do
897
+
898
+ let(:resolver) { stub(:resolve => true) }
899
+
900
+ before do
901
+ File.open("#{kitchen_root}/Berksfile", "wb") do |file|
902
+ file.write("cookbook 'wat'")
903
+ end
904
+ Kitchen::Provisioner::Chef::Berkshelf.stubs(:new).returns(resolver)
905
+ end
906
+
907
+ it "raises a UserError if Berkshelf library can't be loaded" do
908
+ proc { provisioner }.must_raise Kitchen::UserError
909
+ end
910
+
911
+ it "logs on debug that Berkshelf is loading" do
912
+ Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
913
+ provisioner
914
+
915
+ logged_output.string.must_match debug_line(
916
+ "Berksfile found at #{kitchen_root}/Berksfile, loading Berkshelf")
917
+ end
918
+
919
+ it "uses Berkshelf" do
920
+ Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
921
+ resolver.expects(:resolve)
922
+
923
+ provisioner.create_sandbox
924
+ end
925
+
926
+ it "uses Kitchen.mutex for resolving" do
927
+ Kitchen::Provisioner::Chef::Berkshelf.stubs(:load!)
928
+ Kitchen.mutex.expects(:synchronize)
929
+
930
+ provisioner.create_sandbox
931
+ end
932
+ end
933
+
934
+ describe "with a Cheffile under kitchen_root" do
935
+
936
+ let(:resolver) { stub(:resolve => true) }
937
+
938
+ before do
939
+ File.open("#{kitchen_root}/Cheffile", "wb") do |file|
940
+ file.write("cookbook 'wat'")
941
+ end
942
+ Kitchen::Provisioner::Chef::Librarian.stubs(:new).returns(resolver)
943
+ end
944
+
945
+ it "raises a UserError if Librarian library can't be loaded" do
946
+ proc { provisioner }.must_raise Kitchen::UserError
947
+ end
948
+
949
+ it "logs on debug that Berkshelf is loading" do
950
+ Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
951
+ provisioner
952
+
953
+ logged_output.string.must_match debug_line(
954
+ "Cheffile found at #{kitchen_root}/Cheffile, loading Librarian-Chef"
955
+ )
956
+ end
957
+
958
+ it "uses Librarian" do
959
+ Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
960
+ resolver.expects(:resolve)
961
+
962
+ provisioner.create_sandbox
963
+ end
964
+
965
+ it "uses Kitchen.mutex for resolving" do
966
+ Kitchen::Provisioner::Chef::Librarian.stubs(:load!)
967
+ Kitchen.mutex.expects(:synchronize)
968
+
969
+ provisioner.create_sandbox
970
+ end
971
+ end
972
+
973
+ describe "filtering cookbooks files" do
974
+
975
+ it "retains all useful cookbook files" do
976
+ create_full_cookbook("#{kitchen_root}/cookbooks/full")
977
+ provisioner.create_sandbox
978
+
979
+ full_cookbook_files.each do |file|
980
+ sandbox_path("cookbooks/full/#{file}").file?.must_equal true
981
+ end
982
+ end
983
+
984
+ it "strips extra cookbook files" do
985
+ extras = %w[
986
+ .gitignore tmp/librarian chefignore .git/info/excludes
987
+ cookbooks/another/metadata.rb CONTRIBUTING.md metadata.py
988
+ ]
989
+
990
+ create_full_cookbook("#{kitchen_root}/cookbooks/full")
991
+ extras.each do |file|
992
+ create_file("#{kitchen_root}/cookbooks/full/#{file}")
993
+ end
994
+ provisioner.create_sandbox
995
+
996
+ extras.each do |file|
997
+ sandbox_path("cookbooks/full/#{file}").file?.must_equal false
998
+ end
999
+ end
1000
+
1001
+ it "logs on info" do
1002
+ create_full_cookbook("#{kitchen_root}/cookbooks/full")
1003
+ provisioner.create_sandbox
1004
+
1005
+ logged_output.string.must_match info_line(
1006
+ "Removing non-cookbook files before transfer")
1007
+ end
1008
+ end
1009
+
1010
+ describe "Chef config files" do
1011
+
1012
+ let(:file) do
1013
+ IO.read(sandbox_path("generic.rb")).lines.map(&:chomp)
1014
+ end
1015
+
1016
+ it "#create_sanbox creates a generic.rb" do
1017
+ provisioner.create_sandbox
1018
+
1019
+ sandbox_path("generic.rb").file?.must_equal true
1020
+ end
1021
+
1022
+ describe "defaults" do
1023
+
1024
+ before { provisioner.create_sandbox }
1025
+
1026
+ it "sets node_name to the instance name" do
1027
+ file.must_include %{node_name "#{instance.name}"}
1028
+ end
1029
+
1030
+ it "sets checksum_path" do
1031
+ file.must_include %{checksum_path "/tmp/kitchen/checksums"}
1032
+ end
1033
+
1034
+ it "sets file_backup_path" do
1035
+ file.must_include %{file_backup_path "/tmp/kitchen/backup"}
1036
+ end
1037
+
1038
+ it "sets cookbook_path" do
1039
+ file.must_include %{cookbook_path } +
1040
+ %{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
1041
+ end
1042
+
1043
+ it "sets data_bag_path" do
1044
+ file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
1045
+ end
1046
+
1047
+ it "sets environment_path" do
1048
+ file.must_include %{environment_path "/tmp/kitchen/environments"}
1049
+ end
1050
+
1051
+ it "sets node_path" do
1052
+ file.must_include %{node_path "/tmp/kitchen/nodes"}
1053
+ end
1054
+
1055
+ it "sets role_path" do
1056
+ file.must_include %{role_path "/tmp/kitchen/roles"}
1057
+ end
1058
+
1059
+ it "sets client_path" do
1060
+ file.must_include %{client_path "/tmp/kitchen/clients"}
1061
+ end
1062
+
1063
+ it "sets user_path" do
1064
+ file.must_include %{user_path "/tmp/kitchen/users"}
1065
+ end
1066
+
1067
+ it "sets validation_key" do
1068
+ file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
1069
+ end
1070
+
1071
+ it "sets client_key" do
1072
+ file.must_include %{client_key "/tmp/kitchen/client.pem"}
1073
+ end
1074
+
1075
+ it "sets chef_server_url" do
1076
+ file.must_include %{chef_server_url "http://127.0.0.1:8889"}
1077
+ end
1078
+
1079
+ it "sets encrypted_data_bag_secret" do
1080
+ file.must_include %{encrypted_data_bag_secret } +
1081
+ %{"/tmp/kitchen/encrypted_data_bag_secret"}
1082
+ end
1083
+ end
1084
+
1085
+ it "supports overwriting defaults" do
1086
+ config[:generic_rb] = {
1087
+ :node_name => "eagles",
1088
+ :user_path => "/a/b/c/u",
1089
+ :chef_server_url => "https://whereever.io"
1090
+ }
1091
+ provisioner.create_sandbox
1092
+
1093
+ file.must_include %{node_name "eagles"}
1094
+ file.must_include %{user_path "/a/b/c/u"}
1095
+ file.must_include %{chef_server_url "https://whereever.io"}
1096
+ end
1097
+
1098
+ it " supports adding new configuration" do
1099
+ config[:generic_rb] = {
1100
+ :dark_secret => "golang"
1101
+ }
1102
+ provisioner.create_sandbox
1103
+
1104
+ file.must_include %{dark_secret "golang"}
1105
+ end
1106
+ end
1107
+
1108
+ def create_cookbook(path)
1109
+ %w[metadata.rb attributes/all.rb recipes/default.rb].each do |file|
1110
+ create_file(File.join(path, file))
1111
+ end
1112
+ end
1113
+
1114
+ def full_cookbook_files
1115
+ %w[
1116
+ README.org metadata.rb attributes/all.rb definitions/def.rb
1117
+ files/default/config.conf libraries/one.rb libraries/two.rb
1118
+ providers/sweet.rb recipes/default.rb resources/sweet.rb
1119
+ templates/ubuntu/12.04/nginx.conf.erb
1120
+ ]
1121
+ end
1122
+
1123
+ def create_full_cookbook(path)
1124
+ full_cookbook_files.each { |file| create_file(File.join(path, file)) }
1125
+ end
1126
+
1127
+ def create_file(path)
1128
+ FileUtils.mkdir_p(File.dirname(path))
1129
+ File.open(path, "wb") { |f| f.write(path) }
1130
+ end
1131
+ end
1132
+
1133
+ def sandbox_path(path)
1134
+ Pathname.new(provisioner.sandbox_path).join(path)
1135
+ end
1136
+
1137
+ def create_files_under(path)
1138
+ FileUtils.mkdir_p(File.join(path, "sub"))
1139
+ File.open(File.join(path, "alpha.txt"), "wb") do |file|
1140
+ file.write("stuff")
1141
+ end
1142
+ File.open(File.join(path, "sub", "bravo.txt"), "wb") do |file|
1143
+ file.write("junk")
1144
+ end
1145
+ end
1146
+
1147
+ def info_line(msg)
1148
+ %r{^I, .* : #{Regexp.escape(msg)}$}
1149
+ end
1150
+
1151
+ def debug_line(msg)
1152
+ %r{^D, .* : #{Regexp.escape(msg)}$}
1153
+ end
1154
+ end
1155
+
1156
+ def regexify(str, line = :whole_line)
1157
+ r = Regexp.escape(str)
1158
+ r = "^\s*#{r}$" if line == :whole_line
1159
+ Regexp.new(r)
1160
+ end
1161
+ end