class Puppet::Agent
A general class for triggering a run of another class.
Attributes
client[R]
client_class[R]
should_fork[R]
Public Class Methods
new(client_class, should_fork=true)
click to toggle source
# File lib/puppet/agent.rb 26 def initialize(client_class, should_fork=true) 27 @should_fork = can_fork? && should_fork 28 @client_class = client_class 29 end
Public Instance Methods
can_fork?()
click to toggle source
# File lib/puppet/agent.rb 31 def can_fork? 32 Puppet.features.posix? && RUBY_PLATFORM != 'java' 33 end
needing_restart?()
click to toggle source
# File lib/puppet/agent.rb 35 def needing_restart? 36 Puppet::Application.restart_requested? 37 end
run(client_options = {})
click to toggle source
Perform a run with our client.
# File lib/puppet/agent.rb 40 def run(client_options = {}) 41 if disabled? 42 log_disabled_message 43 return 44 end 45 46 result = nil 47 wait_for_lock_deadline = nil 48 block_run = Puppet::Application.controlled_run do 49 # splay may sleep for awhile when running onetime! If not onetime, then 50 # the job scheduler splays (only once) so that agents assign themselves a 51 # slot within the splay interval. 52 do_splay = client_options.fetch(:splay, Puppet[:splay]) 53 if do_splay 54 splay(do_splay) 55 56 if disabled? 57 log_disabled_message 58 break 59 end 60 end 61 62 # waiting for certs may sleep for awhile depending on onetime, waitforcert and maxwaitforcert! 63 # this needs to happen before forking so that if we fail to obtain certs and try to exit, then 64 # we exit the main process and not the forked child. 65 ssl_context = wait_for_certificates(client_options) 66 67 result = run_in_fork(should_fork) do 68 with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client| 69 client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?) 70 begin 71 # lock may sleep for awhile depending on waitforlock and maxwaitforlock! 72 lock do 73 if disabled? 74 log_disabled_message 75 nil 76 else 77 # NOTE: Timeout is pretty heinous as the location in which it 78 # throws an error is entirely unpredictable, which means that 79 # it can interrupt code blocks that perform cleanup or enforce 80 # sanity. The only thing a Puppet agent should do after this 81 # error is thrown is die with as much dignity as possible. 82 Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do 83 Puppet.override(ssl_context: ssl_context) do 84 client.run(client_args) 85 end 86 end 87 end 88 end 89 rescue Puppet::LockError 90 now = Time.now.to_i 91 wait_for_lock_deadline ||= now + Puppet[:maxwaitforlock] 92 93 if Puppet[:waitforlock] < 1 94 Puppet.notice _("Run of %{client_class} already in progress; skipping (%{lockfile_path} exists)") % { client_class: client_class, lockfile_path: lockfile_path } 95 nil 96 elsif now >= wait_for_lock_deadline 97 Puppet.notice _("Exiting now because the maxwaitforlock timeout has been exceeded.") 98 nil 99 else 100 Puppet.info _("Another puppet instance is already running; --waitforlock flag used, waiting for running instance to finish.") 101 Puppet.info _("Will try again in %{time} seconds.") % {time: Puppet[:waitforlock]} 102 sleep Puppet[:waitforlock] 103 retry 104 end 105 rescue RunTimeoutError => detail 106 Puppet.log_exception(detail, _("Execution of %{client_class} did not complete within %{runtimeout} seconds and was terminated.") % 107 {client_class: client_class, runtimeout: Puppet[:runtimeout]}) 108 nil 109 rescue StandardError => detail 110 Puppet.log_exception(detail, _("Could not run %{client_class}: %{detail}") % { client_class: client_class, detail: detail }) 111 nil 112 ensure 113 Puppet.runtime[:http].close 114 end 115 end 116 end 117 true 118 end 119 Puppet.notice _("Shutdown/restart in progress (%{status}); skipping run") % { status: Puppet::Application.run_status.inspect } unless block_run 120 result 121 end
run_in_fork(forking = true) { || ... }
click to toggle source
# File lib/puppet/agent.rb 127 def run_in_fork(forking = true) 128 return yield unless forking or Puppet.features.windows? 129 130 atForkHandler = Puppet::Util::AtFork.get_handler 131 132 atForkHandler.prepare 133 134 begin 135 child_pid = Kernel.fork do 136 atForkHandler.child 137 $0 = _("puppet agent: applying configuration") 138 begin 139 exit(yield || 1) 140 rescue NoMemoryError 141 exit(254) 142 end 143 end 144 ensure 145 atForkHandler.parent 146 end 147 148 exit_code = Process.waitpid2(child_pid) 149 exit_code[1].exitstatus 150 end
stopping?()
click to toggle source
# File lib/puppet/agent.rb 123 def stopping? 124 Puppet::Application.stop_requested? 125 end
Private Instance Methods
log_disabled_message()
click to toggle source
# File lib/puppet/agent.rb 174 def log_disabled_message 175 Puppet.notice _("Skipping run of %{client_class}; administratively disabled (Reason: '%{disable_message}');\nUse 'puppet agent --enable' to re-enable.") % { client_class: client_class, disable_message: disable_message } 176 end
wait_for_certificates(options)
click to toggle source
# File lib/puppet/agent.rb 168 def wait_for_certificates(options) 169 waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert]) 170 sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert, onetime: Puppet[:onetime]) 171 sm.ensure_client_certificate 172 end
with_client(transaction_uuid, job_id = nil) { |client| ... }
click to toggle source
Create and yield a client instance, keeping a reference to it during the yield.
# File lib/puppet/agent.rb 156 def with_client(transaction_uuid, job_id = nil) 157 begin 158 @client = client_class.new(transaction_uuid, job_id) 159 rescue StandardError => detail 160 Puppet.log_exception(detail, _("Could not create instance of %{client_class}: %{detail}") % { client_class: client_class, detail: detail }) 161 return 162 end 163 yield @client 164 ensure 165 @client = nil 166 end