The main object in a Chef run. Preps a Chef::Node and Chef::RunContext, syncs cookbooks if necessary, and triggers convergence.
IO stream that will be used as ‘STDERR’ for formatters. Formatters are configured during `initialize`, so this provides a convenience for setting alternative IO stream during tests.
IO stream that will be used as ‘STDOUT’ for formatters. Formatters are configured during `initialize`, so this provides a convenience for setting alternative IO stream during tests.
Clears all notifications for client run status events. Primarily for testing purposes.
# File lib/chef/client.rb, line 70 def self.clear_notifications @run_start_notifications = nil @run_completed_successfully_notifications = nil @run_failed_notifications = nil end
Creates a new Chef::Client.
# File lib/chef/client.rb, line 147 def initialize(json_attribs=nil, args={}) @json_attribs = json_attribs || {} @node = nil @run_status = nil @runner = nil @ohai = Ohai::System.new event_handlers = configure_formatters event_handlers += Array(Chef::Config[:event_handlers]) @events = EventDispatch::Dispatcher.new(*event_handlers) @override_runlist = args.delete(:override_runlist) @specific_recipes = args.delete(:specific_recipes) if new_runlist = args.delete(:runlist) @json_attribs["run_list"] = new_runlist end end
The list of notifications to be run when the client run completes successfully.
# File lib/chef/client.rb, line 83 def self.run_completed_successfully_notifications @run_completed_successfully_notifications ||= [] end
The list of notifications to be run when the client run fails.
# File lib/chef/client.rb, line 88 def self.run_failed_notifications @run_failed_notifications ||= [] end
The list of notifications to be run when the client run starts.
# File lib/chef/client.rb, line 77 def self.run_start_notifications @run_start_notifications ||= [] end
Add a notification for the ‘client run success’ event. The notification is provided as a block. The current Chef::RunStatus object will be passed to the notification_block when the event is triggered.
# File lib/chef/client.rb, line 102 def self.when_run_completes_successfully(¬ification_block) run_completed_successfully_notifications << notification_block end
Add a notification for the ‘client run failed’ event. The notification is provided as a block. The current Chef::RunStatus is passed to the notification_block when the event is triggered.
# File lib/chef/client.rb, line 109 def self.when_run_fails(¬ification_block) run_failed_notifications << notification_block end
Add a notification for the ‘client run started’ event. The notification is provided as a block. The current Chef::RunStatus object will be passed to the notification_block when the event is triggered.
# File lib/chef/client.rb, line 95 def self.when_run_starts(¬ification_block) run_start_notifications << notification_block end
Mutates the `node` object to prepare it for the chef run. Delegates to policy_builder
The updated node object |
# File lib/chef/client.rb, line 258 def build_node policy_builder.build_node @run_status = Chef::RunStatus.new(node, events) node end
# File lib/chef/client.rb, line 166 def configure_formatters formatters_for_run.map do |formatter_name, output_path| if output_path.nil? Chef::Formatters.new(formatter_name, STDOUT_FD, STDERR_FD) else io = File.open(output_path, "a+") io.sync = true Chef::Formatters.new(formatter_name, io, io) end end end
Converges the node.
true |
Always returns true |
# File lib/chef/client.rb, line 341 def converge(run_context) @events.converge_start(run_context) Chef::Log.debug("Converging node #{node_name}") @runner = Chef::Runner.new(run_context) runner.converge @events.converge_complete true rescue Exception # TODO: should this be a separate #converge_failed(exception) method? @events.converge_complete raise end
# File lib/chef/client.rb, line 186 def default_formatter if (STDOUT.tty? && !Chef::Config[:force_logger]) || Chef::Config[:force_formatter] [:doc] else [:null] end end
# File lib/chef/client.rb, line 367 def do_windows_admin_check if Chef::Platform.windows? Chef::Log.debug("Checking for administrator privileges....") if !has_admin_privileges? message = "chef-client doesn't have administrator privileges on node #{node_name}." if Chef::Config[:fatal_windows_admin_check] Chef::Log.fatal(message) Chef::Log.fatal("fatal_windows_admin_check is set to TRUE.") raise Chef::Exceptions::WindowsNotAdmin, message else Chef::Log.warn("#{message} This might cause unexpected resource failures.") end else Chef::Log.debug("chef-client has administrator privileges on node #{node_name}.") end end end
Expands the run list. Delegates to the policy_builder.
Normally this does not need to be called from here, it will be called by build_node. This is provided so external users (like the chefspec project) can inject custom behavior into the run process.
RunListExpansion: A RunListExpansion or API compatible object.
# File lib/chef/client.rb, line 362 def expanded_run_list policy_builder.expand_run_list end
# File lib/chef/client.rb, line 178 def formatters_for_run if Chef::Config.formatters.empty? [default_formatter] else Chef::Config.formatters end end
# File lib/chef/client.rb, line 231 def handle_child_exit(pid_and_status) status = pid_and_status[1] return true if status.success? message = if status.signaled? "Chef run process terminated by signal #{status.termsig} (#{Signal.list.invert[status.termsig]})" else "Chef run process exited unsuccessfully (exit code #{status.exitstatus})" end raise Exceptions::ChildConvergeError, message end
Instantiates a Chef::Node object, possibly loading the node’s prior state when using chef-client. Delegates to policy_builder
The node object for this chef run |
# File lib/chef/client.rb, line 248 def load_node policy_builder.load_node @node = policy_builder.node end
# File lib/chef/client.rb, line 295 def node_name name = Chef::Config[:node_name] || ohai[:fqdn] || ohai[:machinename] || ohai[:hostname] Chef::Config[:node_name] = name raise Chef::Exceptions::CannotDetermineNodeName unless name # node names > 90 bytes only work with authentication protocol >= 1.1 # see discussion in config.rb. if name.bytesize > 90 Chef::Config[:authentication_protocol_version] = "1.1" end name end
# File lib/chef/client.rb, line 275 def policy_builder @policy_builder ||= Chef::PolicyBuilder.strategy.new(node_name, ohai.data, json_attribs, @override_runlist, events) end
rest<Chef::REST> |
returns Chef::REST connection object |
# File lib/chef/client.rb, line 313 def register(client_name=node_name, config=Chef::Config) if !config[:client_key] @events.skipping_registration(client_name, config) Chef::Log.debug("Client key is unspecified - skipping registration") elsif File.exists?(config[:client_key]) @events.skipping_registration(client_name, config) Chef::Log.debug("Client key #{config[:client_key]} is present - skipping registration") else @events.registration_start(node_name, config) Chef::Log.info("Client key #{config[:client_key]} is not present - registering") Chef::ApiClient::Registration.new(node_name, config[:client_key]).run @events.registration_completed end # We now have the client key, and should use it from now on. @rest = Chef::REST.new(config[:chef_server_url], client_name, config[:client_key]) @resource_reporter = Chef::ResourceReporter.new(@rest) @events.register(@resource_reporter) rescue Exception => e # TODO: munge exception so a semantic failure message can be given to the # user @events.registration_failed(node_name, e, config) raise end
Do a full run for this Chef::Client. Calls:
do_run
This provides a wrapper around do_run allowing the run to be optionally forked.
boolean |
Return value from do_run. Should always returns true. |
# File lib/chef/client.rb, line 201 def run # win32-process gem exposes some form of :fork for Process # class. So we are seperately ensuring that the platform we're # running on is not windows before forking. if(Chef::Config[:client_fork] && Process.respond_to?(:fork) && !Chef::Platform.windows?) Chef::Log.info "Forking chef instance to converge..." pid = fork do [:INT, :TERM].each {|s| trap(s, "EXIT") } client_solo = Chef::Config[:solo] ? "chef-solo" : "chef-client" $0 = "#{client_solo} worker: ppid=#{Process.ppid};start=#{Time.new.strftime("%R:%S")};" begin Chef::Log.debug "Forked instance now converging" do_run rescue Exception => e Chef::Log.error(e.to_s) exit 1 else exit 0 end end Chef::Log.debug "Fork successful. Waiting for new chef pid: #{pid}" result = Process.waitpid2(pid) handle_child_exit(result) Chef::Log.debug "Forked instance successfully reaped (pid: #{pid})" true else do_run end end
Callback to fire notifications that the run completed successfully
# File lib/chef/client.rb, line 122 def run_completed_successfully success_handlers = self.class.run_completed_successfully_notifications success_handlers.each do |notification| notification.call(run_status) end end
Callback to fire notifications that the Chef run failed
# File lib/chef/client.rb, line 130 def run_failed failure_handlers = self.class.run_failed_notifications failure_handlers.each do |notification| notification.call(run_status) end end
# File lib/chef/client.rb, line 291 def run_ohai ohai.all_plugins end
Callback to fire notifications that the Chef run is starting
# File lib/chef/client.rb, line 114 def run_started self.class.run_start_notifications.each do |notification| notification.call(run_status) end @events.run_started(run_status) end
# File lib/chef/client.rb, line 280 def save_updated_node if Chef::Config[:solo] # nothing to do elsif policy_builder.temporary_policy? Chef::Log.warn("Skipping final node save because override_runlist was given") else Chef::Log.debug("Saving the current state of node #{node_name}") @node.save end end
Generated with the Darkfish Rdoc Generator 2.