1) I have a data bag as follows:
"zookeeper":{
"server1":"111.111.111.111",
"server2":"222.222.222.222"
},
2) In my recipe I get the hash as follows.
data_bag("mydb")
db = data_bag_item("mydb", "rtb")
ZOOKEEPER = db['zookeeper']
3) Also in my recipe I have a template as follows:
template "/etc/zookeeper/conf/zoo.cfg" do
path "/etc/zookeeper/conf/"
source "zoo.cfg.erb"
owner "root"
group "root"
mode "0644"
variables :zookeeper => #{ZOOKEEPER}
end
4) I need to have my template look like this
server.1=111.111.111.111:2888:3888
server.2=222.222.222.222:2888:3888
My question is this. How do I pass the hash to the template so I can loop through the hash and create the temlplate? I am not a strong ruby coder.
for example:
count = 1
for server, ipaddress in zookeeper:
server.count=ipaddress:2888:3888
count = count + 1
There are some slight inconsistencies in your setup. In your data bag, you assign IP addresses a name (by using a hash in your JSON). However, you don't seem to use the name in your generated template at all. This has some implications which you should be aware of:
When using associative arrays (called hashes in Ruby or objects in Javascript), the order of the elements is generally not preserved and can significantly change when adding additional elements. While some effort is done on Ruby 1.9 to preserve the insertion order when looping over the hash, you shouldn't generally rely on that. This leads to two possible alternatives to improving your data bag. Which one to choose depends on your actual use case:
server<Number>
in your data bag but server.<Number>
in your template. That way, we can use the key to name your servers and possibly override the generated names.When using the array in your data bag, i.e. when you have something like this:
"zookeeper": [
"111.111.111.111",
"222.222.222.222"
],
you can loop over the array like this in your template:
<% @zookeeper.each_with_index do |ipaddress, index| %>
<%= "server.#{index}=#{ipaddress}:2888:3888" %>
<% end %>
This used the ERB template language to create your file. It used the each_with_index method to iterate over each element in the array.
When using the hash variant instead, assuming you have changed the keys in your data bag to match the syntax in your final generated file, you can loop over the hash like this:
<% @zookeeper.each_pair do |name, ipaddress| %>
<%= "#{name}=#{ipaddress}:2888:3888" %>
<% end %>
This uses the each_pair method of the Hash to loop over each key-value pair and thus generates a line of output for each of these pairs.
As a final remark, your syntax to pass data to the template in your recipe is odd. At first, you should never use names that start with an uppercase letter for variables (like your ZOOKEEPER
variable). In Ruby, these identify constants (like value constants, classes, modules, ...). Use a lowercase name instead. Ruby uses snake_case for variable names by convention.
When passing the value to your template, you can then just pass the variable:
db = data_bag_item("mydb", "rtb")
zookeeper = db['zookeeper']
template "/etc/zookeeper/conf/zoo.cfg" do
path "/etc/zookeeper/conf/"
source "zoo.cfg.erb"
owner "root"
group "root"
mode "0644"
variables :zookeeper => zookeeper
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With