What is the correct way to check for the existence of a nested attribute in Chef?

Node attribute object is HashMap. You can use ruby native API to lookup nested attributes.

Chef Node Object provides a number of helper methods like:

node.attribute?()
node[:foo].attribute?(:bar)
node[:foo].member?(:bar)

There is also a new method node.debug_value() in chef 11 to help you debug node attributes which is also helpful:

node.debug_value(:foo, :bar)

Details can be found from the article Chef 11 In-Depth: Attributes Changes


The way I've solved this more recently has been to always set default values for attributes used in a cookbook where possible.

For example, cookbook/attributes/default.rb would contain:

default[:parent][:child] = nil

And the in the recipe, any check for the attributes value can be reduced to:

node[:parent][:child].nil?

Of course, it's usually far more useful to have a usable default value and to not have to check at all.


Check out the chef-sugar cookbook deep_fetch extension that allows for safe references to deep attributes.


The correct "modern" way to do this is to use the exist?() helper:

if node.exist?('foo', 'bar', 'baz')
  # do stuff with node['foo']['bar']['baz']
end

This supersedes the old chef-sugar deep_fetch mechanism and has been built into chef-client for a very long time at this point.

There is also a read() helper to get the value out, which will return nil if any intermediate key does not exist:

fizz = node.read('foo', 'bar', 'baz')

It is identical to the Hash#dig method which was later added to ruby which is also supported as an alias:

fizz = node.dig('foo', 'bar', 'baz')