Links

Licence

Iteration in Puppet has been a long standing pain point, Puppet 4 address this by adding blocks, loops etc. Here I capture the various approaches to working with some complex data in Puppet before and after Puppet 4

To demonstrate this I’ll take some data from a previous blog post and see how to deal with it, here’s the data that will be in $domains in the examples blow:

Puppet 4 – each loop

It’s quite readable and obvious what’s happening here, it’s more typing than the create_resources example but I think this is the preferred way due to clarity etc

Below this we get into the more academic solutions to the problem, mainly showing off some Puppet 4 features.

Puppet 4 – wildcard shortcut

If listing every key is tedious like above and if you know your hashes map 1:1 to the defined type parameters you can short circuit things a bit, this is quite close to the create_resources convenience:

each($domains)|$name, $domain|{
mail::domain{$name:*=>$domain}}

The splat operator takes all the data in the hash and maps it right onto properties of the define type, quite handy

Puppet 4 – wildcard and defaults

Your data might not all be complete so you’d want to get some defaults merged in, this is something create resources also supports so this is how you’d do it without create_resources:

Puppet 4 – Native DSL create_resources()

Puppet 4 supports functions written in the native DSL, this means you can use the above and generalize it a bit and end up with a reimplementation of create_resources. Not sure I’d recommend this but it does show some techniques that’s related:

The magic here is the Resource[$type] that lets you reference a type programatically. It also works for classes.

So this is close as I can tell an equivalent to create_resources.

Conclusion

That’s about it, there are many more iteration tricks in Puppet 4 but this shows you how to achieve what you did with create_resources in the past and a couple of possible approaches to solving that problem.

Not sure which I’d recommend, but I suspect the choice comes down to personal style and situation.

The data and the modules are basically linked so that’s not a surprise

There doesn’t seem to be a way to remove properties without updating the data unless you follow the long route where your code in the each block lists the supported properties and fetch it explicitely from the data like in the first Puppet 4 example.

For adding properties to the module and not the data, if you make those properties have sane defaults or default to undef and your module not breaking when those are default the techniques above should work

Thanks for the response. We have added properties using the exact technique as you mentioned. We have been able to removing properties by reversing the process, ignoring them in the new version then removing them from the data after it is released.

As somebody who teaches Puppet training courses on a regular basis, I’d like to note that it’s nearly impossible to teach create_resources() to new users of Puppet. There’s so much magic there that it’s hard for folks to wrap their head around it.

But, everybody basically understands .each-style iteration, and it’s easy to teach. When folks don’t understand iterators, it’s typically because they’ve got no previous scripting or programming experience at all – in which case teaching them about iterators is still easier and more obviously logical than trying to explain how create_resources() does a bunch of magic behind the scenes.

So Puppet 4 is significantly easier for new users in that sense, even for those who aren’t yet sure why they’d need iteration in Puppet.