chef 19.3.15 → 19.4.46

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -2
  3. data/chef.gemspec +5 -4
  4. data/lib/chef/application/base.rb +1 -5
  5. data/lib/chef/chef_fs/file_system/chef_server/organization_invites_entry.rb +1 -1
  6. data/lib/chef/cookbook_manifest.rb +18 -7
  7. data/lib/chef/cookbook_uploader.rb +1 -1
  8. data/lib/chef/cookbook_version.rb +3 -3
  9. data/lib/chef/data_bag.rb +3 -4
  10. data/lib/chef/data_collector.rb +1 -0
  11. data/lib/chef/encrypted_data_bag_item.rb +1 -1
  12. data/lib/chef/formatters/error_description.rb +8 -1
  13. data/lib/chef/http/auth_credentials.rb +1 -1
  14. data/lib/chef/http/authenticator.rb +18 -5
  15. data/lib/chef/http.rb +2 -2
  16. data/lib/chef/mixin/properties.rb +1 -1
  17. data/lib/chef/mixin/template.rb +24 -2
  18. data/lib/chef/property.rb +11 -1
  19. data/lib/chef/provider/group/dscl.rb +9 -5
  20. data/lib/chef/provider/group.rb +5 -0
  21. data/lib/chef/provider/mount/solaris.rb +10 -18
  22. data/lib/chef/provider/package/chocolatey.rb +2 -2
  23. data/lib/chef/provider/package/homebrew.rb +2 -3
  24. data/lib/chef/provider/package/portage.rb +0 -1
  25. data/lib/chef/provider/package/yum/python_helper.rb +0 -1
  26. data/lib/chef/provider/service/debian.rb +9 -9
  27. data/lib/chef/resource/apt_repository.rb +5 -1
  28. data/lib/chef/resource/archive_dll_locator.rb +70 -0
  29. data/lib/chef/resource/archive_file.rb +56 -27
  30. data/lib/chef/resource/chef_client_config.rb +187 -21
  31. data/lib/chef/resource/chef_client_hab_ca_cert.rb +10 -3
  32. data/lib/chef/resource/chef_vault_secret.rb +1 -1
  33. data/lib/chef/resource/chocolatey_installer.rb +41 -7
  34. data/lib/chef/resource/chocolatey_package.rb +1 -1
  35. data/lib/chef/resource/dnf_package.rb +1 -1
  36. data/lib/chef/resource/habitat/habitat_package.rb +1 -1
  37. data/lib/chef/resource/habitat/habitat_sup.rb +2 -2
  38. data/lib/chef/resource/habitat_config.rb +1 -1
  39. data/lib/chef/resource/habitat_service.rb +1 -1
  40. data/lib/chef/resource/helpers/path_helpers.rb +2 -2
  41. data/lib/chef/resource/homebrew_cask.rb +11 -5
  42. data/lib/chef/resource/homebrew_tap.rb +18 -0
  43. data/lib/chef/resource/launchd.rb +1 -1
  44. data/lib/chef/resource/mount.rb +2 -2
  45. data/lib/chef/resource/openssl_ec_private_key.rb +1 -1
  46. data/lib/chef/resource/openssl_ec_public_key.rb +2 -2
  47. data/lib/chef/resource/openssl_rsa_private_key.rb +1 -1
  48. data/lib/chef/resource/openssl_rsa_public_key.rb +2 -2
  49. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  50. data/lib/chef/resource/openssl_x509_request.rb +1 -1
  51. data/lib/chef/resource/powershell_package_source.rb +1 -1
  52. data/lib/chef/resource/rhsm_register.rb +1 -1
  53. data/lib/chef/resource/service.rb +1 -1
  54. data/lib/chef/resource/sysctl.rb +22 -5
  55. data/lib/chef/resource/windows_ad_join.rb +1 -1
  56. data/lib/chef/resource/windows_certificate.rb +1 -1
  57. data/lib/chef/resource/windows_security_policy.rb +0 -1
  58. data/lib/chef/resource/windows_service.rb +1 -1
  59. data/lib/chef/resource/windows_task.rb +1 -3
  60. data/lib/chef/resource/windows_update_settings.rb +51 -30
  61. data/lib/chef/resource/yum_package.rb +1 -1
  62. data/lib/chef/resource/yum_repository.rb +2 -2
  63. data/lib/chef/resource.rb +2 -2
  64. data/lib/chef/resource_inspector.rb +1 -1
  65. data/lib/chef/role.rb +1 -1
  66. data/lib/chef/target_io/train/dir.rb +10 -1
  67. data/lib/chef/target_io/train/fileutils.rb +1 -1
  68. data/lib/chef/util/selinux.rb +2 -2
  69. data/lib/chef/version.rb +1 -1
  70. data/lib/chef/win32/api/command_line_helper.rb +2 -2
  71. data/lib/chef/win32/api/error.rb +0 -2
  72. data/lib/chef/win32/api/net.rb +2 -4
  73. data/lib/chef/win32/api.rb +4 -4
  74. data/lib/chef/win32/net.rb +0 -1
  75. data/lib/chef/win32/security/acl.rb +1 -1
  76. data/lib/chef/win32/security.rb +1 -1
  77. metadata +18 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2826c214024eece8ad5f19f58627b1f9102d9d7df7425fbd8d0dd65cce65993
