test-kitchen 1.7.0 → 1.7.1.dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.cane +8 -8
- data/.gitattributes +3 -0
- data/.github/ISSUE_TEMPLATE.md +55 -55
- data/.gitignore +28 -28
- data/.kitchen.ci.yml +23 -23
- data/.kitchen.proxy.yml +27 -27
- data/.rubocop.yml +3 -3
- data/.travis.yml +70 -70
- data/.yardopts +3 -3
- data/Berksfile +3 -3
- data/CHANGELOG.md +1090 -1083
- data/CONTRIBUTING.md +14 -14
- data/Gemfile +19 -19
- data/Gemfile.proxy_tests +4 -4
- data/Guardfile +42 -42
- data/LICENSE +15 -15
- data/MAINTAINERS.md +23 -23
- data/README.md +135 -135
- data/Rakefile +61 -61
- data/appveyor.yml +44 -44
- data/features/kitchen_action_commands.feature +164 -164
- data/features/kitchen_command.feature +16 -16
- data/features/kitchen_console_command.feature +34 -34
- data/features/kitchen_defaults.feature +38 -38
- data/features/kitchen_diagnose_command.feature +96 -96
- data/features/kitchen_driver_create_command.feature +64 -64
- data/features/kitchen_driver_discover_command.feature +25 -25
- data/features/kitchen_help_command.feature +16 -16
- data/features/kitchen_init_command.feature +274 -274
- data/features/kitchen_list_command.feature +104 -104
- data/features/kitchen_login_command.feature +62 -62
- data/features/kitchen_sink_command.feature +30 -30
- data/features/kitchen_test_command.feature +88 -88
- data/features/step_definitions/gem_steps.rb +36 -36
- data/features/step_definitions/git_steps.rb +5 -5
- data/features/step_definitions/output_steps.rb +5 -5
- data/features/support/env.rb +75 -75
- data/lib/kitchen.rb +150 -150
- data/lib/kitchen/base64_stream.rb +55 -55
- data/lib/kitchen/cli.rb +419 -419
- data/lib/kitchen/collection.rb +55 -55
- data/lib/kitchen/color.rb +65 -65
- data/lib/kitchen/command.rb +185 -185
- data/lib/kitchen/command/action.rb +45 -45
- data/lib/kitchen/command/console.rb +58 -58
- data/lib/kitchen/command/diagnose.rb +92 -92
- data/lib/kitchen/command/driver_discover.rb +105 -105
- data/lib/kitchen/command/exec.rb +41 -41
- data/lib/kitchen/command/list.rb +119 -119
- data/lib/kitchen/command/login.rb +43 -43
- data/lib/kitchen/command/sink.rb +54 -54
- data/lib/kitchen/command/test.rb +51 -51
- data/lib/kitchen/config.rb +322 -322
- data/lib/kitchen/configurable.rb +529 -529
- data/lib/kitchen/data_munger.rb +959 -959
- data/lib/kitchen/diagnostic.rb +141 -141
- data/lib/kitchen/driver.rb +56 -56
- data/lib/kitchen/driver/base.rb +134 -134
- data/lib/kitchen/driver/dummy.rb +108 -108
- data/lib/kitchen/driver/proxy.rb +72 -72
- data/lib/kitchen/driver/ssh_base.rb +357 -357
- data/lib/kitchen/errors.rb +229 -229
- data/lib/kitchen/generator/driver_create.rb +177 -177
- data/lib/kitchen/generator/init.rb +296 -296
- data/lib/kitchen/instance.rb +662 -662
- data/lib/kitchen/lazy_hash.rb +142 -142
- data/lib/kitchen/loader/yaml.rb +349 -349
- data/lib/kitchen/logger.rb +423 -423
- data/lib/kitchen/logging.rb +56 -56
- data/lib/kitchen/login_command.rb +52 -52
- data/lib/kitchen/metadata_chopper.rb +52 -52
- data/lib/kitchen/platform.rb +67 -67
- data/lib/kitchen/provisioner.rb +54 -54
- data/lib/kitchen/provisioner/base.rb +236 -236
- data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
- data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
- data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
- data/lib/kitchen/provisioner/chef_apply.rb +124 -124
- data/lib/kitchen/provisioner/chef_base.rb +341 -341
- data/lib/kitchen/provisioner/chef_solo.rb +88 -88
- data/lib/kitchen/provisioner/chef_zero.rb +245 -245
- data/lib/kitchen/provisioner/dummy.rb +79 -79
- data/lib/kitchen/provisioner/shell.rb +138 -138
- data/lib/kitchen/rake_tasks.rb +63 -63
- data/lib/kitchen/shell_out.rb +93 -93
- data/lib/kitchen/ssh.rb +276 -276
- data/lib/kitchen/state_file.rb +120 -120
- data/lib/kitchen/suite.rb +51 -51
- data/lib/kitchen/thor_tasks.rb +66 -66
- data/lib/kitchen/transport.rb +54 -54
- data/lib/kitchen/transport/base.rb +176 -176
- data/lib/kitchen/transport/dummy.rb +79 -79
- data/lib/kitchen/transport/ssh.rb +364 -364
- data/lib/kitchen/transport/winrm.rb +486 -486
- data/lib/kitchen/util.rb +147 -147
- data/lib/kitchen/verifier.rb +55 -55
- data/lib/kitchen/verifier/base.rb +235 -235
- data/lib/kitchen/verifier/busser.rb +277 -277
- data/lib/kitchen/verifier/dummy.rb +79 -79
- data/lib/kitchen/verifier/shell.rb +101 -101
- data/lib/kitchen/version.rb +21 -21
- data/lib/vendor/hash_recursive_merge.rb +82 -82
- data/spec/kitchen/base64_stream_spec.rb +77 -77
- data/spec/kitchen/cli_spec.rb +56 -56
- data/spec/kitchen/collection_spec.rb +80 -80
- data/spec/kitchen/color_spec.rb +54 -54
- data/spec/kitchen/config_spec.rb +408 -408
- data/spec/kitchen/configurable_spec.rb +1095 -1095
- data/spec/kitchen/data_munger_spec.rb +2694 -2694
- data/spec/kitchen/diagnostic_spec.rb +129 -129
- data/spec/kitchen/driver/base_spec.rb +121 -121
- data/spec/kitchen/driver/dummy_spec.rb +199 -199
- data/spec/kitchen/driver/proxy_spec.rb +138 -138
- data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
- data/spec/kitchen/driver_spec.rb +112 -112
- data/spec/kitchen/errors_spec.rb +309 -309
- data/spec/kitchen/instance_spec.rb +1419 -1419
- data/spec/kitchen/lazy_hash_spec.rb +117 -117
- data/spec/kitchen/loader/yaml_spec.rb +774 -774
- data/spec/kitchen/logger_spec.rb +429 -429
- data/spec/kitchen/logging_spec.rb +59 -59
- data/spec/kitchen/login_command_spec.rb +68 -68
- data/spec/kitchen/metadata_chopper_spec.rb +82 -82
- data/spec/kitchen/platform_spec.rb +89 -89
- data/spec/kitchen/provisioner/base_spec.rb +386 -386
- data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
- data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1161
- data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
- data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
- data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
- data/spec/kitchen/provisioner/shell_spec.rb +566 -566
- data/spec/kitchen/provisioner_spec.rb +107 -107
- data/spec/kitchen/shell_out_spec.rb +150 -150
- data/spec/kitchen/ssh_spec.rb +693 -693
- data/spec/kitchen/state_file_spec.rb +129 -129
- data/spec/kitchen/suite_spec.rb +62 -62
- data/spec/kitchen/transport/base_spec.rb +89 -89
- data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
- data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
- data/spec/kitchen/transport_spec.rb +112 -112
- data/spec/kitchen/util_spec.rb +165 -165
- data/spec/kitchen/verifier/base_spec.rb +362 -362
- data/spec/kitchen/verifier/busser_spec.rb +610 -610
- data/spec/kitchen/verifier/dummy_spec.rb +99 -99
- data/spec/kitchen/verifier/shell_spec.rb +160 -160
- data/spec/kitchen/verifier_spec.rb +120 -120
- data/spec/kitchen_spec.rb +114 -114
- data/spec/spec_helper.rb +85 -85
- data/spec/support/powershell_max_size_spec.rb +40 -40
- data/support/busser_install_command.ps1 +14 -14
- data/support/busser_install_command.sh +14 -14
- data/support/chef-client-zero.rb +77 -77
- data/support/chef_base_init_command.ps1 +18 -18
- data/support/chef_base_init_command.sh +2 -2
- data/support/chef_base_install_command.ps1 +85 -85
- data/support/chef_base_install_command.sh +229 -229
- data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
- data/support/chef_zero_prepare_command_legacy.sh +10 -10
- data/support/download_helpers.sh +109 -109
- data/support/dummy-validation.pem +27 -27
- data/templates/driver/CHANGELOG.md.erb +3 -3
- data/templates/driver/Gemfile.erb +3 -3
- data/templates/driver/README.md.erb +64 -64
- data/templates/driver/Rakefile.erb +21 -21
- data/templates/driver/driver.rb.erb +23 -23
- data/templates/driver/gemspec.erb +29 -29
- data/templates/driver/gitignore.erb +17 -17
- data/templates/driver/license_apachev2.erb +15 -15
- data/templates/driver/license_lgplv3.erb +16 -16
- data/templates/driver/license_mit.erb +22 -22
- data/templates/driver/license_reserved.erb +5 -5
- data/templates/driver/tailor.erb +4 -4
- data/templates/driver/travis.yml.erb +11 -11
- data/templates/driver/version.rb.erb +12 -12
- data/templates/init/chefignore.erb +1 -1
- data/templates/init/kitchen.yml.erb +18 -18
- data/test-kitchen.gemspec +62 -62
- data/test/integration/default/default_spec.rb +3 -3
- data/testing_windows.md +37 -37
- metadata +5 -4
|
@@ -1,341 +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
|
-
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
|
|
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
|