Use your runlist as an attribute in a Chef recipe

Use your runlist as an attribute in a Chef recipe

Here is a corner case that came up recently for us in Chef. How do we set an attribute in a template to a value if a specific cookbook/role was used.

A little background. We use role cookbooks in Chef. This allows us to do all kinds of overrides and versioning. All of this works great. We gain all the benefits of  overriding attributes and versioning of the roles. So normally if we have a specific value needed in a “role” it is very easy. But we came up with an edge case that required a little deeper thinking.

With a lot of distributed systems one of ours requires an advertised hostname. Normally we just set this to the fqdn

advertised.host.name=<%= node['fqdn'] %>

But we came up to an instance where we want this set to “localhost”. The first idea was to create an additional attribute to store a state and but an if in the template checking for it. But that seemed like a lot. This is needed for a specific role, so can we just use the runlist to see if the role is in the runlist?

Turns out the answer is yes: node[‘recipes’] returns a list of the recipes in the expanded ran list. By expanded, I mean that if you use a traditional role and it contains 5 recipes, all five will be listed in this attribute. This list can be rather expansive. This is where a proper naming convention in your recipes and roles can help you. Because we do I was able to simply use the .include method on the string.

<% if node['recipes'].include? "my-role-cookbook" %>
advertised.host.name=localhost
<% else %>
advertised.host.name=<%= node['fqdn'] %>
<% end %>

This works great. If you are using traditional roles, you can do the same thing just change node[‘recipes’] to node[‘roles’].

<% if node['roles'].include? "my-role" %>
advertised.host.name=localhost
<% else %>
advertised.host.name=<%= node['fqdn'] %>
<% end %>
Comments are closed.