chef 19.1.164 → 19.3.14

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -17
  3. data/README.md +6 -1
  4. data/Rakefile +11 -0
  5. data/chef-universal-mingw-ucrt.gemspec +9 -2
  6. data/chef.gemspec +19 -9
  7. data/lib/chef/application/client.rb +7 -1
  8. data/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +1 -1
  9. data/lib/chef/client.rb +22 -4
  10. data/lib/chef/compliance/runner.rb +19 -1
  11. data/lib/chef/cookbook/gem_installer.rb +1 -1
  12. data/lib/chef/cookbook_uploader.rb +1 -1
  13. data/lib/chef/dsl/rest_resource.rb +63 -12
  14. data/lib/chef/file_access_control/windows.rb +6 -0
  15. data/lib/chef/file_access_control.rb +12 -1
  16. data/lib/chef/handler/slow_report.rb +3 -4
  17. data/lib/chef/licensing.rb +26 -6
  18. data/lib/chef/node.rb +13 -1
  19. data/lib/chef/policy_builder/expand_node_object.rb +12 -1
  20. data/lib/chef/policy_builder/policyfile.rb +12 -0
  21. data/lib/chef/property.rb +1 -1
  22. data/lib/chef/provider/file/content.rb +3 -2
  23. data/lib/chef/provider/file.rb +5 -2
  24. data/lib/chef/provider/ifconfig/redhat.rb +1 -1
  25. data/lib/chef/provider/package/chocolatey.rb +78 -19
  26. data/lib/chef/provider/package/dnf/dnf_helper.py +355 -65
  27. data/lib/chef/provider/package/dnf/python_helper.rb +6 -3
  28. data/lib/chef/provider/package/dnf.rb +24 -5
  29. data/lib/chef/provider/package/rubygems.rb +25 -2
  30. data/lib/chef/provider/package/yum.rb +1 -1
  31. data/lib/chef/provider/package/yum_tm.rb +1 -1
  32. data/lib/chef/resource/_rest_resource.rb +4 -2
  33. data/lib/chef/resource/build_essential.rb +10 -1
  34. data/lib/chef/resource/chef_client_hab_ca_cert.rb +1 -1
  35. data/lib/chef/resource/chocolatey_installer.rb +1 -1
  36. data/lib/chef/resource/execute.rb +0 -15
  37. data/lib/chef/resource/helpers/path_helpers.rb +5 -3
  38. data/lib/chef/resource/yum_package.rb +1 -1
  39. data/lib/chef/target_io/support.rb +1 -1
  40. data/lib/chef/target_io/train/dir.rb +1 -1
  41. data/lib/chef/target_io/train/file.rb +5 -5
  42. data/lib/chef/target_io/train/fileutils.rb +1 -1
  43. data/lib/chef/version.rb +1 -1
  44. data/lib/chef/win32/version.rb +17 -16
  45. metadata +39 -15
@@ -515,6 +515,8 @@ class Chef
515
515
  # @api private
516
516
  def api_service
517
517
  @api_service ||= Chef::ServerAPI.new(config[:chef_server_url],
518
+ client_name: api_client_name,
519
+ signing_key_filename: api_client_key,
518
520
  version_class: Chef::CookbookManifestVersions)
519
521
  end
520
522
 
@@ -523,6 +525,16 @@ class Chef
523
525
  Chef::Config
524
526
  end
525
527
 
528
+ # @api private
529
+ def api_client_name
530
+ config[:api_client_name] || config[:node_name]
531
+ end
532
+
533
+ # @api private
534
+ def api_client_key
535
+ config[:api_client_key] || config[:client_key]
536
+ end
537
+
526
538
  # Indicates whether the policy is temporary, which means an
527
539
  # override_runlist was provided. Chef::Client uses this to decide whether
528
540
  # to do the final node save at the end of the run or not.
data/lib/chef/property.rb CHANGED
@@ -698,7 +698,7 @@ class Chef
698
698
  # Weeding out class methods avoids unnecessary deprecations such Chef::Resource
699
699
  # defining a `name` property when there's an already-existing `name` method