4
- data.tar.gz: e2a380dfb7165dcbd1c5984bb7ac5f4dee6e2fdfc766c6f759652449a8e422f7
3
+ metadata.gz: 8850f19e1d0b60534fef8df79d7d49b345b46eb651325084eaae19d88649e46f
4
+ data.tar.gz: efcd85be042071e417141f4567304106597e5d3abbd079c3b931ca48313e6a1a
5
5
  SHA512:
6
- metadata.gz: 87932a0c176140829d996007a732be80b8692cafc7efe7edfca548d94a938d04351890a2ec9a05898cf93081b23782a1f4a581947ea2eba818600e4cd75d6609
7
- data.tar.gz: e050d2dd52f2823ed156f0526824df52f75e7b8ed4f7ac7fa3711209997838135b9bd7c1fb3ce0b7beb686896f7897435e07d14699dc2dfe44bc3374c8aecaf1
6
+ metadata.gz: 4faa3811747991d8aceb95407ab2f30cef576066ada2114d1564829251b63d9ea7f4b5a87566bcf51b8041acd278c18b37ce2620b6ceeef21a8d9879d20839be
7
+ data.tar.gz: 777c66a062301e0f7bf809abc3fa85552db3b46ff5b066b1695a269fa1b887de1bf1606100069d5cede4876ba7dedaa27f328e32997b547bb0cc39f37dc09854
data/Gemfile CHANGED
@@ -17,7 +17,7 @@ gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?
17
17
 
18
18
  # required for FIPS or bundler will pick up default openssl
19
19
  install_if -> { !Gem.platforms.any? { |platform| !platform.is_a?(String) && platform.os == "darwin" } } do
20
- gem "openssl", "= 3.3.1"
20
+ gem "openssl", "= 3.3.3"
21
21
  end
22
22
 
23
23
  if File.exist?(File.expand_path("chef-bin", __dir__))
@@ -31,7 +31,7 @@ end
31
31
  group(:packaging) do
32
32
  gem "appbundler"
33
33
  gem "rb-readline"
34
- gem "inspec-core-bin", "= 7.0.107" # need to provide the binaries for inspec
34
+ gem "inspec-core-bin", "= 7.2.1" # need to provide the binaries for inspec
35
35
  gem "chef-vault"
36
36
  end
37
37
 
@@ -61,6 +61,9 @@ group(:development, :test) do
61
61
  gem "webmock"
62
62
  gem "crack", "~> 1.0.1"
63
63
  gem "fauxhai-ng" # for chef-utils gem
64
+ # Pinned explicitly rather than floating in via inspec-core, since this is
65
+ # what the lint workflow runs and it also pins our RuboCop version.
66
+ gem "cookstyle", ">= 9.0"
64
67
  end
65
68
 
66
69
  instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
data/chef.gemspec CHANGED
@@ -54,10 +54,11 @@ Gem::Specification.new do |s|
54
54
  s.add_dependency "mixlib-shellout", ">= 3.3.8", "< 3.5.0"
55
55
  s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0"
56
56
  s.add_dependency "ohai", "~> 19.0"
57
- s.add_dependency "inspec-core", "~> 7.0.107"
57
+ s.add_dependency "inspec-core", "~> 7.2.1"
58
58
 
59
59
  s.add_dependency "ffi", ">= 1.15.5", "< 1.18.0"
60
- s.add_dependency "ffi-yajl", ">= 2.2", "< 4.0"
60
+ # ffi-yajl has a stale version in 3.0.0 specifically that is in use. 3.0.1 and higher is ok again
61
+ s.add_dependency "ffi-yajl", ">= 2.2", "!= 3.0.0", "< 4.0"
61
62
  s.add_dependency "net-sftp", ">= 2.1.2", "< 5.0" # remote_file resource
62
63
  s.add_dependency "net-ftp" # remote_file resource
63
64
  s.add_dependency "ed25519", "~> 1.2" # ssh-ed25519 support for target mode
