test-kitchen 1.7.0 → 1.7.1.dev

Sign up to get free protection for your applications and to get access to all the features.
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