OxDEAD Unicornz

Have you ever seen so many?

Chef: Attribute Overrides in Recipes Is a Bad Idea

I like Chef, but some aspects of its internal kitchenary are pretty poorly documented (or I’m not good enough with Chef to understand why it should behave this exact way).

I’ve hit an annoying problem trying to fix library in a chef cookbook:

I had an attribute assigned in attribute file vault-cookbook/attributes/default.rb:

1
2
3
...
default['vault_name'] = 'foo'
...

and override in recipe vault-cookbook/recipes/some_recipe.rb:

1
2
3
...
override['vault_name'] = 'bar'
...

search_node() function is called from some_recipe.rb and described in a library vault-cookbook/libraries/library.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Chef
  class Recipe
    def search_node(vault_name=node['vault_name'])
      nodes_in_all_vaults = search(:node, 'recipes:vault-cookbook\:\:vault-member')

      Chef::Log.info "Node #{node['fqdn']} is in vault #{node['vault_name']}"

      nodes_in_all_vaults.each do | node_object |
        Chef::Log.info "Node #{node_object['fqdn']} is in vault #{node_object['vault_name']}"

        # some yadda-yadda code

      end

    end
  end
end

search_node() function gets vault name and performs some actions with nodes in this vault.

Now the magic

Guess if two log resource calls in library return same results for same node. Hell no!

1
Chef::Log.info "Node #{node['fqdn']} is in vault #{node['vault_name']}"

returns

1
Node node.fqdn.com is in vault bar

this is ok, override works. But

1
Chef::Log.info "Node #{node_object['fqdn']} is in vault #{node_object['vault_name']}"

returns

1
Node node.fqdn.com is in vault foo

override does not work because override from the recipe is not being applied to node objects found during search, they have vanilla set of attributes.

So if you want to avoid pitfalls keep your attributes in attribute files/roles/environments, not in recipes.

Just to be clear, mentioned issue appies to Chef 11, didn’t test on other versions.