Container LWRPs and notifications

I’m starting to use LWRPs as simple containers for multiple
"first-class" resources. This is, I understand from the recent Chef
training in Ghent and a few online references, the currently suggested
method for aggregating resources with a level of isolation between the
recipe and the invoked resources.

One things I don’t think I’ve seen any firm documentation on is
notifications - one of the reasons LWRPs are suggested over and above
Definitions. More specifically, notifications from the contained
resources to their container LWRP and up the hierarchy.

I know that, near the end of the LWRP action definition, I’m supposed
to set new_resource.updated_by_last_action(boolean). But how do I what
to set if I’m simply containing, say, a pair of templates? I don’t
want the recipe that contains the LWRP itself to have to break
isolation and use any knowledge about the contained resource, and I
think I’m right to try and keep them separate.

I suppose I need the boolean OR of each of the contained resource’s
updated_by_last_action? calls, but I don’t /have/ a reference to each
resource. Unless I look inside and start manipulating the resources()
collection - and that seems a little low-level for what’s touted as a
higher-level interface to custom Resources and Providers.

Any thoughts? Have I missed something obvious?

Cheers,
Jonathan

Jonathan Matthews
London, UK
http://www.jpluscplusm.com/contact.html

On Mon, Feb 14, 2011 at 3:12 PM, Jonathan Matthews
contact@jpluscplusm.comwrote:

I'm starting to use LWRPs as simple containers for multiple
"first-class" resources.

It seems our messages passed each other like ships in the night.

I suppose I need the boolean OR of each of the contained resource's

updated_by_last_action? calls, but I don't /have/ a reference to each
resource. Unless I look inside and start manipulating the resources()
collection - and that seems a little low-level for what's touted as a
higher-level interface to custom Resources and Providers.

Any thoughts? Have I missed something obvious?

I had very similar thoughts. As far as I can tell, beyond whatever else I'm
also missing, what you're missing is that the resource creation methods
actually return the created resource, so you can just do this:

    t = template "foo" do
        ...
    end

and then you have a reference to the Chef::Resource::Template object in t.

However, you need to tell the resource to run whatever action needs running
before the result of updated_by_last_action? is meaningful. So instead of
this:

        t = template "foo" do action :create end

you need to do this:

       t = template "foo" do action :nothing end
       t.run_action :create

And it was the need to do this that led me to ask on-list if there was a
better solution. One that occurs to me is to store the created resources on
an instance variable, and then define a custom updated_by_last_action?
method, something like this:

@resources << template "foo" do action :create ... end

def updated_by_last_action?
super
@resources.map { |r| r.updated_by_last_action? }.inject(false, :|)
end

--
Mark J. Reed markjreed@gmail.com

On Monday, February 14, 2011 at 1:33 PM, Mark J. Reed wrote:
On Mon, Feb 14, 2011 at 3:12 PM, Jonathan Matthews contact@jpluscplusm.com wrote:

I'm starting to use LWRPs as simple containers for multiple
"first-class" resources.

It seems our messages passed each other like ships in the night.

I suppose I need the boolean OR of each of the contained resource's

updated_by_last_action? calls, but I don't /have/ a reference to each
resource. Unless I look inside and start manipulating the resources()
collection - and that seems a little low-level for what's touted as a
higher-level interface to custom Resources and Providers.

Any thoughts? Have I missed something obvious?

This might be tricky. LWRPs are similar to a mini chef run, in that they create the resources in a compile phase, but then they inject them into the resource collection of the "main" Chef run.

However, you may be able to attach the resources from your LWRP resource to the ones inside your LWRP provider. You can get the list of a resource's notifications via Resource#immediate_notifications and Resource#delayed_notifications. The actual notification objects have Notification#resource, Notification#action and Notification#notifying_resource methods to get at their data.

I realize this isn't quite ideal, if you have any suggestions about what would be a more ideal API (preferably without sacrificing flexibility), I'd be interested to hear about it.

--
Dan DeLeo