test-kitchen 1.6.0 → 1.7.0

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