align columns in a Puppet ERB template - puppet

I have the following code in a Puppet ERB template:
<% if #server.class == Array -%>
<% #server.each do |server| -%>
server <%= server %>
restrict <%= server %> <%= #restrict[1] %>
<% end %>
<% end -%>
In the configuration file, since the IP addresses are not all the same number of characters, I am not getting an aligned output:
server 123.123.1.1
restrict 123.123.1.1 mask 255.255.255.224 nomodify notrap noquery
server 123.123.345.33
restrict 123.123.345.33 mask 255.255.255.224 nomodify notrap noquery
server 123.123.345.33
restrict 123.123.345.33 mask 255.255.255.224 nomodify notrap noquery
As can be seen, the mask line is not aligned with the other mask lines.
How can I align them?

You can do anything you can do in Ruby code inside the ERB templates so this would work:
<% if #server.class == Array -%>
<% #server.each do |server| -%>
server <%= "%-14s" % server %>
restrict <%= "%-14s" % server %> <%= #restrict[1] %>
<% end %>
<% end -%>
i.e. you can format strings in Ruby similar to other languages. Ruby docs here.

Related

Unexpected token '/' in {FILE} while compiling ejs

I am working on this: https://www.youtube.com/watch?v=6FOq4cUdH8k
For some reason, the following line is causing the error in the title.
<% include ./partials/messages %>
Removing the line above solves the problem.
I have confirmed that it is not the messages file as there are no slashes in it.
<% if(typeof errors != 'undefined') { %>
<% errors.forEach(function(error){ %>
<%= error.msg %>
<% }); %>
<% } %>
as you can read in the official documentation
Includes are relative to the template with the include call. (This
requires the 'filename' option.) For example if you have
"./views/users.ejs" and "./views/user/show.ejs" you would use <%-
include('user/show'); %>.
You'll likely want to use the raw output tag (<%-) with your include
to avoid double-escaping the HTML output.
so instead of
<% include ./partials/messages %>
Write
<%- include ("./partials/messages") %>
Why?
Template tag <%- outputs the unescaped value into the template, whereas <% 'scriptlet' tag is used for control-flow, no output. The parenthesis and " " are used for filename location

Using puppet hash for epp templates

I have next code in erb template:
<% if #proxy_cache_path.is_a?(Hash) -%>
<% #proxy_cache_path.sort_by{|k,v| k}.each do |key,value| -%>
proxy_cache_path <%= key %> keys_zone=<%= value %> levels=<%= #proxy_cache_levels %> max_size=<%= #proxy_cache_max_size %> inactive=<%= #proxy_cache_inactive -%>
<% end -%>
How to porting it for epp template? Im find very low information for it. Please help.
Here's how you can do that:
Showing an example class and how to declare both an ERB and EPP template for comparison:
# manifests/init.pp
class foo () {
$proxy_cache_path = {
'apples' => 1,
'bananas' => 2,
}
$proxy_cache_levels = 2
$proxy_cache_max_size = 2
$proxy_cache_inactive = 2
# Showing use of ERB:
file { '/foo':
ensure => file,
content => template('foo/mytemplate.erb')
}
# Showing use of EPP, which requires an explicit parameters hash:
file { '/bar':
ensure => file,
content => epp('foo/mytemplate.epp', {
'proxy_cache_path' => $proxy_cache_path,
'proxy_cache_levels' => $proxy_cache_levels,
'proxy_cache_max_size' => $proxy_cache_max_size,
'proxy_cache_inactive' => $proxy_cache_inactive,
}),
}
}
Corrected* contents of the ERB file for comparison:
# templates/mytemplate.erb
<% if #proxy_cache_path.is_a?(Hash) -%>
<% #proxy_cache_path.sort_by{|k,v| k}.each do |key,value| -%>
proxy_cache_path <%= key %> keys_zone=<%= value %> levels=<%= #proxy_cache_levels %> max_size=<%= #proxy_cache_max_size %> inactive=<%= #proxy_cache_inactive -%>
<% end -%>
<% end -%>
(*The code in the question is missing the closing end.)
Contents of EPP file:
# templates/mytemplate.epp
<%- | Hash[String, Integer] $proxy_cache_path, Integer $proxy_cache_levels, Integer $proxy_cache_max_size, Integer $proxy_cache_inactive | -%>
<% include stdlib -%>
<% $proxy_cache_path.keys.sort.each |$key| { -%>
proxy_cache_path <%= $key %> keys_zone=<%= $proxy_cache_path[$key] %> levels=<%= $proxy_cache_levels %> max_size=<%= $proxy_cache_max_size %> inactive=<%= $proxy_cache_inactive -%>
<% } -%>
Things to note about the EPP template file content:
1) The parameters and their types are defined on the first line of the template. Use of this line is optional, but good practice.
2) Since we declared the types on the first line, it is unnecessary and redundant to test if $proxy_cache_path is a Hash.
3) We need to include stdlib in order to access the functions keys and sort. This is different to Ruby (ERB) where these methods are built-in to the language.
4) I simplified the code relative to the Ruby (ERB) because Puppet (EPP) has no sort_by function - and actually there was no need to use it in the ERB either, which could be re-written as:
<% if #proxy_cache_path.is_a?(Hash) -%>
<% #proxy_cache_path.sort.each do |key,value| -%>
proxy_cache_path <%= key %> keys_zone=<%= value %> levels=<%= #proxy_cache_levels %> max_size=<%= #proxy_cache_max_size %> inactive=<%= #proxy_cache_inactive -%>
<% end -%>
<% end -%>
Finally some tests:
# spec/classes/test_spec.rb:
require 'spec_helper'
describe 'foo', :type => :class do
it 'content in foo should be the same as in bar' do
foo = catalogue.resource('file', '/foo').send(:parameters)[:content]
bar = catalogue.resource('file', '/bar').send(:parameters)[:content]
expect(foo).to eq bar
end
end
And the tests pass.
See docs here.

