Chef and Erb Templates. How to Use Boolean Code Blocks

Chef and erb templates. How to use boolean code blocks

Try this:

<% if node[:monit][:server]=='nginx' -%>

nginx_text=<%= node[:nginx][:text] %>

<% end -%>

<% if node[:monit][:server]=='redis' -%>

redis_text=<%= node[:redis][:text] %>

<% end -%>

Code wrapped in <% %> or <% -%> is a statement that is evaluated. Code wrapped in <%= %> is code that is evaluated and the result is placed into the file. Harcoded strings dont have to be wrapped in erb tags if they are constant, but Ruby code must be wrapped in erb tags if you want the result of that code to go into your file

Chef template - Conditionally inserting a block of text

assuming you have an attribute

node[:test][:bool] = true

in the template would have to do

<% if node[:apache][:bool] -%>
ServerAlias ​​<% = node[:apache][:aliasl]%>
<% end -%>

another option is to check if the attribute is null

<% unless node [:icinga][:core][:server_alias].nil? %>
ServerAlias ​​<% = node[:icinga][:core][:server_alias]%>
<% end%>

Write value for template using erb+Chef if value is set

I'm not sure what's wrong with your approach, but if you want a one-liner, this should work:

<%= "c.NotebookApp.certfile = #{node[:ipynb][:NotebookApp][:certfile]}" if node[:ipynb][:NotebookApp][:certfile] %>

For boolean expressions in Ruby, nil and false values translate as false, everything else is true. If you have any value in node[:ipynb][:NotebookApp][:certfile], it will evaluate to true and print the string. Otherwise, it will print nothing.

erb file with chef syntax

Okay, so let's rewind a bit. The first thing is that you generally don't want to reference node attributes directly in templates. In some cases like attributes coming from Ohai it can be okay as a shorthand, but for important data I would also pass it in via the variables property like this:

template '/etc/whatever.conf' do
source 'whatever.conf.erb'
variables a: node['a']
end

With that in place we've now expose the data as a template variable. The second piece of improving this is to let Ruby do the heavy lifting of generating YAML. We can do this using the .to_yaml method in the template:

<%= @a.to_yaml %>

That should be all you need!

Chef and ruby templates - how to loop though key value pairs?

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:

  • Use an array instead of the hash. In an array, the order is guaranteed to be kept. If you don't use the name anyway (i.e. the key in your original hash), you can simply use a hash and be safe here. When going this road, we can loop over the array in the template and generate the count from that.
  • If the order doesn't matter, you should use the key in the hash to name the server as generated into your template. Right now, you use 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.

Using an Array

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.

Using a Hash

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.

Passing data to the template

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


Related Topics



Leave a reply



Submit