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.
- checksums.yaml +4 -4
- data/Gemfile +12 -17
- data/README.md +6 -1
- data/Rakefile +11 -0
- data/chef-universal-mingw-ucrt.gemspec +9 -2
- data/chef.gemspec +19 -9
- data/lib/chef/application/client.rb +7 -1
- data/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +1 -1
- data/lib/chef/client.rb +22 -4
- data/lib/chef/compliance/runner.rb +19 -1
- data/lib/chef/cookbook/gem_installer.rb +1 -1
- data/lib/chef/cookbook_uploader.rb +1 -1
- data/lib/chef/dsl/rest_resource.rb +63 -12
- data/lib/chef/file_access_control/windows.rb +6 -0
- data/lib/chef/file_access_control.rb +12 -1
- data/lib/chef/handler/slow_report.rb +3 -4
- data/lib/chef/licensing.rb +26 -6
- data/lib/chef/node.rb +13 -1
- data/lib/chef/policy_builder/expand_node_object.rb +12 -1
- data/lib/chef/policy_builder/policyfile.rb +12 -0
- data/lib/chef/property.rb +1 -1
- data/lib/chef/provider/file/content.rb +3 -2
- data/lib/chef/provider/file.rb +5 -2
- data/lib/chef/provider/ifconfig/redhat.rb +1 -1
- data/lib/chef/provider/package/chocolatey.rb +78 -19
- data/lib/chef/provider/package/dnf/dnf_helper.py +355 -65
- data/lib/chef/provider/package/dnf/python_helper.rb +6 -3
- data/lib/chef/provider/package/dnf.rb +24 -5
- data/lib/chef/provider/package/rubygems.rb +25 -2
- data/lib/chef/provider/package/yum.rb +1 -1
- data/lib/chef/provider/package/yum_tm.rb +1 -1
- data/lib/chef/resource/_rest_resource.rb +4 -2
- data/lib/chef/resource/build_essential.rb +10 -1
- data/lib/chef/resource/chef_client_hab_ca_cert.rb +1 -1
- data/lib/chef/resource/chocolatey_installer.rb +1 -1
- data/lib/chef/resource/execute.rb +0 -15
- data/lib/chef/resource/helpers/path_helpers.rb +5 -3
- data/lib/chef/resource/yum_package.rb +1 -1
- data/lib/chef/target_io/support.rb +1 -1
- data/lib/chef/target_io/train/dir.rb +1 -1
- data/lib/chef/target_io/train/file.rb +5 -5
- data/lib/chef/target_io/train/fileutils.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/version.rb +17 -16
- 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.
|
|
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
|
-
|
|
27
|
+
content = @new_resource.content
|
|
28
|
+
if content
|
|
28
29
|
tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile
|
|
29
|
-
tempfile.write(
|
|
30
|
+
tempfile.write(content)
|
|
30
31
|
tempfile.close
|
|
31
32
|
tempfile
|
|
32
33
|
else
|
data/lib/chef/provider/file.rb
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
463
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
{}
|