reflection of erb variables - ruby

I'm using a puppet template, which does an erb interpretation of the template file. I'd like to know all the variables available to me, however, there are variables available (e.g., fqdn) that are not listed by any of the reflection methods I'm aware of, specifically, none of these:
<% Module.constants.each do |v| %># module constant: <%= v %>
<% end %>
<% Kernel.local_variables.each do |v| %># local variable: <%= v %>
<% end %>
<% Kernel.instance_variables.each do |v| %># instance variable: <%= v %>
<% end %>
<% Module.class_variables.each do |v| %># class variable: <%= v %>
<% end %>
<% Kernel.global_variables.each do |v| %># global variable: <%= v %>
<% end %>
Is there an extra reflection method for erb that will reveal these to me?

The "See all client variables" should do what you want

Don't really know about puppet templates, but if fqdn is a local variable, then calling local_variables (as in self.local_variables) should display it.

I don't know as much as I'd like to about erb's built-in means of reflection, but with Puppet, I think the hash returned by scope.to_hash is probably what you want. From the templating reference:
<% scope.to_hash.keys.each do |k| -%>
<%= k %>
<% end -%>
Alternately, if you just want a one-time look at the variables the agent node supplies, you can run facter on the node; that's how Puppet gets all that info in the first place.

Related

Puppet ruby template with ip validation - skip failed values not error and stop

I have the following code in a Puppet (ruby) .erb template with a validate function on each value that is iterated over from an array. I want it to continue with next values and preferably issue a warning, or silently continue. The code below errors and stops if an entry fails validation.
For example if the array is $nameservers = ['1.1.1.1','/some.domain/2.2.2.2'] I want it to only process the 1.1.1.1 entry.
This is actually so I can use the same input array for either /etc/resolv.conf or /etc/dnsmask.conf as determined by other logic in my manifest that gets processed by one of 2 templates (no, I'm not crazy) :).
I know that validation can be done in the manifest or on top scope variables, however I have a need to do this in the template.
search <%= scope.lookupvar('dns_search') %>
<% scope.lookupvar('nameservers').each do |server| -%>
<% if scope.function_validate_ip_address([server]) -%>
nameserver <%= server -%>
<% end -%>
<% end -%>
Cheers
I managed to get it working with the following code. The only thing I can't get to add is a trailing newline after the LAST entry only. Any comments on how this block could be improved appreciated.
search <%= scope.lookupvar('dns_search') %>
<% scope.lookupvar('nameservers').each do |server| -%>
<% begin -%>
<% if scope.function_validate_ip_address([server]) %>
nameserver <%= server -%>
<% end -%>
<% rescue => e -%>
<% scope.call_function('warning',[e]) -%>
<% next %>
<% end -%>
<% end -%>

Use a variable name in an erb include call

I'm using Sinatra and I'd like to include another erb file in one of my views but using a variable for the file name.
I was thinking something like this may work but I get an error saying no such file could be found.
<%= erb :'layout/nav/#{device_type}' %>
Currently I'm using the below switch statement to achieve the desired results but the above would be cleaner and less code.
<% case device_type
when 'mobile'%>
<%= erb :'layout/nav/mobile' %>
<% when 'tablet' %>
<%= erb :'layout/nav/tablet' %>
<% else %>
<%= erb :'layout/nav/desktop' %>
<% end %>
Thanks
Giles
I think that could work, you just need to use double quotes to interpolate strings.
Try
<%= erb :"layout/nav/#{device_type}" %>

erb idiom to handle undefined variable

I'm trying to write some puppet .erb, I'd like to handle this "environment" variable if it's:
undefined
a string with newlines
an array.
I've got as far as this:
<% Array(environment).join("\n").split(%r{\n}).each do |f| %>
one line: <%= f %>
<% end %>
But haven't gotten around the undefined case yet. I've tried this
<% if (defined?(environment)).nil? %?
<% Array(environment).join("\n").split(%r{\n}).each do |f| %>
one line: <%= f %>
<% end %>
<% end %>
but am still getting "(erb):11: undefined local variable or method `environment' for main:Object (NameError)" when trying to test it like this:
ruby -rerb -e "environmentUNDEFINEME= [ 'cronvar=cronval', 'var2=val2' ];
puts ERB.new(File.read('templates/job.erb')).result"
Sorry this is so basic, but somebody's got to ask the easy questions. Any help?
I would do this:
<% if defined?(environment) %>
<% Array(environment).each do |f| %>
one line: <%= f %>
<% end %>
<% end %>
I didn't understand why you joining on new lines and then splitting on them again, so I removed it from the example.

Chef and erb templates. How to use boolean code blocks

I am new to chef, ruby, ruby DSL, and erb. I come from python.
In a ruby erb template I want to do something like this.
<% if node[:monit][:server]=='nginx' -%>
ALL OF MY NGINX TEXT
<% end -%>
<% if node[:monit][:server]=='redis' -%>
ALL OF MY REDIS TEXT
<% end -%>
Clearly I am missing something about proper syntax.
Thanks
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

hash enumeration and using outside arguments

I have a form builder and the normal |f| variable. In the middle I'd like to iterate over some hash and get a list of keys by which to build the form. How can I incorporate "f" as an argument to the enumerator.
<%= form_for ..... do |f| %>
<% available_types.each do |k,v| %>
<%= f.text_filed :selection, :value => v %>
<% end %>
<% end %>
As you can see in the code above, "f" is outside of the scope. Ideas?
f should still be in the scope. You misspelled text_field though.

Resources