700
700
  # for a Module.
701
- return false unless declared_in.instance_methods.include?(name)
701
+ return false unless declared_in.method_defined?(name)
702
702
 
703
703
  # Only emit deprecations for some well-known classes. This will still
704
704
  # allow more advanced users to subclass their own custom resources and
@@ -24,9 +24,10 @@ class Chef
24
24
  class File
25
25
  class Content < Chef::FileContentManagement::ContentBase
26
26
  def file_for_provider
27
- if @new_resource.content
27
+ content = @new_resource.content
28
+ if content
28
29
  tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile
29
- tempfile.write(@new_resource.content)
30
+ tempfile.write(content)
30
31
  tempfile.close
31
32
  tempfile
32
33
  else
@@ -197,7 +197,7 @@ class Chef
197
197
  # be overridden in subclasses.
198
198
  def managing_content?
199
199
  return true if new_resource.checksum
200
- return true if !new_resource.content.nil? && @action != :create_if_missing
200
+ return true if new_resource.property_is_set?(:content) && @action != :create_if_missing
201
201
 
202
202
  false
203
203
  end
@@ -472,11 +472,14 @@ class Chef
472
472
  end
473
473
 
474
474
  def load_resource_attributes_from_file(resource)
475
- if ChefUtils.windows?
475
+ if ChefUtils.windows? && !Chef::Config.target_mode?
476
476
  # This is a work around for CHEF-3554.
477
477
  # OC-6534: is tracking the real fix for this workaround.
478
478
  # Add support for Windows equivalent, or implicit resource
479
479
  # reporting won't work for Windows.
480
+ # In target mode on Windows, we still read remote attributes via
481
+ # TargetIO (ScanAccessControl is TargetIO-aware), so idempotency
482
+ # checks work correctly when targeting a remote Linux host.
480
483
  return
481
484
  end
482
485
 
@@ -22,7 +22,7 @@ class Chef
22
22
  class Provider
23
23
  class Ifconfig
24
24
  class Redhat < Chef::Provider::Ifconfig
25
- provides :ifconfig, platform_family: "fedora_derived", target_mode: true
25
+ provides :ifconfig, platform_family: %w{fedora rhel amazon}, target_mode: true
26
26
 
27
27
  def initialize(new_resource, run_context)
28
28
  super(new_resource, run_context)
@@ -257,7 +257,8 @@ class Chef
257
257
  @choco_install_path ||= begin
258
258
  result = powershell_exec!(PATHFINDING_POWERSHELL_COMMAND).result
259
259
  result = "" if result.empty?
260
- result
260
+ # Ensure consistent Windows path separators
261
+ result.empty? ? result : result.tr("/", "\\")
261
262
  end
262
263
  end
263
264
 
@@ -459,8 +460,10 @@ class Chef
459
460
  def get_local_pkg_dirs(base_dir)
460
461
  return [] unless Dir.exist?(base_dir)
461
462
 
462
- Dir.entries(base_dir).select do |dir|
463
- ::File.directory?(::File.join(base_dir, dir)) && !dir.start_with?(".")
463
+ with_file_lock_retry("reading chocolatey package directories") do
464
+ Dir.entries(base_dir).select do |dir|
465
+ ::File.directory?(::File.join(base_dir, dir)) && !dir.start_with?(".")
466
+ end
464
467
  end
465
468
  end
466
469
 
@@ -496,6 +499,60 @@ class Chef
496
499
  args
497
500
  end
498
501
 