@@ -70,13 +71,13 @@ Gem::Specification.new do |s|
70
71
 
71
72
  s.add_dependency "plist", "~> 3.2" # launchd, dscl/mac user, macos_userdefaults, and plist resources
72
73
  s.add_dependency "iniparse", "~> 1.4" # systemd_unit resource
73
- s.add_dependency "addressable"
74
+ s.add_dependency "addressable", ">= 2.9.0"
74
75
  s.add_dependency "syslog"
75
76
  s.add_dependency "csv", "~> 3.3.5" # really needs to come from inspec?
76
77
  s.add_dependency "syslog-logger", "~> 1.6"
77
78
  s.add_dependency "unf_ext", "~> 0.0.9.1" # older platforms
78
79
  s.add_dependency "uri", ">= 1.0.4", "< 1.2.0" # CVE-2025-61594 fixed in >= 1.0.4
79
- s.add_dependency "corefoundation", "~> 0.3.4" # macos_userdefaults resource
80
+ s.add_dependency "corefoundation", "~> 0.3.19" # macos_userdefaults resource
80
81
 
81
82
  s.add_dependency "proxifier2", "~> 1.1"
82
83
 
@@ -219,11 +219,7 @@ class Chef::Application::Base < Chef::Application
219
219
  option :target,
220
220
  short: "-t TARGET",
221
221
  long: "--target TARGET",
222
- description: "Target #{ChefUtils::Dist::Infra::PRODUCT} against a remote system or device",
223
- proc: lambda { |target|
224
- Chef::Log.warn "-- EXPERIMENTAL -- Target mode activated, resources and dsl may change without warning -- EXPERIMENTAL --"
225
- target
226
- }
222
+ description: "Target #{ChefUtils::Dist::Infra::PRODUCT} against a remote system or device"
227
223
 
228
224
  option :disable_config,
229
225
  long: "--disable-config",
@@ -41,7 +41,7 @@ class Chef
41
41
 
42
42
  def write(contents)
43
43
  desired_invites = minimize_value(Chef::JSONCompat.parse(contents, create_additions: false))
44
- actual_invites = _read_json.inject({}) { |h, val| h[val["username"]] = val["id"]; h }
44
+ actual_invites = _read_json.to_h { |val| [val["username"], val["id"]] }
45
45
  invites = actual_invites.keys
46
46
  (desired_invites - invites).each do |invite|
47
47
 
@@ -66,6 +66,7 @@ class Chef
66
66
  @manifest = nil
67
67
  @checksums = nil
68
68
  @manifest_records_by_path = nil
69
+ @relative_dir_cache = Hash.new { |h, k| h[k] = {} }
69
70
  true
70
71
  end
71
72
 
@@ -267,9 +268,21 @@ class Chef
267
268
  @manifest = manifest
268
269
  end
269
270
 
271
+ # Many files in a cookbook share a directory, and computing a file's path
272
+ # relative to a root path is expensive in deeply nested directories over
273
+ # large numbers of files. Cache the relative path per (root path,
274
+ # directory) and append the file's basename so the expensive computation
275
+ # runs once per directory instead of once per file.
276
+ def get_relative_path_from_root(root_path, file)
277
+ dirname = File.dirname(file)
278
+ @relative_dir_cache[root_path][dirname] ||=
279
+ Chef::Util::PathHelper.relative_path_from(root_path, dirname)
280
+ @relative_dir_cache[root_path][dirname] + File.basename(file)
281
+ end
282
+
270
283
  def parse_file_from_root_paths(file)
271
284
  root_paths.each do |root_path|
272
- pathname = Chef::Util::PathHelper.relative_path_from(root_path, file)
285
+ pathname = get_relative_path_from_root(root_path, file)
273
286
 
274
287
  parts = pathname.each_filename.take(2)
275
288
  # Check if path is actually under root_path
@@ -299,9 +312,8 @@ class Chef
299
312
  end
300
313
 
301
314
  def extract_checksums_from_manifest(manifest)
302
- manifest[:all_files].inject({}) do |memo, manifest_record|
303
- memo[manifest_record[:checksum]] = nil
304
- memo
315
+ manifest[:all_files].to_h do |manifest_record|
316
+ [manifest_record[:checksum], nil]
305
317
  end
306
318
  end
307
319
 
@@ -310,9 +322,8 @@ class Chef
310
322
  end
311
323
 
312
324
  def extract_manifest_records_by_path(manifest)
313
- manifest[:all_files].inject({}) do |memo, manifest_record|
314
- memo[manifest_record[:path]] = manifest_record
315
- memo
325
+ manifest[:all_files].to_h do |manifest_record|
326
+ [manifest_record[:path], manifest_record]
316
327
  end
