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
25 def initialize(client_class, should_fork=true)
26   @should_fork = can_fork? && should_fork
27   @client_class = client_class
28 end

Public Instance Methods

can_fork?() click to toggle source
   # File lib/puppet/agent.rb
30 def can_fork?
31   Puppet.features.posix? && RUBY_PLATFORM != 'java'
32 end
needing_restart?() click to toggle source
   # File lib/puppet/agent.rb
34 def needing_restart?
35   Puppet::Application.restart_requested?
36 end
run(client_options = {}) click to toggle source

Perform a run with our client.

   # File lib/puppet/agent.rb
39 def run(client_options = {})
40   if disabled?
41     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 }
42     return
43   end
44 
45   result = nil
46   wait_for_lock_deadline = nil
47   block_run = Puppet::Application.controlled_run do
48     splay client_options.fetch :splay, Puppet[:splay]
49     result = run_in_fork(should_fork) do
50       with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client|
51         client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?)
52         begin
53           lock do
54             # NOTE: Timeout is pretty heinous as the location in which it
55             # throws an error is entirely unpredictable, which means that
56             # it can interrupt code blocks that perform cleanup or enforce
57             # sanity. The only thing a Puppet agent should do after this
58             # error is thrown is die with as much dignity as possible.
59             Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
60               client.run(client_args)
61             end
62           end
63         rescue Puppet::LockError
64           now = Time.now.to_i
65           wait_for_lock_deadline ||= now + Puppet[:maxwaitforlock]
66 
67           if Puppet[:waitforlock] < 1
68             Puppet.notice _("Run of %{client_class} already in progress; skipping  (%{lockfile_path} exists)") % { client_class: client_class, lockfile_path: lockfile_path }
69             nil
70           elsif now >= wait_for_lock_deadline
71             Puppet.notice _("Exiting now because the maxwaitforlock timeout has been exceeded.")
72             nil
73           else
74             Puppet.info _("Another puppet instance is already running; --waitforlock flag used, waiting for running instance to finish.")
75             Puppet.info _("Will try again in %{time} seconds.") % {time: Puppet[:waitforlock]}
76             sleep Puppet[:waitforlock]
77             retry
78           end
79         rescue RunTimeoutError => detail
80           Puppet.log_exception(detail, _("Execution of %{client_class} did not complete within %{runtimeout} seconds and was terminated.") %
81             {client_class: client_class,
82             runtimeout: Puppet[:runtimeout]})
83           nil
84         rescue StandardError => detail
85           Puppet.log_exception(detail, _("Could not run %{client_class}: %{detail}") % { client_class: client_class, detail: detail })
86           nil
87         end
88       end
89     end
90     true
91   end
92   Puppet.notice _("Shutdown/restart in progress (%{status}); skipping run") % { status: Puppet::Application.run_status.inspect } unless block_run
93   result
94 end
run_in_fork(forking = true) { || ... } click to toggle source
    # File lib/puppet/agent.rb
100 def run_in_fork(forking = true)
101   return yield unless forking or Puppet.features.windows?
102 
103   atForkHandler = Puppet::Util::AtFork.get_handler
104 
105   atForkHandler.prepare
106 
107   begin
108     child_pid = Kernel.fork do
109       atForkHandler.child
110       $0 = _("puppet agent: applying configuration")
111       begin
112         exit(yield || 1)
113       rescue NoMemoryError
114         exit(254)
115       end
116     end
117   ensure
118     atForkHandler.parent
119   end
120 
121   exit_code = Process.waitpid2(child_pid)
122   exit_code[1].exitstatus
123 end
stopping?() click to toggle source
   # File lib/puppet/agent.rb
96 def stopping?
97   Puppet::Application.stop_requested?
98 end

Private Instance Methods

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
129 def with_client(transaction_uuid, job_id = nil)
130   begin
131     @client = client_class.new(transaction_uuid, job_id)
132   rescue StandardError => detail
133     Puppet.log_exception(detail, _("Could not create instance of %{client_class}: %{detail}") % { client_class: client_class, detail: detail })
134     return
135   end
136   yield @client
137 ensure
138   @client = nil
139 end