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,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