2016-02-20

Which cookbook did this?

Have you ever come across some settings file where you read something like this:

# ------------------------------------------------------------------
# DO NOT EDIT! Managed by Chef.  
# All changes will be overwritten.
# ------------------------------------------------------------------

Well I have. Quite a few times. And due to the way the system I work with is set up it is not always easy to find out which cookbook actually manages this settings file.

As a means to make things easier to all the sysadmins and future Chefs I decided that there is a need for a better header in all our templates. This is the standard header I have implemented in my templates:

# ------------------------------------------------------------------------------
# DO NOT MODIFY THIS FILE!
# Generated by Chef for node: <%= node['machinename'] %>
# Local modifications WILL be overwritten!
# ------------------------------------------------------------------------------
#
# Debug info (in case this file does not contain what you expected):
# ------------------------------------------------------------------------------
# Cookbook::recipe : <%= @cookbookname %>::<%= @recipename %>
# Cookbook version : <%= node.run_context.cookbook_collection[@cookbookname].metadata.version %>
# Chef environment : <%= node.chef_environment %>
# ------------------------------------------------------------------------------

And here is how I use this in a template resource:

#
# Cookbook Name:: my_cookbook
# Recipe:: default
#

template "/path/to/cfg/my_settings_file" do
  source "my_settings_file.erb"
  variables(
    :cookbookname => self.cookbook_name,
    :recipename => self.recipe_name
  )
end

And here is a sample result for "my_cookbook" version "0.1.0" in environment "dev":

# ------------------------------------------------------------------
# DO NOT MODIFY THIS FILE!
# Generated by Chef for node: myhost.example.com
# Local modifications WILL be overwritten!
# ------------------------------------------------------------------
#
# Debug info (in case this file does not contain what you expected):
# ------------------------------------------------------------------
# Cookbook::recipe : my_cookbook::default
# Cookbook version : 0.1.0
# Chef environment : dev
# ------------------------------------------------------------------

Not only does this make it easier to trace the origin of a particular cookbook but I can also see which version is actually applied and which environment the node belongs to. This makes it so much easier to debug those WTF moments when things do not turn out the way you expect them to. Typically that is the case when you have a version restriction that you have forgotten to update in your environment definition so you are still using an old version of the cookbook.

Obviously there is room for improvement. It would be nice if I did not need to define any variable for this to pass to the template. Still I find this extra work well worth the effort whenever I need to debug something.

I have successfully tested this with chef 11.16.4 and 12.7.2 but there is a risk that the templates will stop working in a future version of Chef, as pointed out in an answer to this Stack Overflow question: How to access Chef metadata from a template.