How to check if chef databag exists?

I want to check if there is a slaves databag. If there is one, and it contains data then I want to execute an action for every slave.

I have the following code:

slaves = data_bag('slaves')

if slaves.length > 0
   for slave in slaves
      ...xyz..
   end
end

This works, except when the databag doesn't exist yet. How can I check if the databag exists yet? Or am I doing this completely wrong?


When you attempt to access a databag that does not exist yet, Chef will raise an exception, depending on which type of Chef Client you are running.

For instance, in Chef Solo, you will raise an exception named Chef::Exceptions::InvalidDataBagPath, whereas with Chef Client (against a Chef Server a Net::HTTPServerException exception will be raised, as the object is not found on an API call to the server.

So you could wrap the setting in a Ruby block, like so:

slaves =  begin
            data_bag('slaves')
          rescue Net::HTTPServerException, Chef::Exceptions::InvalidDataBagPath
            [] # empty array for length comparison
          end

if slaves.length > 0
  for slave in slaves
    ...xyz..

However, this returns an empty array, as you are using it for .length comparison.

If the goal is that if there are any slaves, then iterate on them, I'd do something like this instead:

slaves =  begin
            data_bag('slaves')
          rescue Net::HTTPServerException, Chef::Exceptions::InvalidDataBagPath
            nil
          end

if slaves
  slaves.each do |slave|
    ...xyz..

This returns a nil in the event the data bag doesn't exist, instead of an Array, which would be the correct return in the event the data bag exists, but is empty, and will only execute the xyz steps if not nil.

(I also changed the for slave in slaves to the more idiomatic Ruby .each iterator.)

You can look at the data bag loader code here if interested.