test-kitchen 1.7.0 → 1.7.1.dev

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -8
  3. data/.gitattributes +3 -0
  4. data/.github/ISSUE_TEMPLATE.md +55 -55
  5. data/.gitignore +28 -28
  6. data/.kitchen.ci.yml +23 -23
  7. data/.kitchen.proxy.yml +27 -27
  8. data/.rubocop.yml +3 -3
  9. data/.travis.yml +70 -70
  10. data/.yardopts +3 -3
  11. data/Berksfile +3 -3
  12. data/CHANGELOG.md +1090 -1083
  13. data/CONTRIBUTING.md +14 -14
  14. data/Gemfile +19 -19
  15. data/Gemfile.proxy_tests +4 -4
  16. data/Guardfile +42 -42
  17. data/LICENSE +15 -15
  18. data/MAINTAINERS.md +23 -23
  19. data/README.md +135 -135
  20. data/Rakefile +61 -61
  21. data/appveyor.yml +44 -44
  22. data/features/kitchen_action_commands.feature +164 -164
  23. data/features/kitchen_command.feature +16 -16
  24. data/features/kitchen_console_command.feature +34 -34
  25. data/features/kitchen_defaults.feature +38 -38
  26. data/features/kitchen_diagnose_command.feature +96 -96
  27. data/features/kitchen_driver_create_command.feature +64 -64
  28. data/features/kitchen_driver_discover_command.feature +25 -25
  29. data/features/kitchen_help_command.feature +16 -16
  30. data/features/kitchen_init_command.feature +274 -274
  31. data/features/kitchen_list_command.feature +104 -104
  32. data/features/kitchen_login_command.feature +62 -62
  33. data/features/kitchen_sink_command.feature +30 -30
  34. data/features/kitchen_test_command.feature +88 -88
  35. data/features/step_definitions/gem_steps.rb +36 -36
  36. data/features/step_definitions/git_steps.rb +5 -5
  37. data/features/step_definitions/output_steps.rb +5 -5
  38. data/features/support/env.rb +75 -75
  39. data/lib/kitchen.rb +150 -150
  40. data/lib/kitchen/base64_stream.rb +55 -55
  41. data/lib/kitchen/cli.rb +419 -419
  42. data/lib/kitchen/collection.rb +55 -55
  43. data/lib/kitchen/color.rb +65 -65
  44. data/lib/kitchen/command.rb +185 -185
  45. data/lib/kitchen/command/action.rb +45 -45
  46. data/lib/kitchen/command/console.rb +58 -58
  47. data/lib/kitchen/command/diagnose.rb +92 -92
  48. data/lib/kitchen/command/driver_discover.rb +105 -105
  49. data/lib/kitchen/command/exec.rb +41 -41
  50. data/lib/kitchen/command/list.rb +119 -119
  51. data/lib/kitchen/command/login.rb +43 -43
  52. data/lib/kitchen/command/sink.rb +54 -54
  53. data/lib/kitchen/command/test.rb +51 -51
  54. data/lib/kitchen/config.rb +322 -322
  55. data/lib/kitchen/configurable.rb +529 -529
  56. data/lib/kitchen/data_munger.rb +959 -959
  57. data/lib/kitchen/diagnostic.rb +141 -141
  58. data/lib/kitchen/driver.rb +56 -56
  59. data/lib/kitchen/driver/base.rb +134 -134
  60. data/lib/kitchen/driver/dummy.rb +108 -108
  61. data/lib/kitchen/driver/proxy.rb +72 -72
  62. data/lib/kitchen/driver/ssh_base.rb +357 -357
  63. data/lib/kitchen/errors.rb +229 -229
  64. data/lib/kitchen/generator/driver_create.rb +177 -177
  65. data/lib/kitchen/generator/init.rb +296 -296
  66. data/lib/kitchen/instance.rb +662 -662
  67. data/lib/kitchen/lazy_hash.rb +142 -142
  68. data/lib/kitchen/loader/yaml.rb +349 -349
  69. data/lib/kitchen/logger.rb +423 -423
  70. data/lib/kitchen/logging.rb +56 -56
  71. data/lib/kitchen/login_command.rb +52 -52
  72. data/lib/kitchen/metadata_chopper.rb +52 -52
  73. data/lib/kitchen/platform.rb +67 -67
  74. data/lib/kitchen/provisioner.rb +54 -54
  75. data/lib/kitchen/provisioner/base.rb +236 -236
  76. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  77. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  78. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  79. data/lib/kitchen/provisioner/chef_apply.rb +124 -124
  80. data/lib/kitchen/provisioner/chef_base.rb +341 -341
  81. data/lib/kitchen/provisioner/chef_solo.rb +88 -88
  82. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  83. data/lib/kitchen/provisioner/dummy.rb +79 -79
  84. data/lib/kitchen/provisioner/shell.rb +138 -138
  85. data/lib/kitchen/rake_tasks.rb +63 -63
  86. data/lib/kitchen/shell_out.rb +93 -93
  87. data/lib/kitchen/ssh.rb +276 -276
  88. data/lib/kitchen/state_file.rb +120 -120
  89. data/lib/kitchen/suite.rb +51 -51
  90. data/lib/kitchen/thor_tasks.rb +66 -66
  91. data/lib/kitchen/transport.rb +54 -54
  92. data/lib/kitchen/transport/base.rb +176 -176
  93. data/lib/kitchen/transport/dummy.rb +79 -79
  94. data/lib/kitchen/transport/ssh.rb +364 -364
  95. data/lib/kitchen/transport/winrm.rb +486 -486
  96. data/lib/kitchen/util.rb +147 -147
  97. data/lib/kitchen/verifier.rb +55 -55
  98. data/lib/kitchen/verifier/base.rb +235 -235
  99. data/lib/kitchen/verifier/busser.rb +277 -277
  100. data/lib/kitchen/verifier/dummy.rb +79 -79
  101. data/lib/kitchen/verifier/shell.rb +101 -101
  102. data/lib/kitchen/version.rb +21 -21
  103. data/lib/vendor/hash_recursive_merge.rb +82 -82
  104. data/spec/kitchen/base64_stream_spec.rb +77 -77
  105. data/spec/kitchen/cli_spec.rb +56 -56
  106. data/spec/kitchen/collection_spec.rb +80 -80
  107. data/spec/kitchen/color_spec.rb +54 -54
  108. data/spec/kitchen/config_spec.rb +408 -408
  109. data/spec/kitchen/configurable_spec.rb +1095 -1095
  110. data/spec/kitchen/data_munger_spec.rb +2694 -2694
  111. data/spec/kitchen/diagnostic_spec.rb +129 -129
  112. data/spec/kitchen/driver/base_spec.rb +121 -121
  113. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  114. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  115. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  116. data/spec/kitchen/driver_spec.rb +112 -112
  117. data/spec/kitchen/errors_spec.rb +309 -309
  118. data/spec/kitchen/instance_spec.rb +1419 -1419
  119. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  120. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  121. data/spec/kitchen/logger_spec.rb +429 -429
  122. data/spec/kitchen/logging_spec.rb +59 -59
  123. data/spec/kitchen/login_command_spec.rb +68 -68
  124. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  125. data/spec/kitchen/platform_spec.rb +89 -89
  126. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  127. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  128. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1161
  129. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  130. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  131. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  132. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  133. data/spec/kitchen/provisioner_spec.rb +107 -107
  134. data/spec/kitchen/shell_out_spec.rb +150 -150
  135. data/spec/kitchen/ssh_spec.rb +693 -693
  136. data/spec/kitchen/state_file_spec.rb +129 -129
  137. data/spec/kitchen/suite_spec.rb +62 -62
  138. data/spec/kitchen/transport/base_spec.rb +89 -89
  139. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  140. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  141. data/spec/kitchen/transport_spec.rb +112 -112
  142. data/spec/kitchen/util_spec.rb +165 -165
  143. data/spec/kitchen/verifier/base_spec.rb +362 -362
  144. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  145. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  146. data/spec/kitchen/verifier/shell_spec.rb +160 -160
  147. data/spec/kitchen/verifier_spec.rb +120 -120
  148. data/spec/kitchen_spec.rb +114 -114
  149. data/spec/spec_helper.rb +85 -85
  150. data/spec/support/powershell_max_size_spec.rb +40 -40
  151. data/support/busser_install_command.ps1 +14 -14
  152. data/support/busser_install_command.sh +14 -14
  153. data/support/chef-client-zero.rb +77 -77
  154. data/support/chef_base_init_command.ps1 +18 -18
  155. data/support/chef_base_init_command.sh +2 -2
  156. data/support/chef_base_install_command.ps1 +85 -85
  157. data/support/chef_base_install_command.sh +229 -229
  158. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  159. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  160. data/support/download_helpers.sh +109 -109
  161. data/support/dummy-validation.pem +27 -27
  162. data/templates/driver/CHANGELOG.md.erb +3 -3
  163. data/templates/driver/Gemfile.erb +3 -3
  164. data/templates/driver/README.md.erb +64 -64
  165. data/templates/driver/Rakefile.erb +21 -21
  166. data/templates/driver/driver.rb.erb +23 -23
  167. data/templates/driver/gemspec.erb +29 -29
  168. data/templates/driver/gitignore.erb +17 -17
  169. data/templates/driver/license_apachev2.erb +15 -15
  170. data/templates/driver/license_lgplv3.erb +16 -16
  171. data/templates/driver/license_mit.erb +22 -22
  172. data/templates/driver/license_reserved.erb +5 -5
  173. data/templates/driver/tailor.erb +4 -4
  174. data/templates/driver/travis.yml.erb +11 -11
  175. data/templates/driver/version.rb.erb +12 -12
  176. data/templates/init/chefignore.erb +1 -1
  177. data/templates/init/kitchen.yml.erb +18 -18
  178. data/test-kitchen.gemspec +62 -62
  179. data/test/integration/default/default_spec.rb +3 -3
  180. data/testing_windows.md +37 -37
  181. metadata +5 -4
@@ -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" }
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,1161 +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::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
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