Skip to main content

About the Handler DSL

[edit on GitHub]

Use the Handler DSL to attach a callback to an event. If the event occurs during a Chef Infra Client run, the associated callback is executed. For example:

  • Sending email if a Chef Infra Client run fails
  • Aggregating statistics about resources updated during a Chef Infra Client runs to StatsD

on Method

Use the on method to associate an event type with a callback. The callback defines what steps are taken if the event occurs during a Chef Infra Client run and is defined using arbitrary Ruby code. The syntax is as follows:

Chef.event_handler do
  on :event_type do
    # some Ruby
  end
end

where

  • Chef.event_handler declares a block of code within a recipe that is processed when the named event occurs during a Chef Infra Client run
  • on defines the block of code that will tell Chef Infra Client how to handle the event
  • :event_type is a valid exception event type, such as :run_start, :run_failed, :converge_failed, :resource_failed, or :recipe_not_found

For example:

Chef.event_handler do
  on :converge_start do
    puts "Ohai! I have started a converge."
  end
end

Event Types

The following table describes the events that may occur during a Chef Infra Client run. Each of these events may be referenced in an on method block by declaring it as the event type.

EventDescription
:run_startThe start of a Chef Infra Client run.
:run_startedThe Chef Infra Client run has started.
:run_completedThe Chef Infra Client run has completed.
:run_failedThe Chef Infra Client run has failed.
:ohai_completedThe Ohai run has completed.
:skipping_registrationThe Chef Infra Client is not registering with the Chef Infra Server because it already has a private key or because it does not need one.
:registration_startThe Chef Infra Client is attempting to create a private key with which to register to the Chef Infra Server.
:registration_completedThe Chef Infra Client created its private key successfully.
:registration_failedThe Chef Infra Client encountered an error and was unable to register with the Chef Infra Server.
:node_load_startThe Chef Infra Client is attempting to load node data from the Chef Infra Server.
:node_load_successThe Chef Infra Client successfully loaded node data from the policy builder.
:node_load_failedThe Chef Infra Client encountered an error and was unable to load node data from the Chef Infra Server.
:run_list_expand_failedThe Chef Infra Client failed to expand the run-list.
:node_load_completedThe Chef Infra Client successfully loaded node data from the Chef Infra Server. Default and override attributes for roles have been computed, but are not yet applied.
:policyfile_loadedThe policy file was loaded.
:cookbook_resolution_startThe Chef Infra Client is attempting to pull down the cookbook collection from the Chef Infra Server.
:cookbook_resolution_failedThe Chef Infra Client failed to pull down the cookbook collection from the Chef Infra Server.
:cookbook_resolution_completeThe Chef Infra Client successfully pulled down the cookbook collection from the Chef Infra Server.
:cookbook_clean_startThe Chef Infra Client is attempting to remove unneeded cookbooks.
:removed_cookbook_fileThe Chef Infra Client removed a file from a cookbook.
:cookbook_clean_completeThe Chef Infra Client is done removing cookbooks and/or cookbook files.
:cookbook_sync_startThe Chef Infra Client is attempting to synchronize cookbooks.
:synchronized_cookbookThe Chef Infra Client is attempting to synchronize the named cookbook.
:updated_cookbook_fileThe Chef Infra Client updated the named file in the named cookbook.
:cookbook_sync_failedThe Chef Infra Client was unable to synchronize cookbooks.
:cookbook_sync_completeThe Chef Infra Client is finished synchronizing cookbooks.
:cookbook_gem_startThe Chef Infra Client is collecting gems from the cookbooks.
:cookbook_gem_installingThe Chef Infra Client is installing a cookbook gem.
:cookbook_gem_usingThe Chef Infra Client is using a cookbook gem.
:cookbook_gem_finishedThe Chef Infra Client finished installing cookbook gems.
:cookbook_gem_failedThe Chef Infra Client failed to install cookbook gems.
:cookbook_compilation_startThe Chef Infra Client created the run_context and is starting cookbook compilation.
:library_load_startThe Chef Infra Client is loading library files.
:library_file_loadedThe Chef Infra Client successfully loaded the named library file.
:library_file_load_failedThe Chef Infra Client was unable to load the named library file.
:library_load_completeThe Chef Infra Client is finished loading library files.
:lwrp_load_startThe Chef Infra Client is loading custom resources.
:lwrp_file_loadedThe Chef Infra Client successfully loaded the named custom resource.
:lwrp_file_load_failedThe Chef Infra Client was unable to load the named custom resource.
:lwrp_load_completeThe Chef Infra Client is finished loading custom resources.
:ohai_plugin_load_startOhai has started loading plugins.
:ohai_plugin_file_loadedOhai has loaded a plugin.
:ohai_plugin_file_load_failedOhai failed to load a plugin.
:ohai_plugin_load_completeOhai has completed loading plugins.
:attribute_load_startThe Chef Infra Client is loading attribute files.
:attribute_file_loadedThe Chef Infra Client successfully loaded the named attribute file.
:attribute_file_load_failedThe Chef Infra Client was unable to load the named attribute file.
:attribute_load_completeThe Chef Infra Client is finished loading attribute files.
:definition_load_startThe Chef Infra Client is loading definitions.
:definition_file_loadedThe Chef Infra Client successfully loaded the named definition.
:definition_file_load_failedThe Chef Infra Client was unable to load the named definition.
:definition_load_completeThe Chef Infra Client is finished loading definitions.
:recipe_load_startThe Chef Infra Client is loading recipes.
:recipe_file_loadedThe Chef Infra Client successfully loaded the named recipe.
:recipe_file_load_failedThe Chef Infra Client was unable to load the named recipe.
:recipe_not_foundThe Chef Infra Client was unable to find the named recipe.
:recipe_load_completeThe Chef Infra Client is finished loading recipes.
:cookbook_compilation_completeThe Chef Infra Client completed all cookbook compilation phases.
:converge_startThe Chef Infra Client run converge phase has started.
:action_collection_registrationProvides a reference to the action_collection before cookbooks are compiled.
:converge_completeThe Chef Infra Client run converge phase is complete.
:converge_failedThe Chef Infra Client run converge phase has failed.
:control_group_startedThe named control group is being processed.
:control_example_successThe named control group has been processed.
:control_example_failureThe named control group's processing has failed.
:resource_action_startA resource action is starting.
:resource_skippedA resource action was skipped.
:resource_current_state_loadedA resource's current state was loaded.
:resource_after_state_loadedA resource's after state was loaded.
:resource_current_state_load_bypassedA resource's current state was not loaded because the resource does not support why-run mode.
:resource_bypassedA resource action was skipped because the resource does not support why-run mode.
:resource_update_appliedA change has been made to a resource. (This event occurs for each change made to a resource.)
:resource_update_progressA resource sent a progress notification to the user to indicate overall progress of a long running operation.
:resource_failed_retriableA resource action has failed and will be retried.
:resource_failedA resource action has failed and will not be retried.
:resource_updatedA resource requires modification.
:resource_up_to_dateA resource is already correct.
:resource_completedAll actions for the resource are complete.
:stream_openedA stream has opened.
:stream_closedA stream has closed.
:stream_outputA chunk of data from a single named stream.
:handlers_startThe handler processing phase of a Chef Infra Client run has started.
:handler_executedThe named handler was processed.
:handlers_completedThe handler processing phase of a Chef Infra Client run is complete.
:provider_requirement_failedAn assertion declared by a provider has failed.
:whyrun_assumptionAn assertion declared by a provider has failed, but execution is allowed to continue because the Chef Infra Client is running in why-run mode.
:deprecationA deprecation message has been emitted.
:attribute_changedPrints out all the attribute changes in cookbooks or sets a policy that override attributes should never be used.

