summaryrefslogtreecommitdiff
path: root/docs/dev/design_documents/event_handler_recipe_dsl.md
blob: da9d2b09d69b8780c627401e4c6498b9f5233629 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Recipe DSL method for event handler hooks

Allow cookbook authors to easily add custom logic on Chef events.

## Motivation

Chef has an extensive [event dispatch mechanism](https://github.com/chef/chef/blob/main/lib/chef/event_dispatch/base.rb).
But incorporating some custom logic against any of the events is an onerous process, which involves
subclassing the based event handler and adding it via the config. This RFC
proposes a recipe DSL method to ease this. For new Chef users, this will reduce
the entry barrier.

## Specification

Currently, `chef-client` sets up couple of default handlers -- e.g. doc, base -- during
initialization. An additional empty event handler -- a subclass
of the base handler without any custom logic -- can be added alongside the
existing handlers, which will used as a placeholder for user-specific hooks.

A top level (::Chef) method will be introduced (`event_handler`) to wrap the
main event handler DSL (`on`). Users can tap into one of the event types
-- as specified in base dispatcher -- using this DSL to execute their custom logic.

The additional top level method(`Chef.event_handler`) will allow the handler
DSL usage in and outside of recipes, and also ease writing backward-compatible
changes for the `on` method if need be.

The following is an example of sending hipchat notification on chef run failure.

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

The following is another example of taking a distributed lock via `etcd`, to 
prevent concurrent chef runs in different nodes.

```ruby
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
```

The following is another example of sending a hipchat alert on a key config change.

```ruby
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
```