How to place an EJS tag within another

I am using EJS as my templating engine. I am passing variables from node js to ejs like...
router.get("/AdminDatabase", function(req, res) {
res.render('Pages/AdminDatabase', {title: 'WebFormsAdmin', role: 'System Admin' });
});
I am building a role base control and for this I want to change the header of the page base on the role of user.
<% include ../partials/Common/header_<%= role %> %>
The problem is with the above segment. How can I place the variable role inside this EJS code segment?
My header files are
header_System Admin.ejs,
header_Survey Admin.ejs,
header_Survey Taker.ejs
A workaround would be to do a conditional render like so:
<% switch (role) {
case 'System Admin': %>
<% include ./partials/header_System_Admin %>
<% break; %>
<% case 'Survey Admin': %>
<% include ./partials/header_Survey_Admin %>
<% break; %>
<% default: %>
<% include ./partials/header_Survey_Taker %>
<% break; %>
<% } %>
Note that the first case must be grouped with the switch declaration. Make sure the paths are correct for your partials.
You can concatenate the path and the variable.
<%- include('../partials/Common/header_'+role) %>

Chef Template If Attribute Exists

I've got an optional attribute on my nodes. I want my template to only set a specific value if that attribute exists:
<% if node['haproxy']['server']['backup'] %>
server <%= node['haproxy']['server']['backup']['hostname'] %> <%= node['haproxy']['server']['backup']['ipaddress'] %>:<%= node['mysql']['port'] %> weight 1 maxconn 100 check
<% end %>
This looks good to me but when I run it I'm getting the following error:
Chef::Mixin::Template::TemplateError
------------------------------------
no implicit conversion of String into Integer
How can I get this working so Chef recognizes if the attribute is set?
Try
<% if node['haproxy']['server'].attribute?('backup') %>

puppet erb extra newline

I have a puppet template that is adding an extra newline on each iteration of the inner loop. The template is as follows:
;; THIS FILE IS MANAGED BY PUPPET
; <%= #comment %>
[production]
<%-
#data.sort.map do |provider,attributes|
#data[provider].sort.map do |key,value| -%>
<%= provider %>.<%= key %> = "<%= value %>"
<%- end
end -%>
The output is something along the lines of:
;; THIS FILE IS MANAGED BY PUPPET
; Some random config file
[production]
provider1.a="1"
provider1.a="2"
provider1.a="3"
provider2.a="4"
provider2.a="5"
provider2.a="6"
As far as I can tell, that template should be suppressing the additional newlines. Am I missing something?
try add '-' value in iteration.
"<%= value %>" => "<%= value -%>"
Change to:
;; THIS FILE IS MANAGED BY PUPPET
; <%= #comment %>
[production]
<%-
#data.sort.map do |provider,attributes|
#data[provider].sort.map do |key,value| -%>
<%= provider %>.<%= key %> = "<%= value -%>"
<%- end end -%>

Resources