317
328
  end
318
329
 
@@ -54,7 +54,7 @@ class Chef
54
54
  checksum_files.merge!(cb.checksums)
55
55
  end
56
56
 
57
- checksums = checksum_files.inject({}) { |memo, elt| memo[elt.first] = nil; memo }
57
+ checksums = checksum_files.to_h { |checksum, _path| [checksum, nil] }
58
58
  new_sandbox = rest.post("sandboxes", { checksums: checksums })
59
59
 
60
60
  Chef::Log.info("Uploading files")
@@ -605,13 +605,13 @@ class Chef
605
605
  # For each manifest record, produce a mapping of base filename (i.e. recipe name
606
606
  # or attribute file) to on disk location
607
607
  def relative_paths_by_name(records)
608
- records.select { |record| record[:name].end_with?(".rb") }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:path]; memo }
608
+ records.select { |record| record[:name].end_with?(".rb") }.to_h { |record| [File.basename(record[:name], ".rb"), record[:path]] }
609
609
  end
610
610
 
611
611
  # For each manifest record, produce a mapping of base filename (i.e. recipe name
612
612
  # or attribute file) to on disk location
613
613
  def filenames_by_name(records)
614
- records.select { |record| record[:name].end_with?(".rb") }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
614
+ records.select { |record| record[:name].end_with?(".rb") }.to_h { |record| [File.basename(record[:name], ".rb"), record[:full_path]] }
615
615
  end
616
616
 
617
617
  # Filters YAML files from the superset of provided files.
@@ -639,7 +639,7 @@ class Chef
639
639
 
640
640
  # Filters JSON files from the superset of provided files.
641
641
  def json_filenames_by_name(records)
642
- records.select { |record| record[:name].end_with?(".json") }.inject({}) { |memo, record| memo[File.basename(record[:name], ".json")] = record[:full_path]; memo }
642
+ records.select { |record| record[:name].end_with?(".json") }.to_h { |record| [File.basename(record[:name], ".json"), record[:full_path]] }
643
643
  end
644
644
 
645
645
  def file_vendor
data/lib/chef/data_bag.rb CHANGED
@@ -100,13 +100,12 @@ class Chef
100
100
  Chef::Util::PathHelper.escape_glob_dir(path), "*"
101
101
  )).map { |f| File.basename(f) }.sort
102
102
  end
103
- names.inject({}) { |h, n| h[n] = n; h }
103
+ names.to_h { |n| [n, n] }
104
104
  else
105
105
  if inflate
106
106
  # Can't search for all data bags like other objects, fall back to N+1 :(
107
- list(false).inject({}) do |response, bag_and_uri|
108
- response[bag_and_uri.first] = load(bag_and_uri.first)
109
- response
107
+ list(false).to_h do |bag_name, _bag_uri|
108
+ [bag_name, load(bag_name)]
110
109
  end
111
110
  else
112
111
  Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("data")
@@ -66,6 +66,7 @@ class Chef
66
66
  @events = events
67
67
  @expanded_run_list = {}
68
68
  @deprecations = Set.new
69
+ @http_output_locations_clients = {}
69
70
  end
70
71
 
71
72
  # Hook to grab the run_status. We also make the decision to run or not run here (our
@@ -84,7 +84,7 @@ class Chef::EncryptedDataBagItem
84
84
  end
85
85
 
86
86
  def to_h
87
- @enc_hash.keys.inject({}) { |hash, key| hash[key] = self[key]; hash }
87
+ @enc_hash.keys.to_h { |key| [key, self[key]] }
88
88
  end
89
89
 
90
90
  alias_method :to_hash, :to_h
@@ -59,10 +59,17 @@ class Chef
59
59
 
60
60
  private
61
61
 
62
+ MAX_DISPLAY_TEXT_LENGTH = 10_000
63
+
62
64
  def display_section(heading, text, out)
63
65
  out.puts heading
64
66
  out.puts "-" * heading.size
65
- out.puts text
67
+ if text.is_a?(String) && text.length > MAX_DISPLAY_TEXT_LENGTH
68
+ out.puts text[0, MAX_DISPLAY_TEXT_LENGTH]
69
+ out.puts "\n... [truncated #{text.length - MAX_DISPLAY_TEXT_LENGTH} characters of output]"
70
+ else
71
+ out.puts text
72
+ end
66
73
  out.puts "\n"
67
74
  end
68
75
 
@@ -56,7 +56,7 @@ class Chef
56
56
 
57
57
  sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(request_params)
58
58
  signed = sign_obj.sign(key, use_ssh_agent: @use_ssh_agent).merge({ host: host })
