January 26, 2011

Opscode Chef LWRPs and notifications

Wow, so @kallistec is my hero. I was trying to write a LWRP for my rsyslog cookbook in my Chef repo, and it WASN'T WORKING. The purpose of the LWRP was to allow other cookbooks to declare that they had text-only logfiles, and have the rsyslog LWRP then generate the appropriate imfile configuration stanza in /etc/rsyslog.d.

All well and good. However, this meant that inside my provider file, I had the following: (from rsyslog/providers/imfile.rb):


# Create new rsyslog snippet to configure imfile to follow a text log
action :create do
  template "/etc/rsyslog.d/#{new_resource.tag}.conf" do
    source "imfile-stanza.erb"
    cookbook "rsyslog"
    owner "root"
    group "root"
    mode 0644
    variables(
      :location => new_resource.location, 
      :tag => new_resource.tag, 
      :facility => new_resource.facility, 
      :priority => new_resource.priority, 
      :label => new_resource.label)
    notifies :reload, "service rsyslog", :delayed
  end 
end
...because in the default recipe for the rsyslog cookbook (/rsyslog/recipes/default.rb) I had:
  service "rsyslog" do
    supports :restart => true, :reload => true
    action  :enable, :start
  end 
...but this DIDN'T WORK. I kept getting errors that looked like this:
ERROR: Exception handlers complete
/usr/lib/ruby/gems/1.8/gems/chef-0.9.12/bin/../lib/chef/runner.rb:53:in `run_action': undefined method `run_action' for "service rsyslog":String (NoMethodError)
...when the chef client ran on the appropriate node. After much patience with me on IRC, @kallistec explained that the problem I was having was that when an LWRP is compiled and executed during a chef run, it has its own resource collection *distinct* from the 'larger' resource collection. As a result, the service which was getting declared in the default.rb wasn't getting pulled in to the resource collection during the run. At his suggestion, I put a service definition into the action provider action :create stanza, so I then had this in /providers/imfile.rb:
# Create new rsyslog snippet to configure imfile to follow a text log
action :create do
  service "rsyslog" do
    supports :restart => true, :reload => true
    action :nothing
  end 

  template "/etc/rsyslog.d/#{new_resource.tag}.conf" do
    source "imfile-stanza.erb"
    cookbook "rsyslog"
    owner "root"
    group "root"
    mode 0644
    variables(
      :location => new_resource.location, 
      :tag => new_resource.tag, 
      :facility => new_resource.facility, 
      :priority => new_resource.priority, 
      :label => new_resource.label)
    notifies :reload, "service rsyslog", :delayed
  end 
end
But that didn't work either! Finally, @kallistec advised that I change the notification syntax in the provider stanza back to the *old* (pre-chef-0.9.10) syntax. That meant changing:
    notifies :reload, "service rsyslog", :delayed
...to:
    notifies :reload, resources(:service => "rsyslog"), :delayed
AND THAT WORKED! Whew. Thanks again to @kallistec for patience, expertise and helpfulness. Also, thanks to @fujin for help getting the LWRP together in the first place!

Posted by jbz at 6:18 PM | Comments (1) | TrackBack