502
+ # Wait for chocolatey to release file locks after package operations
503
+ # @param names [Array<String>] package names that were just installed/upgraded
504
+ def wait_for_chocolatey_lock_release(names)
505
+ return if names.empty?
506
+
507
+ Chef::Log.debug("Waiting for chocolatey to release file locks for packages: #{names.join(", ")}")
508
+
509
+ # Check for .chocolateyPending files and wait for them to be released
510
+ names.each do |name|
511
+ pending_file = ::File.join(choco_lib_path, name.downcase, ".chocolateyPending")
512
+ if ::File.exist?(pending_file)
513
+ with_file_lock_retry("waiting for .chocolateyPending file release: #{pending_file}") do
514
+ # Try to open the file exclusively - this will fail if it's locked
515
+ ::File.open(pending_file, "r") do |f|
516
+ f.flock(::File::LOCK_EX | ::File::LOCK_NB) or raise Errno::EAGAIN
517
+ end
518
+ end
519
+ end
520
+ end
521
+ end
522
+
523
+ # Retry file operations that might encounter chocolatey process file locks
524
+ # @param operation_desc [String] description of the operation for logging
525
+ # @param max_retries [Integer] maximum number of retry attempts
526
+ # @param base_delay [Float] base delay between retries in seconds
527
+ def with_file_lock_retry(operation_desc, max_retries: 5, base_delay: 0.5)
528
+ retries = 0
529
+ begin
530
+ yield
531
+ rescue Errno::EACCES, Errno::EBUSY, Errno::EAGAIN, Errno::ENOENT => e
532
+ if retries < max_retries && file_lock_error?(e)
533
+ retries += 1
534
+ delay = base_delay * (2**(retries - 1)) # exponential backoff
535
+ Chef::Log.debug("Chocolatey file lock detected during #{operation_desc}, retrying in #{delay}s (attempt #{retries}/#{max_retries}): #{e.message}")
536
+ sleep(delay)
537
+ retry
538
+ else
539
+ Chef::Log.warn("Failed #{operation_desc} after #{retries} retries: #{e.message}")
540
+ raise e
541
+ end
542
+ end
543
+ end
544
+
545
+ # Check if the error is related to file locking by chocolatey processes
546
+ # @param error [Exception] the exception to check
547
+ # @return [Boolean] true if it's a chocolatey file lock related error
548
+ def file_lock_error?(error)
549
+ error.message&.include?("being used by another process") ||
550
+ error.message&.include?("chocolateyPending") ||
551
+ error.is_a?(Errno::EACCES) ||
552
+ error.is_a?(Errno::EBUSY) ||
553
+ error.is_a?(Errno::EAGAIN)
554
+ end
555
+
499
556
  # Fetch the local package versions from chocolatey
500
557
  def fetch_package_versions(base_dir, target_dirs, targets)
501
558
  pkg_versions = {}
@@ -511,25 +568,27 @@ class Chef
511
568
  # Grab the locally installed packages from the nupkg list
512
569
  # rather than shelling out to chocolatey
513
570
  def get_pkg_data(path)
514
- t = ::File.join(path, "*.nupkg").gsub("\\", "/")
515
- targets = Dir.glob(t)
516
-
517
- # Extract package version from the first nuspec file in this nupkg
518
- targets.each do |target|
519
- Zip::File.open(target) do |zip_file|
520
- zip_file.each do |entry|
521
- next unless entry.name.end_with?(".nuspec")
522
-
523
- f = entry.get_input_stream
524
- doc = REXML::Document.new(f.read.to_s)
525
- f.close
526
- id = doc.elements["package/metadata/id"]
527
- version = doc.elements["package/metadata/version"]
528
- return { id.text.to_s.downcase => version.text } if id && version
571
+ with_file_lock_retry("get package data for #{path}") do
572
+ t = ::File.join(path, "*.nupkg")
573
+ targets = Dir.glob(t)
574
+
575
+ # Extract package version from the first nuspec file in this nupkg
576
+ targets.each do |target|
577
+ Zip::File.open(target) do |zip_file|
578
+ zip_file.each do |entry|
579
+ next unless entry.name.end_with?(".nuspec")
580
+
581
+ f = entry.get_input_stream
582
+ doc = REXML::Document.new(f.read.to_s)
583
+ f.close
584
+ id = doc.elements["package/metadata/id"]
585
+ version = doc.elements["package/metadata/version"]
586
+ return { id.text.to_s.downcase => version.text } if id && version
587
+ end
529
588
  end
530
589
  end
590
+ {}
531
591
  end
532
- {}
533
592
  rescue StandardError => e
534
593
  Chef::Log.warn("Failed to get package info for #{path}: #{e}")
535
594
  {}