59
- signed.inject({}) { |memo, kv| memo[(kv[0].to_s.upcase).to_s] = kv[1]; memo }
59
+ signed.to_h { |k, v| [k.to_s.upcase.to_s, v] }
60
60
  end
61
61
 
62
62
  end
@@ -150,8 +150,9 @@ class Chef
150
150
 
151
151
  if !!results
152
152
  @raw_key = results
153
- elsif key_file == nil? && raw_key == nil?
154
- puts "\nNo key detected\n"
153
+ elsif key_file.nil? && raw_key.nil?
154
+ Chef::Log.debug("No key detected")
155
+ return
155
156
  elsif !!key_file
156
157
  @raw_key = IO.read(key_file).strip
157
158
  elsif !!raw_key
@@ -305,14 +306,26 @@ class Chef
305
306
 
306
307
  if !!check_certstore_for_key(client_name)
307
308
  ps_blob = powershell_exec!(get_the_key_ps(client_name, password)).result
309
+ # ps_blob can be false when the PowerShell Catch block fires (e.g. cert export
310
+ # race condition or temporary store lock). Guard before calling Hash#[] to
311
+ # avoid NoMethodError: undefined method `[]' for false:FalseClass.
312
+ return false unless ps_blob.is_a?(Hash) && ps_blob["PSPath"]
313
+
308
314
  file_path = ps_blob["PSPath"].split("::")[1]
309
- pkcs = OpenSSL::PKCS12.new(File.binread(file_path), password)
315
+
316
+ # Use begin/ensure to guarantee the unique temp file is deleted even if
317
+ # File.binread or OpenSSL::PKCS12.new raises an exception, preventing
318
+ # orphaned PFX files on disk.
319
+ begin
320
+ pkcs = OpenSSL::PKCS12.new(File.binread(file_path), password)
321
+ ensure
322
+ File.delete(file_path) if File.exist?(file_path)
323
+ end
310
324
 
311
325
  # We check the pfx we just extracted the private key from
312
326
  # if that cert is expiring in 7 days or less we generate a new pfx/p12 object
313
327
  # then we post the new public key from that to the client endpoint on
314
328
  # chef server.
315
- File.delete(file_path)
316
329
  key_expiring = is_certificate_expiring?(pkcs)
317
330
  if key_expiring
318
331
  powershell_exec!(delete_old_key_ps(client_name))
@@ -338,7 +351,7 @@ class Chef
338
351
  Try {
339
352
  $my_pwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText;
340
353
  $cert = Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } -ErrorAction Stop;
341
- $tempfile = [System.IO.Path]::GetTempPath() + "export_pfx.pfx";
354
+ $tempfile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName() + ".pfx");
342
355
  Export-PfxCertificate -Cert $cert -Password $my_pwd -FilePath $tempfile;
343
356
  }
344
357
  Catch {
data/lib/chef/http.rb CHANGED
@@ -510,9 +510,9 @@ class Chef
510
510
 
511
511
  # @api private
512
512
  def redirected_to(response)
513
- return nil unless response.is_a?(Net::HTTPRedirection)
513
+ return nil unless response.is_a?(Net::HTTPRedirection)
514
514
  # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this
515
- return nil if response.is_a?(Net::HTTPNotModified)
515
+ return nil if response.is_a?(Net::HTTPNotModified)
516
516
 
517
517
  response["location"]
518
518
  end
@@ -100,7 +100,7 @@ class Chef
100
100
  def property(name, type = NOT_PASSED, **options)
101
101
  name = name.to_sym
102
102
 
103
- options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo }
103
+ options.transform_keys!(&:to_sym)
104
104
 
105
105
  options[:instance_variable_name] = :"@#{name}" unless options.key?(:instance_variable_name)
106
106
  options[:name] = name
@@ -93,6 +93,12 @@ class Chef
93
93
  @_extension_modules = []
94
94
  end
95
95
 
96
+ # Provide a compact inspect so exception messages do not dump the full
97
+ # template context, including node attributes and secrets.
98
+ def inspect
99
+ "#<#{self.class} template_name=#{@template_name.inspect} cookbook_name=#{@cookbook_name.inspect}>"
100
+ end
101
+
96
102
  ###
97
103
  # USER FACING API
98
104
  ###
@@ -220,8 +226,15 @@ class Chef
220
226
  @original_exception, @template, @context, @options = original_exception, template, context, options
221
227
  end
222
228
 
229
+ MAX_MESSAGE_LENGTH = 10_000
230
+
223
231
  def message
