My Profile Photo

Spencer Owen

The art of progress is to preserve order amid change and preserve change amid order - Alfred North Whitehead

CHEF notify :before resource

Update This blog article was written before chef 12.6 which now includes a :before notification timer. Take a look at how it works here:

Chef is awesome. The one feature that chef 12 is missing is the ability to do a conditional notify before another resource. I don’t blame chef since no other configuration management tool I’ve tried supports this either. Normally this should be provided by the package.

Example scenario:

Windows machine with a custom DLL that is managed by a cookbook. The dll is needed by a service that is also managed by the cookbook.

What do you do if you need to stop the service before you replace the dll. While chef cookbooks run in order, there is no way to determine that a resource is about to be updated. You can use null resources, and send a notify to stop a service, but you can’t know that the service needs to be restarted until after the file is replaced.

Option A: Ask the developer who made the dll to make an MSI package that handles the services (not likely to happen).
Option B: Use the food taster design pattern. (I just made that term up)

Hundreds of years ago, kings and leaders would have prisoners taste their food before they ate so they could determine if the food was poisoned. We will use the same principle to determine if a file is about to be changed.


powershell_script 'stopService' do
  guard_interpreter :powershell_script
  code <<-EOH
    Stop-Service 'foo'
  only_if "(Get-Service -Name foo)"
  action :run

cookbook_file 'c:\\windows\\foo.dll' do
  source 'foo.dll'
  action :nothing

cookbook_file 'c:\\windows\\foo-chef.dll' do
  source 'foo.dll'
  action :create
  notifies :run, "powershell_script[stopService]", :immediately
  notifies :create, "cookbook_file[c:\\windows\\foo.dll]", :immediately

powershell_script 'startService' do
  guard_interpreter :powershell_script
  cod <<-EOH
    Start-Service 'foo'
  only_if "(Get-Service foo.status -eq 'Stopped'"
  action :run

Here we have 2 identical files c:\windows\foo-chef.dll c:\windows\foo.dll

If the foo-chef.dll is updated, then chef stop the service and replace the real dll

Additional Resources
updated_by_last_action? compile time vs run time