test-kitchen 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
@@ -1,294 +1,341 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, 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 "fileutils"
20
- require "pathname"
21
- require "json"
22
- require "cgi"
23
-
24
- require "kitchen/provisioner/chef/berkshelf"
25
- require "kitchen/provisioner/chef/common_sandbox"
26
- require "kitchen/provisioner/chef/librarian"
27
- require "kitchen/util"
28
- require "mixlib/install"
29
- begin
30
- require "chef-config/config"
31
- require "chef-config/workstation_config_loader"
32
- rescue LoadError # rubocop:disable Lint/HandleExceptions
33
- # This space left intentionally blank.
34
- end
35
-
36
- module Kitchen
37
-
38
- module Provisioner
39
-
40
- # Common implementation details for Chef-related provisioners.
41
- #
42
- # @author Fletcher Nichol <fnichol@nichol.ca>
43
- class ChefBase < Base
44
-
45
- default_config :require_chef_omnibus, true
46
- default_config :chef_omnibus_url, "https://www.chef.io/chef/install.sh"
47
- default_config :chef_omnibus_install_options, nil
48
- default_config :run_list, []
49
- default_config :attributes, {}
50
- default_config :config_path, nil
51
- default_config :log_file, nil
52
- default_config :profile_ruby, false
53
- default_config :cookbook_files_glob, %w[
54
- README.* metadata.{json,rb}
55
- attributes/**/* definitions/**/* files/**/* libraries/**/*
56
- providers/**/* recipes/**/* resources/**/* templates/**/*
57
- ].join(",")
58
-
59
- default_config :data_path do |provisioner|
60
- provisioner.calculate_path("data")
61
- end
62
- expand_path_for :data_path
63
-
64
- default_config :data_bags_path do |provisioner|
65
- provisioner.calculate_path("data_bags")
66
- end
67
- expand_path_for :data_bags_path
68
-
69
- default_config :environments_path do |provisioner|
70
- provisioner.calculate_path("environments")
71
- end
72
- expand_path_for :environments_path
73
-
74
- default_config :nodes_path do |provisioner|
75
- provisioner.calculate_path("nodes")
76
- end
77
- expand_path_for :nodes_path
78
-
79
- default_config :roles_path do |provisioner|
80
- provisioner.calculate_path("roles")
81
- end
82
- expand_path_for :roles_path
83
-
84
- default_config :clients_path do |provisioner|
85
- provisioner.calculate_path("clients")
86
- end
87
- expand_path_for :clients_path
88
-
89
- default_config :encrypted_data_bag_secret_key_path do |provisioner|
90
- provisioner.calculate_path("encrypted_data_bag_secret_key", :type => :file)
91
- end
92
- expand_path_for :encrypted_data_bag_secret_key_path
93
-
94
- # Reads the local Chef::Config object (if present). We do this because
95
- # we want to start bring Chef config and ChefDK tool config closer
96
- # together. For example, we want to configure proxy settings in 1
97
- # location instead of 3 configuration files.
98
- #
99
- # @param config [Hash] initial provided configuration
100
- def initialize(config = {})
101
- super(config)
102
-
103
- if defined?(ChefConfig::WorkstationConfigLoader)
104
- ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
105
- end
106
- # This exports any proxy config present in the Chef config to
107
- # appropriate environment variables, which Test Kitchen respects
108
- ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
109
- end
110
-
111
- # (see Base#create_sandbox)
112
- def create_sandbox
113
- super
114
- Chef::CommonSandbox.new(config, sandbox_path, instance).populate
115
- end
116
-
117
- # (see Base#init_command)
118
- def init_command
119
- dirs = %w[
120
- cookbooks data data_bags environments roles clients
121
- encrypted_data_bag_secret
122
- ].sort.map { |dir| remote_path_join(config[:root_path], dir) }
123
-
124
- vars = if powershell_shell?
125
- init_command_vars_for_powershell(dirs)
126
- else
127
- init_command_vars_for_bourne(dirs)
128
- end
129
-
130
- prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
131
- end
132
-
133
- # (see Base#install_command)
134
- def install_command
135
- return unless config[:require_chef_omnibus]
136
-
137
- version = config[:require_chef_omnibus].to_s.downcase
138
-
139
- # Passing "true" to mixlib-install currently breaks the windows metadata_url
140
- # TODO: remove this line once https://github.com/chef/mixlib-install/pull/22
141
- # is accepted and released
142
- version = "" if version == "true" && powershell_shell?
143
-
144
- installer = Mixlib::Install.new(version, powershell_shell?, install_options)
145
- config[:chef_omnibus_root] = installer.root
146
- prefix_command(sudo(installer.install_command))
147
- end
148
-
149
- private
150
-
151
- # @return [Hash] an option hash for the install commands
152
- # @api private
153
- def install_options
154
- project = /\s*-P (\w+)\s*/.match(config[:chef_omnibus_install_options])
155
- {
156
- :omnibus_url => config[:chef_omnibus_url],
157
- :project => project.nil? ? nil : project[1],
158
- :install_flags => config[:chef_omnibus_install_options],
159
- :sudo_command => sudo_command
160
- }.tap do |opts|
161
- opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
162
- opts[:http_proxy] = config[:http_proxy] if config.key? :http_proxy
163
- opts[:https_proxy] = config[:https_proxy] if config.key? :https_proxy
164
- end
165
- end
166
-
167
- # @return [String] an absolute path to a Berksfile, relative to the
168
- # kitchen root
169
- # @api private
170
- def berksfile
171
- File.join(config[:kitchen_root], "Berksfile")
172
- end
173
-
174
- # @return [String] an absolute path to a Cheffile, relative to the
175
- # kitchen root
176
- # @api private
177
- def cheffile
178
- File.join(config[:kitchen_root], "Cheffile")
179
- end
180
-
181
- # Generates a Hash with default values for a solo.rb or client.rb Chef
182
- # configuration file.
183
- #
184
- # @return [Hash] a configuration hash
185
- # @api private
186
- def default_config_rb # rubocop:disable Metrics/MethodLength
187
- root = config[:root_path].gsub("$env:TEMP", "\#{ENV['TEMP']\}")
188
-
189
- {
190
- :node_name => instance.name,
191
- :checksum_path => remote_path_join(root, "checksums"),
192
- :file_cache_path => remote_path_join(root, "cache"),
193
- :file_backup_path => remote_path_join(root, "backup"),
194
- :cookbook_path => [
195
- remote_path_join(root, "cookbooks"),
196
- remote_path_join(root, "site-cookbooks")
197
- ],
198
- :data_bag_path => remote_path_join(root, "data_bags"),
199
- :environment_path => remote_path_join(root, "environments"),
200
- :node_path => remote_path_join(root, "nodes"),
201
- :role_path => remote_path_join(root, "roles"),
202
- :client_path => remote_path_join(root, "clients"),
203
- :user_path => remote_path_join(root, "users"),
204
- :validation_key => remote_path_join(root, "validation.pem"),
205
- :client_key => remote_path_join(root, "client.pem"),
206
- :chef_server_url => "http://127.0.0.1:8889",
207
- :encrypted_data_bag_secret => remote_path_join(
208
- root, "encrypted_data_bag_secret"
209
- )
210
- }
211
- end
212
-
213
- # Generates a rendered client.rb/solo.rb/knife.rb formatted file as a
214
- # String.
215
- #
216
- # @param data [Hash] a key/value pair hash of configuration
217
- # @return [String] a rendered Chef config file as a String
218
- # @api private
219
- def format_config_file(data)
220
- data.each.map { |attr, value|
221
- [attr, format_value(value)].join(" ")
222
- }.join("\n")
223
- end
224
-
225
- # Converts a Ruby object to a String interpretation suitable for writing
226
- # out to a client.rb/solo.rb/knife.rb file.
227
- #
228
- # @param obj [Object] an object
229
- # @return [String] a string representation
230
- # @api private
231
- def format_value(obj)
232
- if obj.is_a?(String) && obj =~ /^:/
233
- obj
234
- elsif obj.is_a?(String)
235
- %{"#{obj.gsub(/\\/, "\\\\\\\\")}"}
236
- elsif obj.is_a?(Array)
237
- %{[#{obj.map { |i| format_value(i) }.join(", ")}]}
238
- else
239
- obj.inspect
240
- end
241
- end
242
-
243
- # Generates the init command variables for Bourne shell-based platforms.
244
- #
245
- # @param dirs [Array<String>] directories
246
- # @return [String] shell variable lines
247
- # @api private
248
- def init_command_vars_for_bourne(dirs)
249
- [
250
- shell_var("sudo_rm", sudo("rm")),
251
- shell_var("dirs", dirs.join(" ")),
252
- shell_var("root_path", config[:root_path])
253
- ].join("\n")
254
- end
255
-
256
- # Generates the init command variables for PowerShell-based platforms.
257
- #
258
- # @param dirs [Array<String>] directories
259
- # @return [String] shell variable lines
260
- # @api private
261
- def init_command_vars_for_powershell(dirs)
262
- [
263
- %{$dirs = @(#{dirs.map { |d| %{"#{d}"} }.join(", ")})},
264
- shell_var("root_path", config[:root_path])
265
- ].join("\n")
266
- end
267
-
268
- # Load cookbook dependency resolver code, if required.
269
- #
270
- # (see Base#load_needed_dependencies!)
271
- def load_needed_dependencies!
272
- super
273
- if File.exist?(berksfile)
274
- debug("Berksfile found at #{berksfile}, loading Berkshelf")
275
- Chef::Berkshelf.load!(logger)
276
- elsif File.exist?(cheffile)
277
- debug("Cheffile found at #{cheffile}, loading Librarian-Chef")
278
- Chef::Librarian.load!(logger)
279
- end
280
- end
281
-
282
- # @return [String] a powershell command to reload the `PATH` environment
283
- # variable, only to be used to support old Omnibus Chef packages that
284
- # require `PATH` to find the `ruby.exe` binary
285
- # @api private
286
- def reload_ps1_path
287
- [
288
- %{$env:PATH},
289
- %{[System.Environment]::GetEnvironmentVariable("PATH","Machine")\n\n}
290
- ].join(" = ")
291
- end
292
- end
293
- end
294
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, 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 "fileutils"
20
+ require "pathname"
21
+ require "json"
22
+ require "cgi"
23
+
24
+ require "kitchen/provisioner/chef/berkshelf"
25
+ require "kitchen/provisioner/chef/common_sandbox"
26
+ require "kitchen/provisioner/chef/librarian"
27
+ require "kitchen/util"
28
+ require "mixlib/install"
29
+ require "mixlib/install/script_generator"
30
+
31
+ begin
32
+ require "chef-config/config"
33
+ require "chef-config/workstation_config_loader"
34
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
35
+ # This space left intentionally blank.
36
+ end
37
+
38
+ module Kitchen
39
+
40
+ module Provisioner
41
+
42
+ # Common implementation details for Chef-related provisioners.
43
+ #
44
+ # @author Fletcher Nichol <fnichol@nichol.ca>
45
+ class ChefBase < Base
46
+
47
+ default_config :require_chef_omnibus, true
48
+ default_config :chef_omnibus_url, "https://www.chef.io/chef/install.sh"
49
+ default_config :chef_omnibus_install_options, nil
50
+ default_config :run_list, []
51
+ default_config :attributes, {}
52
+ default_config :config_path, nil
53
+ default_config :log_file, nil
54
+ default_config :log_level, "auto"
55
+ default_config :profile_ruby, false
56
+ default_config :cookbook_files_glob, %w[
57
+ README.* metadata.{json,rb}
58
+ attributes/**/* definitions/**/* files/**/* libraries/**/*
59
+ providers/**/* recipes/**/* resources/**/* templates/**/*
60
+ ].join(",")
61
+
62
+ default_config :data_path do |provisioner|
63
+ provisioner.calculate_path("data")
64
+ end
65
+ expand_path_for :data_path
66
+
67
+ default_config :data_bags_path do |provisioner|
68
+ provisioner.calculate_path("data_bags")
69
+ end
70
+ expand_path_for :data_bags_path
71
+
72
+ default_config :environments_path do |provisioner|
73
+ provisioner.calculate_path("environments")
74
+ end
75
+ expand_path_for :environments_path
76
+
77
+ default_config :nodes_path do |provisioner|
78
+ provisioner.calculate_path("nodes")
79
+ end
80
+ expand_path_for :nodes_path
81
+
82
+ default_config :roles_path do |provisioner|
83
+ provisioner.calculate_path("roles")
84
+ end
85
+ expand_path_for :roles_path
86
+
87
+ default_config :clients_path do |provisioner|
88
+ provisioner.calculate_path("clients")
89
+ end
90
+ expand_path_for :clients_path
91
+
92
+ default_config :encrypted_data_bag_secret_key_path do |provisioner|
93
+ provisioner.calculate_path("encrypted_data_bag_secret_key", :type => :file)
94
+ end
95
+ expand_path_for :encrypted_data_bag_secret_key_path
96
+
97
+ # Reads the local Chef::Config object (if present). We do this because
98
+ # we want to start bring Chef config and ChefDK tool config closer
99
+ # together. For example, we want to configure proxy settings in 1
100
+ # location instead of 3 configuration files.
101
+ #
102
+ # @param config [Hash] initial provided configuration
103
+ def initialize(config = {})
104
+ super(config)
105
+
106
+ if defined?(ChefConfig::WorkstationConfigLoader)
107
+ ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
108
+ end
109
+ # This exports any proxy config present in the Chef config to
110
+ # appropriate environment variables, which Test Kitchen respects
111
+ ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
112
+ end
113
+
114
+ # (see Base#create_sandbox)
115
+ def create_sandbox
116
+ super
117
+ Chef::CommonSandbox.new(config, sandbox_path, instance).populate
118
+ end
119
+
120
+ # (see Base#init_command)
121
+ def init_command
122
+ dirs = %w[
123
+ cookbooks data data_bags environments roles clients
124
+ encrypted_data_bag_secret
125
+ ].sort.map { |dir| remote_path_join(config[:root_path], dir) }
126
+
127
+ vars = if powershell_shell?
128
+ init_command_vars_for_powershell(dirs)
129
+ else
130
+ init_command_vars_for_bourne(dirs)
131
+ end
132
+
133
+ prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
134
+ end
135
+
136
+ # (see Base#install_command)
137
+ def install_command
138
+ return unless config[:require_chef_omnibus] || config[:product_name]
139
+ prefix_command(sudo(install_script_contents))
140
+ end
141
+
142
+ private
143
+
144
+ # @return [Hash] an option hash for the install commands
145
+ # @api private
146
+ def install_options
147
+ project = /\s*-P (\w+)\s*/.match(config[:chef_omnibus_install_options])
148
+ {
149
+ :omnibus_url => config[:chef_omnibus_url],
150
+ :project => project.nil? ? nil : project[1],
151
+ :install_flags => config[:chef_omnibus_install_options],
152
+ :sudo_command => sudo_command
153
+ }.tap do |opts|
154
+ opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
155
+ [:install_msi_url, :http_proxy, :https_proxy].each do |key|
156
+ opts[key] = config[key] if config.key? key
157
+ end
158
+ end
159
+ end
160
+
161
+ # @return [String] an absolute path to a Berksfile, relative to the
162
+ # kitchen root
163
+ # @api private
164
+ def berksfile
165
+ File.join(config[:kitchen_root], "Berksfile")
166
+ end
167
+
168
+ # @return [String] an absolute path to a Cheffile, relative to the
169
+ # kitchen root
170
+ # @api private
171
+ def cheffile
172
+ File.join(config[:kitchen_root], "Cheffile")
173
+ end
174
+
175
+ # Generates a Hash with default values for a solo.rb or client.rb Chef
176
+ # configuration file.
177
+ #
178
+ # @return [Hash] a configuration hash
179
+ # @api private
180
+ def default_config_rb # rubocop:disable Metrics/MethodLength
181
+ root = config[:root_path].gsub("$env:TEMP", "\#{ENV['TEMP']\}")
182
+
183
+ {
184
+ :node_name => instance.name,
185
+ :checksum_path => remote_path_join(root, "checksums"),
186
+ :file_cache_path => remote_path_join(root, "cache"),
187
+ :file_backup_path => remote_path_join(root, "backup"),
188
+ :cookbook_path => [
189
+ remote_path_join(root, "cookbooks"),
190
+ remote_path_join(root, "site-cookbooks")
191
+ ],
192
+ :data_bag_path => remote_path_join(root, "data_bags"),
193
+ :environment_path => remote_path_join(root, "environments"),
194
+ :node_path => remote_path_join(root, "nodes"),
195
+ :role_path => remote_path_join(root, "roles"),
196
+ :client_path => remote_path_join(root, "clients"),
197
+ :user_path => remote_path_join(root, "users"),
198
+ :validation_key => remote_path_join(root, "validation.pem"),
199
+ :client_key => remote_path_join(root, "client.pem"),
200
+ :chef_server_url => "http://127.0.0.1:8889",
201
+ :encrypted_data_bag_secret => remote_path_join(
202
+ root, "encrypted_data_bag_secret"
203
+ )
204
+ }
205
+ end
206
+
207
+ # Generates a rendered client.rb/solo.rb/knife.rb formatted file as a
208
+ # String.
209
+ #
210
+ # @param data [Hash] a key/value pair hash of configuration
211
+ # @return [String] a rendered Chef config file as a String
212
+ # @api private
213
+ def format_config_file(data)
214
+ data.each.map { |attr, value|
215
+ [attr, format_value(value)].join(" ")
216
+ }.join("\n")
217
+ end
218
+
219
+ # Converts a Ruby object to a String interpretation suitable for writing
220
+ # out to a client.rb/solo.rb/knife.rb file.
221
+ #
222
+ # @param obj [Object] an object
223
+ # @return [String] a string representation
224
+ # @api private
225
+ def format_value(obj)
226
+ if obj.is_a?(String) && obj =~ /^:/
227
+ obj
228
+ elsif obj.is_a?(String)
229
+ %{"#{obj.gsub(/\\/, "\\\\\\\\")}"}
230
+ elsif obj.is_a?(Array)
231
+ %{[#{obj.map { |i| format_value(i) }.join(", ")}]}
232
+ else
233
+ obj.inspect
234
+ end
235
+ end
236
+
237
+ # Generates the init command variables for Bourne shell-based platforms.
238
+ #
239
+ # @param dirs [Array<String>] directories
240
+ # @return [String] shell variable lines
241
+ # @api private
242
+ def init_command_vars_for_bourne(dirs)
243
+ [
244
+ shell_var("sudo_rm", sudo("rm")),
245
+ shell_var("dirs", dirs.join(" ")),
246
+ shell_var("root_path", config[:root_path])
247
+ ].join("\n")
248
+ end
249
+
250
+ # Generates the init command variables for PowerShell-based platforms.
251
+ #
252
+ # @param dirs [Array<String>] directories
253
+ # @return [String] shell variable lines
254
+ # @api private
255
+ def init_command_vars_for_powershell(dirs)
256
+ [
257
+ %{$dirs = @(#{dirs.map { |d| %{"#{d}"} }.join(", ")})},
258
+ shell_var("root_path", config[:root_path])
259
+ ].join("\n")
260
+ end
261
+
262
+ # Load cookbook dependency resolver code, if required.
263
+ #
264
+ # (see Base#load_needed_dependencies!)
265
+ def load_needed_dependencies!
266
+ super
267
+ if File.exist?(berksfile)
268
+ debug("Berksfile found at #{berksfile}, loading Berkshelf")
269
+ Chef::Berkshelf.load!(logger)
270
+ elsif File.exist?(cheffile)
271
+ debug("Cheffile found at #{cheffile}, loading Librarian-Chef")
272
+ Chef::Librarian.load!(logger)
273
+ end
274
+ end
275
+
276
+ # @return [String] a powershell command to reload the `PATH` environment
277
+ # variable, only to be used to support old Omnibus Chef packages that
278
+ # require `PATH` to find the `ruby.exe` binary
279
+ # @api private
280
+ def reload_ps1_path
281
+ [
282
+ %{$env:PATH},
283
+ %{[System.Environment]::GetEnvironmentVariable("PATH","Machine")\n\n}
284
+ ].join(" = ")
285
+ end
286
+
287
+ # @return [String] contents of the install script
288
+ # @api private
289
+ def install_script_contents
290
+ # by default require_chef_omnibus is set to true. Check config[:product_name] first
291
+ # so that we can use it if configured.
292
+ if config[:product_name]
293
+ script_for_product
294
+ elsif config[:require_chef_omnibus]
295
+ script_for_omnibus_version
296
+ end
297
+ end
298
+
299
+ # @return [String] contents of product based install script
300
+ # @api private
301
+ def script_for_product
302
+ installer = Mixlib::Install.new({
303
+ :product_name => config[:product_name],
304
+ :product_version => config[:product_version],
305
+ :channel => (config[:channel] || :stable).to_sym
306
+ }.tap do |opts|
307
+ opts[:shell_type] = :ps1 if powershell_shell?
308
+ [:platform, :platform_version, :architecture].each do |key|
309
+ opts[key] = config[key] if config[key]
310
+ end
311
+ end)
312
+ config[:chef_omnibus_root] = installer.root
313
+ if powershell_shell?
314
+ installer.install_command
315
+ else
316
+ install_from_file(installer.install_command)
317
+ end
318
+ end
319
+
320
+ def install_from_file(command)
321
+ install_file = "/tmp/chef-installer.sh"
322
+ script = ["cat > #{install_file} <<\"EOL\""]
323
+ script << "#!/bin/bash"
324
+ script << command
325
+ script << "EOL"
326
+ script << "chmod +x #{install_file}"
327
+ script << sudo(install_file)
328
+ script.join("\n")
329
+ end
330
+
331
+ # @return [String] contents of version based install script
332
+ # @api private
333
+ def script_for_omnibus_version
334
+ installer = Mixlib::Install::ScriptGenerator.new(
335
+ config[:require_chef_omnibus], powershell_shell?, install_options)
336
+ config[:chef_omnibus_root] = installer.root
337
+ installer.install_command
338
+ end
339
+ end
340
+ end
341
+ end