Well said Zac!
Zac Stevens firstname.lastname@example.org wrote:
On Tue, Mar 19, 2013 at 9:34 PM, Jay Feldblum <email@example.com:firstname.lastname@example.org> wrote:
But a definition is essentially a parameterized recipe template (macro). Not an abstraction. That’s why I talked about resources and providers being an abstraction, but talked about definitions being merely a grouping of related resource declarations.
An example of something suited to be a definition would be: the apache_conf definition in the apache2 cookbook. The right level of abstraction for this particular case is to call a procedure (macro) that simply declares another resource with some predefined attributes and some other parameterized attributes. Every apache config file change needs to trigger a reload or restart of the service, and there may be many such config files, so wrapping that up in a definition (macro) is useful.
This is a good example. Some others, that I’ve used…
- Accumulating template variables
This pattern is documented here: http://docs.opscode.com/essentials_cookbook_definitions_example_one_definition.html
- Setting node attributes or run state
In this case, the definition might not contain any resources, but instead wraps up setting some attributes, or stashing some data for other recipes to use later. Why not use plain old ruby methods, defined in libraries? They’re much harder for those new to ruby to write in the first place, and the syntax in recipes is different (which has pro’s and con’s).
- “How do I run a recipe multiple times with different data?”
I’ve heard this question a number of times, on IRC and from co-workers. After working through getting a recipe to work (at all), the next requirement is to “run” it more than once, with different data. The smallest increment required to achieve this involves changing the recipe into into a definition. Could they move straight to LWRPs? Sure, but that’s a bunch more to learn, particularly for folks who are early on the ruby learning curve, and have not yet properly apprehended the resource/provider model.To my mind, "Definitions are just crappy LWRPs" is the second most irritating meme in the Chef community. If we were to remove them just because they can be misused, what of all the other Chef features that fall into that category? I've seen terrible sins committed using execute/script when more appropriate resources were available - should they go? A whole class of criticism of Chef is the ability to use arbitrary ruby in our recipes. Should that ability go away too?
Definitions have their own place in Chef’s conceptual model, separate from Resources and Providers. Some new users do struggle with their purpose, which isn’t at all surprising - the docs are not amazing, apache_site is a poor example (that probably should be an LWRP), and many people seem to think that Definitions should be ignored entirely, in favour of LWRPs. I think the problem is communication: the feature is sound, the guidance needs improvement.
So, my arguments in favour of keeping definitions are that they have a distinct (albeit under-appreciated) purpose, and that they can ease the learning curve for new users.