17 Jul 2012LWRP notifying on changed resources
Opscode Chef's light-weight resource providers are awesome. They allow you to compose a more complex resource from simpler resources. The one thing that has always annoyed me is that you can no longer use notifications to indicate which resources are actually changed or so I thought. Then along came a post at a gist by yfeldblum that demonstrated how to do this.
Of course I wanted to simplify this as almost all of our LWRPs will need this so I converted it into a method that can be added in the library directory.
def notifying_action(key, &block) action key do # So that we can refer to these within the sub-run-context # block. cached_new_resource = new_resource cached_current_resource = current_resource # Setup a sub-run-context. sub_run_context = @run_context.dup sub_run_context.resource_collection = Chef::ResourceCollection.new # Declare sub-resources within the sub-run-context. Since they # are declared here, they do not pollute the parent run-context. begin original_run_context, @run_context = @run_context, sub_run_context instance_eval(&block) ensure @run_context = original_run_context end # Converge the sub-run-context inside the provider action. # Make sure to mark the resource as updated-by-last-action if # any sub-run-context resources were updated (any actual # actions taken against the system) during the # sub-run-context convergence. begin Chef::Runner.new(sub_run_context).converge ensure if sub_run_context.resource_collection.any?(&:updated?) new_resource.updated_by_last_action(true) end end end end
Now all the providers can simply use something like the following to define your actions in your provider. This will propagate notifications if any sub-resources have changed.
notifying_action :run do file "/tmp/something" do owner "root" group "root" mode "0755" action :create end end