Create A Data Bag Item if Missing


#1

I am trying to write a recipe which (among other things) checks a if a data bag item is present. In a nutshell it's a data bag for storing properties of each host, and each host should have an item in this data bag. If they do not, I need the host to create a new data bag item.

I've tried different variations on the data_bag and data_bag_item helpers, ie.

    if !data_bag_item('host_properties', node['hostname'])



    if data_bag_item('host_properties', node['hostname']).nil?



    hp = data_bag('host_properties)
    me = hp[node['hostname']]

But with that, chef-client always fails at compile time with a 404 any time the item doesn't exist, so it never even gets to the point of actually running the recipe.

I dug in to the Chef::DataBagItem class - there is a validate_id! method but it requires an "id_str" parameter, but it's not clear what id_str is, exactly. Running the .new() method does create a new data bag item, but also overwrites the data bag if it already exists.

Am I going about this the wrong way? I'm new-ish to Chef (less than a year) so maybe there's a better, more standard way of doing this?


#2

Hi,

You can use ruby_block to let this check happen in runtime :

You code could be for example :
ruby_block "Check Databag - #{recipe_name}" do
block do
# Retrieve databag item for current host
databagItem = begin
data_bag_item('host_properties', "#{node.hostname}")
rescue Net::HTTPServerException
end
# Create or Update databag item
if databagItem.nil?
# Write here your update statements...
databagItem = Chef::DataBagItem.new
databagItem.data_bag("host_properties")
end
databagItem["#{node.hostname}"] = {} if databagItem["#{node.hostname}"].nil?
databagItem.save
end
action :run
end


#3

Perfect, thanks!!