I'm new to puppet and realy need some help with it:
I have the following value im my application my_app.pp value:
akka_application_cluster_seed_nodes => '"akka.tcp://ActorSystem#host1:2551","akka.tcp://ActorSystem#host2:2551","akka.tcp://ActorSystem#host3:2551"'
Now in my erb file min-nr-of-members value should be calculated by getting the size of akka_application_cluster_seed_nodes array divide by 2 plus 1
$min-nr-of-members = $akka_application_cluster_seed_nodes.size/2 +1
For example:
auto-down-unreachable-after = <%= get_param('akka_cluster_auto_down_unreachable_after')%>
and something like this:
<% $cluster= get_param('akka_cluster_auto_down_unreachable_after') %>
<% $minNumOfNodes = ($cluster.size / 2)+1 %>
min-nr-of-members = <% $minNumOfNodes %>
Can you please help?
'"akka.tcp://ActorSystem#host1:2551","akka.tcp://ActorSystem#host2:2551","akka.tcp://ActorSystem#host3:2551"'
is not an array in puppet.
Use split function to create an array from it :
$array_nodes = split($akka_application_cluster_seed_nodes, ',')
Next use size function from stdlib to calculate array size in puppet, and calculate desired value:
$array_size = size($array_nodes)
Then use it in your erb file:
min-nr-of-members = <%= Integer(#array_size) / 2 + 1 %>
Related
$value = sha1("anything");
$secure = '<input type = "hidden" value = "'.$value.'"/>';
$this->twig->addGlobal('anything',$secure);
After this I access this variable like this on template
{{ anything }}
The big surprise print this variable don't escaped like this
<input type = "hidden" value = "8867c88b56e0bfb82cffaf15a66bc8d107d6754a"/>
I want to print as html tag. But it worked when I used {{ anything|raw }}, I wish it worked without using raw filter
You can mark the variable as safe, without the filter raw, if you wrap it in a Twig\Markup instance, e.g.
$value = sha1("anything");
$secure = new \Twig\Markup('<input type = "hidden" value = "'.$value.'"/>', 'UTF-8');
$this->twig->addGlobal('anything',$secure);
I am creating an array with a for loop for a series of dates that are in this format '2019-04'. The problem is that ejs is evaluating this as a subtraction and giving me '2015'.
var labels = []
<%for(var i = 0; i < totals.length; i++) { %>
labels.push(<%= totals[i].period%>+",")
console.log(labels)
<%}%>
The expected result should always be the date in the format YYYY-MM but the results are a subtraction so for 2018-12 I get 2006, 2019-1 I get 2018 and so on.
I solved it. I only needed to include the ejs tags in quotations and didn't need them on the comma
labels.push("<%= totals[i].period %>",)
I want to deploy a config file on several linux machines and need to make sure that a certain variable in that config file has a unique value for each machine. Until now I've been shipping the same config file the following way:
file {
"/etc/nxserver/node.conf":
mode => 644,
ensure => file,
source => "puppet:///modules/nxserver/nxserver-node.conf";
}
I assume that switching to templates is as easy as replacing the source with content:
file {
"/etc/nxserver/node.conf":
mode => 644,
group => root,
content => template("nxserver/nxserver-node.erb"),
}
In the nxserver-node.erb file I could set the variable of interest the following way:
# This file is managed by puppet
... random config stuff ...
somevariable = <%= hostname %>
My questions:
Is there a way to process & extract parts of <%= hostname %> inside the erb file? E.g. my hostnames could be "desktop-01234", and I would want to use the "01234" bit only. How would I achieve this?
Alternatively, could I specify a range of valid values that get uniquely but randomly assigned to the variable inside the erb file? E.g. somevariable could be a variable representing some port number, in the range of 1000 - 4000. I need to make sure that on each puppet host this variable has a different value. How would I achieve this?
EDIT: I can use
fqdn_rand(MAX, [SEED]) to generate a random number that's unique for each hostname, but according to the docs it will return a random whole number greater than or equal to 0 and less than MAX.
<% Puppet::Parser::Functions.function('fqdn_rand') -%>
<% value = scope.function_fqdn_rand(['10000']) -%>
somevariable=<%= value.to_s %>
I've tried using + as well as add to add an offset but + seems to be reserved for strings and the add function is unknown.
the following does exactly what I need:
<% Puppet::Parser::Functions.function('fqdn_rand') -%>
<% offset = "1000".to_i -%>
<% value = scope.function_fqdn_rand(['10000']).to_i + offset -%>
somevariable=<%= value.to_s %>
In ERB templates, you can do everything Ruby can. The String methods are especially helpful.
For example, to cut the prefix from your hostname, you could use
somevariable = <%= #hostname.sub(/^desktop-/, '') %>
What is the proper way to check if a variable is undef in a puppet template?
In the manifest the variable is defined as follows
$myvar = undef
How is this checked in the template?
Is saw the following two variants
<% if #myvar -%>
<% end -%>
and
<% if not #myvar.nil? and #myvar -%>
<% end -%>
They both seem to work in my case, but I wonder if the first approach fails in on certain cases?
The Puppet documentation (at the time of writing this answer) explains it very well: https://puppet.com/docs/puppet/latest/lang_template_erb.html#concept-5365
Since undef is not the same as false, just using an if is not a good way to check for it. Also when a variable is defined, but has a value of false or nil it is also impossible to check with a simple if.
This is why you want to use scope.lookupvar(‘variable’) and check its return value for :undef or :undefined (or nil) to know if it was set to undef, or never set at all.
I'd say the check depends on whether you want an alternative when the variable is not defined.
I'm using the following rules:
Required variable
Check in your puppet script whether the variable contains the expected value before even considering template rendering:
if $myvar == undef {
fail {"You really must set myvar, seriously."}
}
if ! $anothervar {
fail {"anothervar is false, undefined or empty."}
}
You can make your life easier by setting the type of parameters explicitly. This spares you type comparisons and conversions.
In your template you simply write the variables then:
<%= #myvar %>
<%= #anothervar %>
Optional variable that must be defined
If you assume the variable is defined, you can treat it as boolean.
The mapping is as follows (source):
falsey: empty string, false, undef
truthy: everything else
In Puppet >=4:
falsey: false, undef
truthy: everything else
Examples:
print 'something' if #myvar evaluates to true, otherwise 'something else'.
<% if #myvar %>something<% else %>something else<% end %>
print 'something' if #myvar evaluates to true
<% if #myvar %>something<% end %>
print #myvar if it evaluates to true, otherwise 'alternative' %>
<%= #myvar ? #myvar : 'alternative' %>
Optional variable that may be defined
If you are not sure a variable is even defined and don't want to make wrong assumptions, check it in the template.
Examples:
print 'something' followed by #myvar if #myvar is defined and not empty
<% if defined?(#myvar) && ! #myvar.empty? %>something<%= #myvar %><% end %>
print #myvar if it's defined and greater than 10
<%= #myvar if defined?(#myvar) && #myvar > 10 %>
The first one should work like a charm, it's what is being taught in the courses as well.
Number two seems... redundant.
I pass my template an array of strings which I would like to convert to a jaavascript array:
Controller file (php):
$myVar = array('a','b','c');
Desired html:
var myVar = ["a","b","c"];
I try the following code (twig):
var myVar = ["{{ myVar | join('","') }}"];
But the twig generator converts the quotation marks to html entities and this is the result:
var myVar = ["a","b","c"];
Some idea?
You need to apply the raw filter:
var myVar = ["{{ myVar | join('","') | raw }}"];
Maerlyn's answer will work, however the drawback with it is that the values in the myVar array will be outputted raw too, which, depending on the origin of that variable, could lead to vulnerabilities in your website, such as XSS.
I found two ways to do this while maintaining the escaping on the array values. The first is using a loop with an if statement to check whether it's the last iteration to determine whether we need to output the "glue" used in the join or not:
var myVar = [{% for val in myVar %}"{{ val }}"{% if loop.last == false %},{% endif %}{% endfor %}]
The second way is to let PHP your PHP handle everything, including the escaping, and then output the raw string in Twig:
$arr = array_map(
function($value) {
return '"' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '"';
},
$arr
);
$myVar = '[' . implode(',', $arr) . ']';
Then pass the $myVar variable to your view, and then you can just do:
{{ myVar|raw }}