class PoiseLanguages::System::Provider
The default provider for `poise_languages_system`.
@api private @since 1.0 @see Resource
@provides poise_languages_system
Public Instance Methods
The `install` action for the `poise_languages_system` resource.
@return [void]
# File lib/poise_languages/system/resource.rb, line 99 def action_install notifying_block do install_packages run_action_hack end end
The `uninstall` action for the `poise_languages_system` resource.
@return [void]
# File lib/poise_languages/system/resource.rb, line 119 def action_uninstall notifying_block do uninstall_packages end end
The `upgrade` action for the `poise_languages_system` resource.
@return [void]
# File lib/poise_languages/system/resource.rb, line 109 def action_upgrade notifying_block do upgrade_packages run_action_hack end end
Private Instance Methods
Install the needed language packages.
@api private @return [Array<Chef::Resource>]
# File lib/poise_languages/system/resource.rb, line 131 def install_packages packages = {new_resource.package_name => new_resource.package_version} # If we are supposed to install the dev package, grab it using the same # version as the main package. if new_resource.dev_package packages[new_resource.dev_package] = new_resource.package_version end Chef::Log.debug("[#{new_resource.parent}] Building package resource using #{packages.inspect}.") # Check for multi-package support. package_resource_class = Chef::Resource.resource_for_node(:package, node) package_provider_class = package_resource_class.new('multipackage_check', run_context).provider_for_action(:install) package_resources = if package_provider_class.respond_to?(:use_multipackage_api?) && package_provider_class.use_multipackage_api? package packages.keys do version packages.values end else # Fallback for non-multipackage. packages.map do |pkg_name, pkg_version| package pkg_name do version pkg_version end end end # Apply some settings to all of the resources. Array(package_resources).each do |res| res.retries(5) res.define_singleton_method(:apply_action_hack?) { true } end end
Hack a provider object to run our verification code.
@param provider [Chef::Provider] Provider
object to patch. @param version [String] Language version prefix to check for. @return [void]
# File lib/poise_languages/system/resource.rb, line 226 def patch_load_current_resource!(provider, version) # Create a closure module and inject it. provider.extend Module.new { # Patch load_current_resource to run our verification logic after # the normal code. define_method(:load_current_resource) do super().tap do |_| each_package do |package_name, new_version, current_version, candidate_version| # In Chef 12.14+, candidate_version is a Chef::Decorator::Lazy object # so we need the nil? check to see if the object being proxied is # nil (i.e. there is no version). The `\d+:` is for RPM epoch prefixes. unless candidate_version && (!candidate_version.nil?) && (!candidate_version.empty?) && candidate_version =~ /^(\d+:)?#{Regexp.escape(version)}/ # Don't display a wonky error message if there is no candidate. candidate_label = if candidate_version && (!candidate_version.nil?) && (!candidate_version.empty?) candidate_version else candidate_version.inspect end raise PoiseLanguages::Error.new("Package #{package_name} would install #{candidate_label}, which does not match #{version.empty? ? version.inspect : version}. Please set the package_name or package_version provider options.") end end end end } end
Run the requested action for all package resources. This exists because we inject our version check in to the provider directly and I want to only run the provider action once for performance. It is otherwise mostly a stripped down version of Chef::Resource#run_action.
@param action [Symbol] Action to run on all package resources. @return [void]
# File lib/poise_languages/system/resource.rb, line 190 def run_action_hack # If new_resource.package_version is set, skip this madness. return if new_resource.package_version # Process every resource in the current collection, which is bounded # by notifying_block. run_context.resource_collection.each do |resource| # Only apply to things we tagged above. next unless resource.respond_to?(:apply_action_hack?) && resource.apply_action_hack? Array(resource.action).each do |action| # Reset it so we have a clean baseline. resource.updated_by_last_action(false) # Grab the provider. provider = resource.provider_for_action(action) provider.action = action # Inject our check for the candidate version. This will actually # get run during run_action below. patch_load_current_resource!(provider, new_resource.version) # Run our action. Chef::Log.debug("[#{new_resource.parent}] Running #{provider} with #{action}") provider.run_action(action) # Check updated flag. new_resource.updated_by_last_action(true) if resource.updated_by_last_action? end # Make sure the resource doesn't run again when notifying_block ends. resource.action(:nothing) end end
Uninstall the needed language packages.
@api private @return [Array<Chef::Resource>]
# File lib/poise_languages/system/resource.rb, line 177 def uninstall_packages install_packages.each do |res| res.action(node.platform_family?('debian') ? :purge : :remove) end end
Upgrade the needed language packages.
@api private @return [Array<Chef::Resource>]
# File lib/poise_languages/system/resource.rb, line 167 def upgrade_packages install_packages.each do |res| res.action(:upgrade) end end