Search code examples
chef-infrawrappercookbookrecipe

How to wrap notifies or subscribes in chef cookbook


In keepalived cookbook there is such definition of keepalived service resource:

service "keepalived" do
    supports :restart => true
    action [:enable, :start]
    subscribes :restart, "template[keepalived.conf]"
end

It's probably ok for most people but I don't want to restart keepalived in case of small changes in configuration. Restarting will cause moving ip's from master server to slave and so on - on CentOS it's enough to reload service.

So I started wrapping it in my cookbook like this:

begin
    r = resources(:service => "keepalived")
    r.supports :restart => true, :reload => true
    r.subscribes :reload, "service[keepalived]"
rescue Chef::Exceptions::ResourceNotFound
    Chef::Log.warn "could not find service to override!"
end

But this called restart and then reload of service:

 Recipe: keepalived::default
     - restart service service[keepalived]
     - reload service service[keepalived]

I found here: https://github.com/chef/chef/blob/78ba88287781667e4aa344bc4ceff280fa7ac466/lib/chef/resource.rb#L316 that subscribes is converted into notifies so I tried to wrap notifies on template[keepalived.conf] with same result and without success ;/

Can any one help with that?


Solution

  • You can't "override" subscribe or notify calls. You can, however, remove them from the notification stack, but it's not a pretty thing to do. The run_context object has a collection of immediate and delayed notifications. You'll have to get at that, search through it, and remove the offending notification. And, since very little of that is in the public API, you'll risk it breaking with each update of Chef. Your best bet is to put in a PR with the cookbook asking the restart to be changed to reload, or at least giving the option of changing it to a reload.

    I will add exact example here:

    n = run_context.delayed_notifications('template[keepalived.conf]')
    n.first.action = :reload
    

    Additional tips:

    • use notifies_immediately or delayed_notifications for exact type of notyfication,

    • subscribes is silently converted into notifies on target resource, so you have to always overwrite proper notifes object.