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.