224
- @original_exception.message
232
+ msg = @original_exception.message
233
+ if msg.length > MAX_MESSAGE_LENGTH
234
+ msg[0, MAX_MESSAGE_LENGTH] + "\n... [truncated #{msg.length - MAX_MESSAGE_LENGTH} characters]"
235
+ else
236
+ msg
237
+ end
225
238
  end
226
239
 
227
240
  def line_number
@@ -258,7 +271,16 @@ class Chef
258
271
  end
259
272
 
260
273
  def to_s
261
- "\n\n#{self.class} (#{message}) #{source_location}:\n\n" +
274
+ location_parts = []
275
+ if @context.respond_to?(:cookbook_name) && @context.cookbook_name
276
+ location_parts << "cookbook: #{@context.cookbook_name}"
277
+ end
278
+ if @context.respond_to?(:template_name) && @context.template_name
279
+ location_parts << "template: #{@context.template_name}"
280
+ end
281
+ location_hint = location_parts.empty? ? "" : " (#{location_parts.join(", ")})"
282
+
283
+ "\n\n#{self.class} (#{message}) #{source_location}#{location_hint}:\n\n" +
262
284
  "#{source_listing}\n\n #{original_exception.backtrace.join("\n ")}\n\n"
263
285
  end
264
286
  end
data/lib/chef/property.rb CHANGED
@@ -122,7 +122,9 @@ class Chef
122
122
  # will create a deprecation warning.
123
123
  #
124
124
  def initialize(**options)
125
- options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo }
125
+ # `**options` is already a fresh hash owned by this method, so normalize the
126
+ # keys in place rather than building a second hash to hold the same data.
127
+ options.transform_keys!(&:to_sym)
126
128
  @options = options
127
129
  options[:name] = options[:name].to_sym if options[:name]
128
130
  options[:instance_variable_name] = options[:instance_variable_name].to_sym if options[:instance_variable_name]
@@ -543,6 +545,14 @@ class Chef
543
545
  Chef::Mixin::ParamsValidate.validate({ name => value }, { name => validation_options })
544
546
  end
545
547
  end
548
+ rescue Chef::Exceptions::ValidationFailed
549
+ # validation_options strips :sensitive before it ever reaches the
550
+ # validators below, so they have no way to redact the value themselves --
551
+ # do it here instead of leaking it in the exception message.
552
+ raise unless sensitive?
553
+
554
+ raise Chef::Exceptions::ValidationFailed,
555
+ "Property #{name}'s value does not pass validation. The value has been suppressed because 'sensitive' is set to true on this property."
546
556
  end
547
557
 
548
558
  #
@@ -61,7 +61,6 @@ class Chef
61
61
  val.strip! if val
62
62
  case key.downcase
63
63
  when "primarygroupid"
64
- new_resource.gid(val) unless new_resource.gid
65
64
  current_resource.gid(val)
66
65
  when "groupmembership"
67
66
  current_resource.members(val.split(" "))
@@ -99,10 +98,15 @@ class Chef
99
98
  end
100
99
 
101
100
  def set_gid
102
- new_resource.gid(get_free_gid) if [nil, ""].include? new_resource.gid
103
- raise(Chef::Exceptions::Group, "gid is already in use") if gid_used?(new_resource.gid)
104
-
105
- safe_dscl("create", "/Groups/#{new_resource.group_name}", "PrimaryGroupID", new_resource.gid)
101
+ # Resolve the gid into a local so that the desired state on the new
102
+ # resource is left alone. Memoizing a free gid back onto the resource
103
+ # would mean a reused resource object gets the same gid every time
104
+ # rather than a fresh free one.
105
+ gid = new_resource.gid
106
+ gid = get_free_gid if [nil, ""].include?(gid)
107
+ raise(Chef::Exceptions::Group, "gid is already in use") if gid_used?(gid)
108
+
109
+ safe_dscl("create", "/Groups/#{new_resource.group_name}", "PrimaryGroupID", gid)
106
110
  end
107
111
 
108
112
  def set_members
@@ -111,6 +111,11 @@ class Chef
111
111
  end
112
112
 
113
113
  def group_gid_match?
114
+ # No gid requested means no desired gid, so whatever the group already
115
+ # has is a match. Providers must not backfill new_resource.gid from the
116
+ # current state to make this comparison work.
117
+ return true if new_resource.gid.nil?
118
+
114
119
  new_resource.gid.to_s == current_resource.gid.to_s
115
120
  end
116
121
 
@@ -26,7 +26,7 @@ class Chef
26
26
  class Mount
27
27
  # Mount Solaris File systems
28
28
  class Solaris < Chef::Provider::Mount
29
- provides :mount, platform_family: "solaris_based"
29
+ provides :mount, platform_family: "solaris_based", target_mode: true
30
30
 
