loop over hash in defined order in ruby template - ruby

I have a ruby template (.erb) that I want to iterate over a hash. It should produce the same output file each time the puppet agent runs.
What I currently have is the following. This is my template (part of rsyslog config if anyone is wondering):
<% log_files.each do |log_file, tag| -%>
# <%= log_file %>
$InputFileName <%= log_file %>
$InputFileTag <%= tag %>:
This template is rendered with a hash that looks like this:
log_files => {
'/root/apache_auth.local' => 'httpd',
'/root/install.log' => 'hugo',
},
(Not real logfiles). This works and produces the config file I want. The problem with this is that each time I call the puppet agent, the order of the log files in the hash is changed, so the config file gets rewritten, and subsequently the daemon gets restarted. The functionality stays the same, but I would rather not have the config file rewritten and rsyslog restarted each time the puppet agent runs.
Now I assume that this is unsolvable with hashes, as their nature is that they do not have a defined order. What other options do I have to achieve what I want?

Since the scriptlets inside an ERB template consist of Ruby code, this is essentially a Ruby question. The possible answers therefore depend on which version of Ruby is running underneath your Puppet catalog compiler. However, although there may be better alternatives in newer Ruby, this variation on your code will work in any Ruby supported by Puppet since Puppet 2.7:
<% #log_files.sort.each do |log_file, tag| -%>
# <%= log_file %>
$InputFileName <%= log_file %>
$InputFileTag <%= tag %>:
<% end -%>
The key here (no pun intended) is the sort.

Related

Best way to write "if condition" within chef template .erb file

I am using a template node.erb file within Chef.
I have created an if condition within the chef node.erb file but it is not working as expected.
<% if (node['my_port'] > 0) %>
- port:8000
<% end -%>
Within, my chef attributes, I have listed node['my_port'] = 8200
Please suggest what I might be doing wrong.

.erb equivalent to the PHP $_GET["name"];

I have a page set up in PHP which pulls data from the URL and echos it in HTML. Is there a .erb Ruby equivalent to this?
<?php echo $_GET["name"];?>
Is this possible? Thanks!
In ERB, it looks like this:
<%= variable_name %>
If you want to perform some action without printing the result, you do this
<% #user.sign_up %>
Notice the difference being the =

Passing binding or arguments to ERB from the command line

I have been playing around with erb from the command line recently. I wanted to make a dirt simple erb template, for example the following:
<%- name = "Joe"; quality = "fantastic" -%>
Hello. My name is <%= name %>. I hope your day is <%= quality %>.
This works if I run
erb -T - thatfile.erb
what I want to do is to make name and quality be passable from command line arguments, so that I could do something like:
./thatfile.erb "Bill" "super"
from the bash prompt and do the same thing.
I am aware that I could write a ruby script that would just read that template in and then use ERB.new(File.read("thatfile.erb")).result(binding), or writing the template after an END and doing likewise, but I'm looking for a more lightweight approach if it exists, because I don't want to write two files for each erb script that I create for this purpose.
Alternatively, you can use a ruby script and load it in as a library.
# vars.rb
#hello = 'kirk'
# template.html.erb
<div><%= #hello %></div>
$ erb -r './vars' template.html.erb
Please note that Ruby 2.2 and newer provide a much nicer solution that was implemented according to this:
erb var1=val1 var2=val2 my-template.erb
I went with the BASH command-line shortcut for environmental variables.
Outside:
STUFF=foo,bar erb input.html.erb >output.html
Inside:
<%
stuff = ENV['STUFF'].split(',')
%>
After a few minutes e-searching I determined the other solutions are all variations on "write the erb wrapper command yourself." Could be wrong, but I ain't going back.
If you are using unix, try following:
$ cat 1.erb
Hello. My name is <%= name %>. I hope your day is <%= quality %>.
$ (echo '<% name="Joe"; quality="fantastic" %>' && cat 1.erb) | erb
Hello. My name is Joe. I hope your day is fantastic.

put Ruby configuration into non-ruby configs

I'd like to be able to have configuration (with the ability to code in Ruby) in one place. Since different configs (like bash scripts) don't understand Ruby, I'd have to prepopulate them. Is there an easy-to-use tool for this?
I've found ruby-parseconfig but that's not what I'm looking for.
Looks like you can do this with chef templates.
Example:
#
# /etc/sudoers
#
# Generated by Chef for <%= node[:fqdn] %>
#
Defaults !lecture,tty_tickets,!fqdn
# User privilege specification
root ALL=(ALL) ALL
<% #sudoers_users.each do |user| -%>
<%= user %> ALL=(ALL) <%= "NOPASSWD:" if #passwordless %>ALL
<% end -%>

undocumented ERB syntax: <%=h ... %>

http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html lists a set of Recognized Tags - however, this list seems incomplete; for one thing it's missing the dash variant (<%- ... -%>, which suppresses line breaks IIRC).
Now I've come across another seemingly undocumented variant:
<%=h some_variable %>
<%= link_to h(some_variable) ... %>
Google wouldn't tell me what that was all about; can anyone point me to an explanation?
It's not an ERB syntax. It is <%= ... %> and inside it is calling the ERB::Util.hmethod
h here is just a regular method, in fact it's an alias for html_escape.
http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB/Util.html#M000868

Resources