diff options
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/mixin/why_run.rb | 10 | ||||
-rw-r--r-- | lib/chef/provider.rb | 2 | ||||
-rw-r--r-- | lib/chef/provider/mount/linux.rb | 18 | ||||
-rw-r--r-- | lib/chef/provider/mount/mount.rb | 2 | ||||
-rw-r--r-- | lib/chef/provider/package.rb | 81 | ||||
-rw-r--r-- | lib/chef/provider/package/dnf.rb | 2 | ||||
-rw-r--r-- | lib/chef/provider/package/powershell.rb | 23 | ||||
-rw-r--r-- | lib/chef/resource/chef_client_config.rb | 23 | ||||
-rw-r--r-- | lib/chef/resource/dnf_package.rb | 10 | ||||
-rw-r--r-- | lib/chef/resource/support/client.erb | 7 | ||||
-rw-r--r-- | lib/chef/version.rb | 2 |
11 files changed, 132 insertions, 48 deletions
diff --git a/lib/chef/mixin/why_run.rb b/lib/chef/mixin/why_run.rb index efe327168e..357c4a655d 100644 --- a/lib/chef/mixin/why_run.rb +++ b/lib/chef/mixin/why_run.rb @@ -242,8 +242,12 @@ class Chef end end - def initialize(resource, run_context) - @resource, @run_context = resource, run_context + attr_accessor :action + + def initialize(resource, run_context, action) + @resource = resource + @run_context = run_context + @action = action @assertions = Hash.new { |h, k| h[k] = [] } @blocked_actions = [] end @@ -305,6 +309,8 @@ class Chef # "You don't have sufficient privileges to delete #{@new_resource.path}") # end def assert(*actions) + return unless actions.include?(action.to_sym) || actions.include?(:all_actions) + assertion = Assertion.new yield assertion actions.each { |action| @assertions[action] << assertion } diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb index e7d7ca84ff..80c58c09ee 100644 --- a/lib/chef/provider.rb +++ b/lib/chef/provider.rb @@ -269,7 +269,7 @@ class Chef end def requirements - @requirements ||= ResourceRequirements.new(@new_resource, run_context) + @requirements ||= ResourceRequirements.new(@new_resource, run_context, action || new_resource.action) end def description(description = "NOT_PASSED") diff --git a/lib/chef/provider/mount/linux.rb b/lib/chef/provider/mount/linux.rb index 382e37d41a..83fbfab957 100644 --- a/lib/chef/provider/mount/linux.rb +++ b/lib/chef/provider/mount/linux.rb @@ -29,10 +29,16 @@ class Chef # "findmnt" outputs the mount points with volume. # Convert the mount_point of the resource to a real path in case it # contains symlinks in its parents dirs. + def loop_mount_points + # get loop_mount_points only if not initialized earlier + @loop_mount_points ||= shell_out!("losetup -a").stdout + + rescue Errno::ENOENT + @loop_mount_points = "" + end def mounted? mounted = false - real_mount_point = if ::File.exists? @new_resource.mount_point ::File.realpath(@new_resource.mount_point) else @@ -45,6 +51,14 @@ class Chef when /\A#{Regexp.escape(real_mount_point)}\s+#{device_mount_regex}\s/ mounted = true logger.trace("Special device #{device_logstring} mounted as #{real_mount_point}") + # Permalink for loop type devices mount points https://rubular.com/r/a0bS4p2RvXsGxx + when %r{\A#{Regexp.escape(real_mount_point)}\s+\/dev\/loop+[0-9]+\s} + loop_mount_points.each_line do |mount_point| + if mount_point.include? device_real + mounted = true + break + end + end # Permalink for multiple devices mounted to the same mount point(i.e. '/proc') https://rubular.com/r/a356yzspU7N9TY when %r{\A#{Regexp.escape(real_mount_point)}\s+([/\w])+\s} mounted = false @@ -64,4 +78,4 @@ class Chef end end end -end +end
\ No newline at end of file diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb index 802ee11c23..2bc9d2c78f 100644 --- a/lib/chef/provider/mount/mount.rb +++ b/lib/chef/provider/mount/mount.rb @@ -279,4 +279,4 @@ class Chef end end end -end +end
\ No newline at end of file diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb index 65d2254258..82d7ed00cf 100644 --- a/lib/chef/provider/package.rb +++ b/lib/chef/provider/package.rb @@ -438,47 +438,81 @@ class Chef @target_version_array ||= begin target_version_array = [] - each_package do |package_name, new_version, current_version, candidate_version| + each_package do |package_name, new_version, current_version, candidate_version, magic_version| case action when :upgrade - if current_version.nil? - # with use_magic_version there may be a package installed, but it fails the user's - # requested new_resource.version constraints + if version_equals?(current_version, new_version) + # This is a short-circuit (mostly for the rubygems provider) to avoid needing to + # expensively query the candidate_version which must come later. This only checks + # exact matching, the check for fuzzy matching is later. + logger.trace("#{new_resource} #{package_name} #{new_version} is already installed") + target_version_array.push(nil) + elsif current_version.nil? + # This is a simple check to see if we have any currently installed version at all, this is + # safe to do before the allow_downgrade check so we check this before. logger.trace("#{new_resource} has no existing installed version. Installing install #{candidate_version}") target_version_array.push(candidate_version) - elsif !use_magic_version? && version_equals?(current_version, new_version) - # this is a short-circuit (mostly for the rubygems provider) to avoid needing to expensively query the candidate_version which must come later - logger.trace("#{new_resource} #{package_name} #{new_version} is already installed") + elsif !allow_downgrade && version_compare(current_version, candidate_version) == 1 + # This check for downgrading when allow_downgrade is false uses the current_version rather + # than the magic_version since we never want to downgrade even if the constraints are not met + # if the version is higher. This check does use the candidate_version and unlazies this so + # there will a perf hit on idempotent use when allow_downgrade is false which is unavoidable. + logger.trace("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)") target_version_array.push(nil) + elsif magic_version.nil? + # This is the check for fuzzy matching of the installed_version, where if the installed version + # does not match the desired version constraints (but is not an exact match) then we need to + # install the candidate_version (this must come after the allow_downgrade check) + logger.trace("#{new_resource} has an installed version that does not match the version constraint. Installing install #{candidate_version}") + target_version_array.push(candidate_version) elsif candidate_version.nil? + # This check necessarily unlazies the candidate_version and may be expensive (connecting to + # rubygems.org or whatever). It comes as late as possible. logger.trace("#{new_resource} #{package_name} has no candidate_version to upgrade to") target_version_array.push(nil) elsif version_equals?(current_version, candidate_version) + # This check sees if the candidate_version is already installed or if we should upgrade/update the + # package. This is the normal idempotent behavior of :upgrade and is inherently expensive due to + # unlazying the candidate_version. To prevent the perf hit the version may be specified with a full + # version constraint. Then the cookbook can roll the version forward and use :upgrade to force version + # pinning. logger.trace("#{new_resource} #{package_name} #{candidate_version} is already installed") target_version_array.push(nil) - elsif !allow_downgrade && version_compare(current_version, candidate_version) == 1 - logger.trace("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)") - target_version_array.push(nil) else - logger.trace("#{new_resource} #{package_name} is out of date, will upgrade to #{candidate_version}") + logger.trace("#{new_resource} #{package_name} is out of date, will update to #{candidate_version}") target_version_array.push(candidate_version) end when :install - if new_version && !use_magic_version? + if current_version && new_version && !allow_downgrade && version_compare(current_version, new_version) == 1 + # This is the idempotency guard for downgrades when downgrades are not allowed. This should perhaps raise + # an exception since we were told to install an exact package version but we are silently refusing to do so + # because a higher version is already installed. Maybe we need a flag for users to apply their preferred + # declarative philosophy? This has to come early and outside of the two code paths below. + logger.warn("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{new_version}. Skipping...)") + target_version_array.push(nil) + elsif new_version && !use_magic_version? + # This is for "non magic version using" subclasses to do comparisons between the current_version and the + # desired new_version. XXX: If we converted this to current_version_requirement_satisfied? and made it specific + # to the current version check and then eliminated the magic_version, we might be able to eliminate separate codepaths + # here, and eliminate the semantic confusion around the magic_version? if version_requirement_satisfied?(current_version, new_version) logger.trace("#{new_resource} #{package_name} #{current_version} satisfies #{new_version} requirement") target_version_array.push(nil) - elsif current_version && !allow_downgrade && version_compare(current_version, new_version) == 1 - logger.warn("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{new_version}. Skipping...)") - target_version_array.push(nil) else + # XXX: some subclasses seem to depend on this behavior where the new_version can be different from the + # candidate_version and we install the new_version, it seems like the candidate_version should be fixed to + # be resolved correctly to the new_version for those providers. although it may just be unit test bugs. + # it would be more correct to use the candidate_version here, but then it needs to be the correctly resolved + # candidate_version against the new_version constraint. logger.trace("#{new_resource} #{package_name} #{current_version} needs updating to #{new_version}") target_version_array.push(new_version) end - elsif current_version.nil? - # with use_magic_version there may be a package installed, but it fails the user's - # requested new_resource.version constraints + elsif magic_version.nil? + # This is for when we have a "magic version using" subclass and where the installed version does not match the + # constraint specified in the new_version, so we need to upgrade to the candidate_version. This is the only + # codepath in the :install branch which references the candidate_version so it is slow, but it is the path where + # we need to do work anyway. XXX: should we check for candidate_version.nil? somewhere around here? logger.trace("#{new_resource} #{package_name} not installed, installing #{candidate_version}") target_version_array.push(candidate_version) else @@ -512,8 +546,8 @@ class Chef @packages_missing_candidates ||= begin missing = [] - each_package do |package_name, new_version, current_version, candidate_version| - missing.push(package_name) if current_version.nil? && candidate_version.nil? + each_package do |package_name, new_version, current_version, candidate_version, magic_version| + missing.push(package_name) if magic_version.nil? && candidate_version.nil? end missing end @@ -536,7 +570,7 @@ class Chef @forced_packages_missing_candidates ||= begin missing = [] - each_package do |package_name, new_version, current_version, candidate_version| + each_package do |package_name, new_version, current_version, candidate_version, magic_version| next if new_version.nil? || current_version.nil? if use_magic_version? @@ -559,9 +593,10 @@ class Chef def each_package package_name_array.each_with_index do |package_name, i| candidate_version = candidate_version_array[i] - current_version = use_magic_version? ? magic_version[i] : current_version_array[i] + current_version = current_version_array[i] + magic_version = use_magic_version? ? magic_version_array[i] : current_version_array[i] new_version = new_version_array[i] - yield package_name, new_version, current_version, candidate_version + yield package_name, new_version, current_version, candidate_version, magic_version end end diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb index 5c74ad0414..67bf24a411 100644 --- a/lib/chef/provider/package/dnf.rb +++ b/lib/chef/provider/package/dnf.rb @@ -98,7 +98,7 @@ class Chef end end - def magic_version + def magic_version_array package_name_array.each_with_index.map do |pkg, i| magical_version(i).version_with_arch end diff --git a/lib/chef/provider/package/powershell.rb b/lib/chef/provider/package/powershell.rb index 1c123d7952..2fe6cc2abc 100644 --- a/lib/chef/provider/package/powershell.rb +++ b/lib/chef/provider/package/powershell.rb @@ -17,13 +17,13 @@ require_relative "../package" require_relative "../../resource/powershell_package" -require_relative "../../mixin/powershell_out" +require_relative "../../mixin/powershell_exec" class Chef class Provider class Package class Powershell < Chef::Provider::Package - include Chef::Mixin::PowershellOut + include Chef::Mixin::PowershellExec provides :powershell_package @@ -54,9 +54,9 @@ class Chef # Installs the package specified with the version passed else latest version will be installed def install_package(names, versions) names.each_with_index do |name, index| - cmd = powershell_out(build_powershell_package_command("Install-Package '#{name}'", versions[index]), timeout: new_resource.timeout) + cmd = powershell_exec(build_powershell_package_command("Install-Package '#{name}'", versions[index]), timeout: new_resource.timeout) next if cmd.nil? - raise Chef::Exceptions::PowershellCmdletException, "Failed to install package due to catalog signing error, use skip_publisher_check to force install" if /SkipPublisherCheck/.match?(cmd.stderr) + raise Chef::Exceptions::PowershellCmdletException, "Failed to install package due to catalog signing error, use skip_publisher_check to force install" if /SkipPublisherCheck/.match?(cmd.error) end end @@ -64,11 +64,12 @@ class Chef def remove_package(names, versions) names.each_with_index do |name, index| if versions && !versions[index].nil? - powershell_out(build_powershell_package_command("Uninstall-Package '#{name}'", versions[index]), timeout: new_resource.timeout) + powershell_exec(build_powershell_package_command("Uninstall-Package '#{name}'", versions[index]), timeout: new_resource.timeout) else version = "0" until version.empty? - version = powershell_out(build_powershell_package_command("Uninstall-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip + version = powershell_exec(build_powershell_package_command("Uninstall-Package '#{name}'"), timeout: new_resource.timeout).result + version = version.strip if version.respond_to?(:strip) unless version.empty? logger.info("Removed package '#{name}' with version #{version}") end @@ -82,13 +83,14 @@ class Chef versions = [] new_resource.package_name.each_with_index do |name, index| version = if new_resource.version && !new_resource.version[index].nil? - powershell_out(build_powershell_package_command("Find-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip + powershell_exec(build_powershell_package_command("Find-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).result else - powershell_out(build_powershell_package_command("Find-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip + powershell_exec(build_powershell_package_command("Find-Package '#{name}'"), timeout: new_resource.timeout).result end if version.empty? version = nil end + version = version.strip if version.respond_to?(:strip) versions.push(version) end versions @@ -99,13 +101,14 @@ class Chef version_list = [] new_resource.package_name.each_with_index do |name, index| version = if new_resource.version && !new_resource.version[index].nil? - powershell_out(build_powershell_package_command("Get-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip + powershell_exec(build_powershell_package_command("Get-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).result else - powershell_out(build_powershell_package_command("Get-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip + powershell_exec(build_powershell_package_command("Get-Package '#{name}'"), timeout: new_resource.timeout).result end if version.empty? version = nil end + version = version.strip if version.respond_to?(:strip) version_list.push(version) end version_list diff --git a/lib/chef/resource/chef_client_config.rb b/lib/chef/resource/chef_client_config.rb index bd4ccbc478..ed5f3b26a8 100644 --- a/lib/chef/resource/chef_client_config.rb +++ b/lib/chef/resource/chef_client_config.rb @@ -87,6 +87,17 @@ class Chef ] end ``` + + **Report directly to the [Chef Automate data collector endpoint](/automate/data_collection/#configure-chef-infra-client-to-use-the-data-collector-endpoint-in-chef-automate).** + + ```ruby + chef_client_config 'Create client.rb' do + chef_server_url 'https://chef.example.dmz' + data_collector_server_url 'https://automate.example.dmz' + data_collector_token 'TEST_TOKEN_TEST' + end + ``` + DOC # @todo policy_file or policy_group being set requires the other to be set so enforce that. @@ -231,6 +242,14 @@ class Chef property :additional_config, String, description: "Additional text to add at the bottom of the client.rb config. This can be used to run custom Ruby or to add less common config options" + property :data_collector_server_url, String, + description: "The data collector url (typically automate) to send node, converge and compliance data. Note: Data collection reporting to Automate should be performed directly by Chef Infra Server if possible, as this removes the need to distribute tokens to individual nodes.", + introduced: "17.8" + + property :data_collector_token, String, + description: "The data collector token to interact with the data collector server url (Automate). Note: Data collection reporting to Automate should be performed directly by Chef Infra Server if possible, as this removes the need to distribute tokens to individual nodes.", + introduced: "17.8" + action :create, description: "Create a client.rb config file for configuring #{ChefUtils::Dist::Infra::PRODUCT}." do unless ::Dir.exist?(new_resource.config_directory) directory new_resource.config_directory do @@ -282,7 +301,9 @@ class Chef ssl_verify_mode: new_resource.ssl_verify_mode, start_handlers: format_handler(new_resource.start_handlers), additional_config: new_resource.additional_config, - policy_persist_run_list: new_resource.policy_persist_run_list + policy_persist_run_list: new_resource.policy_persist_run_list, + data_collector_server_url: new_resource.data_collector_server_url, + data_collector_token: new_resource.data_collector_token ) mode "0640" action :create diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb index 80727de7d0..aad0192490 100644 --- a/lib/chef/resource/dnf_package.rb +++ b/lib/chef/resource/dnf_package.rb @@ -68,12 +68,10 @@ class Chef end } - def allow_downgrade(arg = nil) - unless arg.nil? - Chef.deprecated(:dnf_package_allow_downgrade, "the allow_downgrade property on the dnf_package provider is not used, DNF supports downgrades by default.") - end - true - end + property :allow_downgrade, [ TrueClass, FalseClass ], + description: "Allow downgrading a package to satisfy requested version requirements.", + default: true, + desired_state: false end end end diff --git a/lib/chef/resource/support/client.erb b/lib/chef/resource/support/client.erb index 0a0db02249..8e96ca49e2 100644 --- a/lib/chef/resource/support/client.erb +++ b/lib/chef/resource/support/client.erb @@ -37,6 +37,13 @@ log_location <%= @log_location %> log_location <%= @log_location.inspect %> <% end -%> <% end -%> +<%# These data_collector options are special as they have a '.' -%> +<% unless @data_collector_server_url.nil? || @data_collector_server_url.empty? %> +data_collector.server_url <%= @data_collector_server_url %> +<% end %> +<% unless @data_collector_token.nil? || @data_collector_token.empty? %> +data_collector.token <%= @data_collector_token %> +<% end %> <%# The code below is not DRY on purpose to improve readability -%> <% unless @start_handlers.empty? -%> # Do not crash if a start handler is missing / not installed yet diff --git a/lib/chef/version.rb b/lib/chef/version.rb index ab1d551e75..ef237e0df9 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -23,7 +23,7 @@ require_relative "version_string" class Chef CHEF_ROOT = File.expand_path("..", __dir__) - VERSION = Chef::VersionString.new("17.8.7") + VERSION = Chef::VersionString.new("17.8.20") end # |