Parent

Included Modules

Files

Class/Module Index [+]

Quicksearch

Chef::Client

Chef::Client

The main object in a Chef run. Preps a Chef::Node and Chef::RunContext, syncs cookbooks if necessary, and triggers convergence.

Constants

STDERR_FD

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.

STDOUT_FD

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.

Attributes

events[R]
json_attribs[R]
node[RW]
ohai[RW]
rest[RW]
run_status[R]
runner[RW]

Public Class Methods

clear_notifications() click to toggle source

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
new(json_attribs=nil, args={}) click to toggle source

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
run_completed_successfully_notifications() click to toggle source

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
run_failed_notifications() click to toggle source

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
run_start_notifications() click to toggle source

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
when_run_completes_successfully(¬ification_block) click to toggle source

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(&notification_block)
  run_completed_successfully_notifications << notification_block
end
when_run_fails(¬ification_block) click to toggle source

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(&notification_block)
  run_failed_notifications << notification_block
end
when_run_starts(¬ification_block) click to toggle source

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(&notification_block)
  run_start_notifications << notification_block
end

Public Instance Methods

build_node() click to toggle source

Mutates the `node` object to prepare it for the chef run. Delegates to policy_builder

Returns

Chef::Node

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
configure_formatters() click to toggle source
# 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
converge(run_context) click to toggle source

Converges the node.

Returns

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
default_formatter() click to toggle source
# 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
do_windows_admin_check() click to toggle source
# 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
expanded_run_list() click to toggle source

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.

Returns

RunListExpansion: A RunListExpansion or API compatible object.

# File lib/chef/client.rb, line 362
def expanded_run_list
  policy_builder.expand_run_list
end
formatters_for_run() click to toggle source
# File lib/chef/client.rb, line 178
def formatters_for_run
  if Chef::Config.formatters.empty?
    [default_formatter]
  else
    Chef::Config.formatters
  end
end
handle_child_exit(pid_and_status) click to toggle source
# 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
load_node() click to toggle source

Instantiates a Chef::Node object, possibly loading the node’s prior state when using chef-client. Delegates to policy_builder

Returns

Chef::Node

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
node_name() click to toggle source
# 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
policy_builder() click to toggle source
# 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
register(client_name=node_name, config=Chef::Config) click to toggle source

Returns

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
run() click to toggle source

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.

Returns

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
run_completed_successfully() click to toggle source

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
run_failed() click to toggle source

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
run_ohai() click to toggle source
# File lib/chef/client.rb, line 291
def run_ohai
  ohai.all_plugins
end
run_started() click to toggle source

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
save_updated_node() click to toggle source
# 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
setup_run_context() click to toggle source
# File lib/chef/client.rb, line 264
def setup_run_context
  run_context = policy_builder.setup_run_context(@specific_recipes)
  assert_cookbook_path_not_empty(run_context)
  run_status.run_context = run_context
  run_context
end
sync_cookbooks() click to toggle source
# File lib/chef/client.rb, line 271
def sync_cookbooks
  policy_builder.sync_cookbooks
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.