Examples

The following examples show ways to use the Handler DSL.

Send Email

Use the on method to create an event handler that sends email when a Chef Infra Client run fails. This will require:

  • A way to tell Chef Infra Client how to send email
  • An event handler that describes what to do when the :run_failed event is triggered
  • A way to trigger the exception and test the behavior of the event handler

Define How Email is Sent

Use a library to define the code that sends email when a Chef Infra Client run fails. Name the file helper.rb and add it to a cookbook’s /libraries directory:

require 'net/smtp'

module HandlerSendEmail
  class Helper
    def send_email_on_run_failure(node_name)
      message = "From: Chef <chef@chef.io>\n"
      message &lt;&lt; "To: Grant <grantmc@chef.io>\n"
      message &lt;&lt; "Subject: Chef run failed\n"
      message &lt;&lt; "Date: #{Time.now.rfc2822}\n\n"
      message &lt;&lt; "Chef run failed on #{node_name}\n"
      Net::SMTP.start('localhost', 25) do |smtp|
        smtp.send_message message, 'chef@chef.io', 'grantmc@chef.io'
      end
    end
  end
end

Add the Handler

Invoke the library helper in a recipe:

Chef.event_handler do
  on :run_failed do
    HandlerSendEmail::Helper.new.send_email_on_run_failure(
      Chef.run_context.node.name
    )
  end
end
  • Use Chef.event_handler to define the event handler
  • Use the on method to specify the event type

Within the on block, tell Chef Infra Client how to handle the event when it is triggered.

Test the Handler

Use the following code block to trigger the exception and have the Chef Infra Client send email to the specified email address:

ruby_block 'fail the run' do
  block do
    raise 'deliberately fail the run'
  end
end

etcd Locks

The following example shows how to prevent concurrent Chef Infra Client runs from both holding a lock on etcd:

lock_key = "#{node.chef_environment}/#{node.name}"

Chef.event_handler do
  on :converge_start do |run_context|
    Etcd.lock_acquire(lock_key)
  end
end

Chef.event_handler do
  on :converge_complete do
    Etcd.lock_release(lock_key)
  end
end

HipChat Notifications

Event messages can be sent to a team communication tool like HipChat. For example, if a Chef Infra Client run fails:

Chef.event_handler do
  on :run_failed do |exception|
    hipchat_notify exception.message
  end
end

or send an alert on a configuration change:

Chef.event_handler do
  on :resource_updated do |resource, action|
    if resource.to_s == 'template[/etc/nginx/nginx.conf]'
      Helper.hipchat_message("#{resource} was updated by chef")
    end
  end
end

attribute_changed event hook

In a cookbook library file, you can add this to print out all attribute changes in cookbooks:

Chef.event_handler do
  on :attribute_changed do |precedence, key, value|
    puts "setting attribute #{precedence}#{key.map { |n| "[\"#{n}\"]" }.join} = #{value}"
  end
end

If you want to setup a policy that override attributes should never be used:

Chef.event_handler do
  on :attribute_changed do |precedence, key, value|
    raise 'override policy violation' if precedence == :override
  end
end

Was this page helpful?

×









Search Results