class Chef::Application::Base
This is a temporary class being used as a part of an effort to reduce duplication between Chef::Application::Client
and Chef::Application::Solo
.
If you are looking to make edits to the Client/Solo behavior please make changes here.
If you are looking to reference or subclass this class, use Chef::Application::Client
instead. This base class will be removed once the work is complete and external code will break.
@deprecated use Chef::Application::Client
instead, this will be removed in Chef-16
Constants
- IMMEDIATE_RUN_SIGNAL
- RECONFIGURE_SIGNAL
- SELF_PIPE
Mimic self_pipe sleep from Unicorn to capture signals safely
Attributes
chef_client_json[R]
Public Instance Methods
run_application()
click to toggle source
Run the chef client, optionally daemonizing or looping at intervals.
# File lib/chef/application/base.rb, line 346 def run_application if Chef::Config[:version] puts "#{ChefUtils::Dist::Infra::PRODUCT} version: #{::Chef::VERSION}" end if !Chef::Config[:client_fork] || Chef::Config[:once] begin # run immediately without interval sleep, or splay run_chef_client(Chef::Config[:specific_recipes]) rescue SystemExit raise rescue Exception => e Chef::Application.fatal!("#{e.class}: #{e.message}", e) end else interval_run_chef_client end end
setup_application()
click to toggle source
# File lib/chef/application/base.rb, line 322 def setup_application Chef::Daemon.change_privilege end
setup_signal_handlers()
click to toggle source
Calls superclass method
Chef::Application#setup_signal_handlers
# File lib/chef/application/base.rb, line 326 def setup_signal_handlers super unless Chef::Platform.windows? SELF_PIPE.replace IO.pipe trap("USR1") do Chef::Log.info("SIGUSR1 received, will run now or after the current run") SELF_PIPE[1].putc(IMMEDIATE_RUN_SIGNAL) # wakeup master process from select end # Override the trap setup in the parent so we can avoid running reconfigure during a run trap("HUP") do Chef::Log.info("SIGHUP received, will reconfigure now or after the current run") SELF_PIPE[1].putc(RECONFIGURE_SIGNAL) # wakeup master process from select end end end
Private Instance Methods
aws_api_region()
click to toggle source
# File lib/chef/application/base.rb, line 420 def aws_api_region ENV["AWS_REGION"] || Aws.shared_config.region || Aws::EC2Metadata.new.get("/latest/meta-data/placement/region") end
fetch_recipe_tarball(url, path)
click to toggle source
# File lib/chef/application/base.rb, line 381 def fetch_recipe_tarball(url, path) require "open-uri" unless defined?(OpenURI) uri = URI.parse(url) Chef::Log.trace("Download recipes tarball from #{url} to #{path}") if File.exist?(url) FileUtils.cp(url, path) elsif uri.scheme == "s3" require "aws-sdk-s3" unless defined?(Aws::S3) bucket_name = uri.hostname s3 = Aws::S3::Client.new(region: s3_bucket_location(bucket_name)) object = s3.get_object(bucket: bucket_name, key: uri.path[1..-1]) File.open(path, "wb") do |f| f.write(object.body.read) end elsif URI::DEFAULT_PARSER.make_regexp.match?(url) File.open(path, "wb") do |f| URI.open(url) do |r| f.write(r.read) end end else Chef::Application.fatal! "You specified --recipe-url but the value is neither a valid URL, an S3 bucket nor a path to a file that exists on disk." + "Please confirm the location of the tarball and try again." end end
for_ezra()
click to toggle source
# File lib/chef/application/base.rb, line 488 def for_ezra puts <<~EOH For Ezra Zygmuntowicz: The man who brought you Chef Solo Early contributor to Chef Kind hearted open source advocate Rest in peace, Ezra. EOH end
interval_run_chef_client()
click to toggle source
# File lib/chef/application/base.rb, line 424 def interval_run_chef_client if Chef::Config[:daemonize] Chef::Daemon.daemonize(ChefUtils::Dist::Infra::PRODUCT) # Start first daemonized run after configured number of seconds if Chef::Config[:daemonize].is_a?(Integer) sleep_then_run_chef_client(Chef::Config[:daemonize]) end end loop do sleep_then_run_chef_client(time_to_sleep) Chef::Application.exit!("Exiting", 0) unless Chef::Config[:interval] end end
interval_sleep(sec)
click to toggle source
sleep and handle queued signals
# File lib/chef/application/base.rb, line 469 def interval_sleep(sec) unless SELF_PIPE.empty? # mimic sleep with a timeout on IO.select, listening for signals setup in #setup_signal_handlers return unless IO.select([ SELF_PIPE[0] ], nil, nil, sec) signal = SELF_PIPE[0].getc.chr return if signal == IMMEDIATE_RUN_SIGNAL # be explicit about this behavior # we need to sleep again after reconfigure to avoid stampeding when logrotate runs out of cron if signal == RECONFIGURE_SIGNAL reconfigure interval_sleep(sec) end else sleep(sec) end end
s3_bucket_location(bucket_name)
click to toggle source
# File lib/chef/application/base.rb, line 410 def s3_bucket_location(bucket_name) s3 = Aws::S3::Client.new(region: aws_api_region) resp = s3.get_bucket_location(bucket: bucket_name) resp.location_constraint rescue Aws::S3::Errors::AccessDenied => _e Chef::Log.warn("Missing s3:GetBucketLocation privilege, trying currently configured region #{aws_api_region}") aws_api_region end
sleep_then_run_chef_client(sleep_sec)
click to toggle source
# File lib/chef/application/base.rb, line 440 def sleep_then_run_chef_client(sleep_sec) Chef::Log.trace("Sleeping for #{sleep_sec} seconds") # interval_sleep will return early if we received a signal (unless on windows) interval_sleep(sleep_sec) run_chef_client(Chef::Config[:specific_recipes]) reconfigure rescue SystemExit => e raise rescue Exception => e if Chef::Config[:interval] Chef::Log.error("#{e.class}: #{e}") Chef::Log.trace("#{e.class}: #{e}\n#{e.backtrace.join("\n")}") retry end Chef::Application.fatal!("#{e.class}: #{e.message}", e) end
time_to_sleep()
click to toggle source
# File lib/chef/application/base.rb, line 461 def time_to_sleep duration = 0 duration += rand(Chef::Config[:splay]) if Chef::Config[:splay] duration += Chef::Config[:interval] if Chef::Config[:interval] duration end
unforked_interval_error_message()
click to toggle source
# File lib/chef/application/base.rb, line 374 def unforked_interval_error_message "Unforked #{ChefUtils::Dist::Infra::PRODUCT} interval runs are disabled by default." + "\nConfiguration settings:" + ("\n interval = #{Chef::Config[:interval]} seconds" if Chef::Config[:interval]).to_s + "\nEnable #{ChefUtils::Dist::Infra::PRODUCT} interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options." end
windows_interval_error_message()
click to toggle source
# File lib/chef/application/base.rb, line 367 def windows_interval_error_message "Windows #{ChefUtils::Dist::Infra::PRODUCT} interval runs are not supported in #{ChefUtils::Dist::Infra::PRODUCT} 15 and later." + "\nConfiguration settings:" + ("\n interval = #{Chef::Config[:interval]} seconds" if Chef::Config[:interval]).to_s + "\nPlease manage #{ChefUtils::Dist::Infra::PRODUCT} as a scheduled task instead." end