Attributes are dead, long live Helper Libraries

Brian Mearns
3 min readAug 1, 2018

Avoid using attributes when all you really want is a single source of truth; attributes should be used for things that you expect users will want to tweak.

I’ve noticed a pervasive overuse of attributes in a lot of chef cookbooks, with an attributes/default.rb file defining dozens of different attributes. That means dozens of things that users of the cookbook can tweak to modify it's behavior. Are all combinations valid? Have all combinations been tested? How much additional logic and complexity were added to the cookbook to deal with all of these combinations?

The main driver behind this seems to be a conflation of attributes for variables. In software development, we learn not to hard code the same value in multiple places, but to encapsulate it in a shared variable (or constant); a basic application of the DRY principle (“Don’t Repeat Yourself”) . The rationale is sound: if you have to hardcode the path to the log directory in multiple places, what happens if you change it in one place but forget to change it in another? There’s a good chance something will break. So if you put it in a shared variable (or constant), you have a single source of truth, which is a Good Thing.

In chef, attributes can serve as a single source of truth: node['my_cookbook']['logging']['log_dir'] becomes the canonical way to refer to the log directory through out your cookbook.

The problem is, that’s not what attributes are for.

Yes, they function that way, in the same way that a heavy soled boot functions as a hammer. But that’s not what either of those are meant for.

Attributes in chef are meant as configuration parameters. Parameters, as in inputs to your cookbooks. If you’re using attributes to serve as your single source of truth…well, that truth may not be quite what you expect. Your “shared variable” has now become an input to your code. Is that really what you intended? If not, then attributes are not what you want.

Helper Library to the rescue

If you’re using attributes just so that you have a single source of truth across your entire cookbook, consider using the helper library pattern instead. The helper library pattern adds a library to your cookbook which exposes an object with methods for getting the shared data; the object exposed by the library acts as a single source of truth. It also provides a convenient place to define derived values — values that are derived from attributes or from other values and need to be derived in the same way in multiple places. Lastly, the helper library can encapsulate how (and if) information is pulled out of the node attributes, so you don’t have to clutter your recipes with a lot of attribute access. Your helper library could even do validation of attributes, all in one common place.

To create a helper library, add a file under the libraries/ directory in your cookbook. Typically called something like ${COOKBOOK_NAME}_helper.rb. A simple example of a helper library is below:

Using the helper library inside a recipe is as simple as accessing the methods you added to the Chef::Resource and Chef::Recipe classes:

Note that there is no need to include the library in the recipe; by adding it under libraries/ it is automatically loaded, and by adding it to the Chef::Resource and Chef::Recipe classes, it is automatically available inside recipes.

Conclusion

Attributes in chef are really great for their intended use: as user inputs to your cookbook. When they are misapplied to act as a single source of truth that is not meant to be modified by users of the cookbook, they lead to added complication and fragility.

For more information on chef libraries, see https://docs.chef.io/libraries.html.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Brian Mearns
Brian Mearns

Written by Brian Mearns

Software Engineer since 2007 ・ Parent ・ Mediocre Runner ・ Flower and Tree Enthusiast ・ Crappy Wood Worker ・ he/him or they/them

Responses (1)

Write a response

I found this quite helpful. However, I have a question. I’m finding that the helper class’s method is being evaluated before the node variable has the node attributes in it. This causes the chef-client to fail since it does not have ‘myapp’ in…

--