31
31
  extend Forwardable
32
32
 
@@ -52,21 +52,21 @@ class Chef
52
52
 
53
53
  def define_resource_requirements
54
54
  requirements.assert(:mount, :remount) do |a|
55
- a.assertion { !device_should_exist? || ::File.exist?(device) }
55
+ a.assertion { !device_should_exist? || ::TargetIO::File.exist?(device) }
56
56
  a.failure_message(Chef::Exceptions::Mount, "Device #{device} does not exist")
57
57
  a.whyrun("Assuming device #{device} would have been created")
58
58
  end
59
59
 
60
60
  unless fsck_device == "-"
61
61
  requirements.assert(:mount, :remount) do |a|
62
- a.assertion { ::File.exist?(fsck_device) }
62
+ a.assertion { ::TargetIO::File.exist?(fsck_device) }
63
63
  a.failure_message(Chef::Exceptions::Mount, "Device #{fsck_device} does not exist")
64
64
  a.whyrun("Assuming device #{fsck_device} would have been created")
65
65
  end
66
66
  end
67
67
 
68
68
  requirements.assert(:mount, :remount) do |a|
69
- a.assertion { ::File.exist?(mount_point) }
69
+ a.assertion { ::TargetIO::File.exist?(mount_point) }
70
70
  a.failure_message(Chef::Exceptions::Mount, "Mount point #{mount_point} does not exist")
71
71
  a.whyrun("Assuming mount point #{mount_point} would have been created")
72
72
  end
@@ -118,10 +118,6 @@ class Chef
118
118
  end
119
119
  end
120
120
 
121
- def etc_tempfile
122
- yield Tempfile.open("vfstab", "/etc")
123
- end
124
-
125
121
  def mount_options_unchanged?
126
122
  new_options = native_options(options)
127
123
  current_options = native_options(current_resource.nil? ? nil : current_resource.options)
@@ -172,7 +168,7 @@ class Chef
172
168
  enabled = false
173
169
  pass = false
174
170
  fstype = options = nil
175
- ::File.foreach(VFSTAB) do |line|
171
+ ::TargetIO::File.foreach(VFSTAB) do |line|
176
172
  case line
177
173
  when /^[#\s]/
178
174
  next
@@ -213,12 +209,8 @@ class Chef
213
209
  end
214
210
 
215
211
  def vfstab_write(contents)
216
- etc_tempfile do |f|
212
+ ::TargetIO::File.open(VFSTAB, "w") do |f|
217
213
  f.write(contents.join(""))
218
- f.close
219
- # move, preserving modes of destination file
220
- mover = Chef::FileContentManagement::Deploy.strategy(true)
221
- mover.deploy(f.path, VFSTAB)
222
214
  end
223
215
  end
224
216
 
@@ -233,7 +225,7 @@ class Chef
233
225
  def delete_vfstab_entry
234
226
  contents = []
235
227
  found = false
236
- ::File.readlines(VFSTAB).reverse_each do |line|
228
+ ::TargetIO::File.readlines(VFSTAB).reverse_each do |line|
237
229
  if !found && line =~ /^#{device_regex}\s+\S+\s+#{Regexp.escape(mount_point)}/
238
230
  found = true
239
231
  logger.trace("#{new_resource} is removed from vfstab")
@@ -245,7 +237,7 @@ class Chef
245
237
  end
246
238
 
247
239
  def merge_vfstab_entry
248
- contents = ::File.readlines(VFSTAB)
240
+ contents = ::TargetIO::File.readlines(VFSTAB)
249
241
  contents[-1].chomp!
250
242
  contents << vfstab_entry
251
243
  end
@@ -262,8 +254,8 @@ class Chef
262
254
  end
263
255
 
264
256
  def device_regex
265
- if ::File.symlink?(device)
266
- "(?:#{Regexp.escape(device)}|#{Regexp.escape(::File.expand_path(::File.readlink(device), ::File.dirname(device)))})"
257
+ if ::TargetIO::File.symlink?(device)
258
+ "(?:#{Regexp.escape(device)}|#{Regexp.escape(::File.expand_path(::TargetIO::File.readlink(device), ::File.dirname(device)))})"
267
259
  else
268
260
  Regexp.escape(device)
269
261
  end
@@ -395,8 +395,8 @@ class Chef
395
395
  Chef::Log.debug("Choco List Command: #{cmd}")
396
396
 
397
397
  raw = parse_list_output(*cmd)
398
- raw.keys.each_with_object({}) do |name, available|
399
- available[name] = desired_name_versions[name] || raw[name]
398
+ raw.keys.to_h do |name|
399
+ [name, desired_name_versions[name] || raw[name]]
400
400
  end
401
401
  end
402
402
  @@choco_available_packages[new_resource.list_options].merge!(available_versions)
@@ -72,8 +72,7 @@ class Chef
72
72
  # and which packages can be upgrades. We do this by checking if brew_info has an entry
73
73
  # via the installed_version helper.
74
74
  def upgrade_package(names, versions)
75
- upgrade_pkgs = names.select { |x| installed_version(x) }
76
- install_pkgs = names.reject { |x| installed_version(x) }
75
+ upgrade_pkgs, install_pkgs = names.partition { |x| installed_version(x) }
77
76
 
78
77
  brew_cmd_output("upgrade", options, upgrade_pkgs) unless upgrade_pkgs.empty?
79
78
  brew_cmd_output("install", options, install_pkgs) unless install_pkgs.empty?
@@ -198,7 +197,7 @@ class Chef
198
197
  # the package provider can magically handle that
199
198
  shell_out_cmd = options[:allow_failure] ? :shell_out : :shell_out!
200
199
 
201
- output = send(shell_out_cmd, homebrew_bin_path, *command, user: homebrew_uid, environment: { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
200
+ output = send(shell_out_cmd, homebrew_bin_path, *command, user: homebrew_uid, timeout: new_resource.timeout, environment: { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
202
201
  output.stdout.chomp
203
202
  end
204
203
  end
@@ -79,7 +79,6 @@ class Chef
79
79
 
80
80
  if pkginfo.exitstatus != 0
81
81
  pkginfo.stderr.each_line do |line|
82
- # cspell:disable-next-line
83
82
  if /[Uu]nqualified atom .*match.* multiple/.match?(line)
84
83
  raise_error_for_query("matched multiple packages (please specify a category):\n#{pkginfo.inspect}")
85
84
  end
@@ -116,7 +116,6 @@ class Chef
116
116
  end
117
117
 
118
118
  def is_arch?(arch)
119
- # cspell:disable-next
120
119
  arches = %w{aarch64 alpha alphaev4 alphaev45 alphaev5 alphaev56 alphaev6 alphaev67 alphaev68 alphaev7 alphapca56 armv5tejl armv5tel armv5tl armv6l armv7l armv8l armv6hl armv7hl armv7hnl armv8hl i386 athlon geode i386 i486 i586 i686 ia64 mips mipsel mips64 mips64el noarch ppc ppc64 ppc64iseries ppc64p7 ppc64pseries ppc64le riscv32 riscv64 riscv128 s390 s390x sh3 sh4 sh4a sparc sparc64 sparc64v sparcv8 sparcv9 sparcv9v x86_64 amd64 ia32e}
121
120
  arches.include?(arch)
122
121
  end
@@ -59,15 +59,15 @@ class Chef
59
59
  a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.",
60
60
  "Assigning temporary priorities to continue.",
61
61
  "If this service is not properly installed prior to this point, this will fail."] do
62
- temp_priorities = { "6" => [:stop, "20"],
63
- "0" => [:stop, "20"],
64
- "1" => [:stop, "20"],
65
- "2" => [:start, "20"],
66
- "3" => [:start, "20"],
67
- "4" => [:start, "20"],
68
- "5" => [:start, "20"] }
69
- current_resource.priority(temp_priorities)
70
- end
62
+ temp_priorities = { "6" => [:stop, "20"],
63
+ "0" => [:stop, "20"],
64
+ "1" => [:stop, "20"],
65
+ "2" => [:start, "20"],
66
+ "3" => [:start, "20"],
67
+ "4" => [:start, "20"],
68
+ "5" => [:start, "20"] }
69
+ current_resource.priority(temp_priorities)
70
+ end
71
71
  end
72
72
  end
73
73
 
@@ -176,6 +176,10 @@ class Chef
176
176
  description: "Determines whether to rebuild the APT package cache.",
177
177
  default: true, desired_state: false
178
178
 
179
+ property :cache_rebuild_ignore_failure, [TrueClass, FalseClass],
180
+ description: "Determines whether to fail the run if rebuilding the APT package cache fails.",
181
+ default: true, desired_state: false
182
+
179
183
  property :options, [String, Array],
180
184
  description: "Additional options to set for the repository",
181
185
  default: [], coerce: proc { |x| Array(x) }
@@ -554,7 +558,7 @@ class Chef
554
558
  end
555
559
 
556
560
  apt_update new_resource.name do
557
- ignore_failure true
561
+ ignore_failure new_resource.cache_rebuild_ignore_failure
558
562
  action :nothing
559
563
  end
560
564