I want to store ip address, port values in a two dimensional array.
192.168.1.156, 4100
192.168.1.157, 4000
Using the defined array, I want to fill this following template structure.
<members>
<%- if #members -%>
<%- #members.each_pair do |hostname,port| -%>
<member>
<hostName><%= hostname %></hostName>
<port><%= port %></port>
</member>
<%- end -%>
<%- end -%>
</members>
How do I construct the two dimensional array in my setup.pp or init.pp file?
It would make the most sense for you to declare your data in hash form. In Hiera, you can use YAML
members:
192.168.1.156: 4100
192.168.1.157: 4000
or JSON
{ members: { '192.168.1.156': '4100', '192.168.1.157': '4000' } }
If you don't want to use Hiera, you can declare the data right in the manifest.
$members = { '192.168.1.156' => '4100',
'192.168.1.157' => '4000' }
Related
I have the following hiera:
profile::example::firewalls:
- serverclass1:
label: http
port: 80
label: https
port: 443
- serverclass2:
label: ssh
port: 22
label: telnet
port: 21
I try to call it in the following way in an erb template:
<% #example = scope().call_function('hiera',['profile::example::firewalls']) -%>
show me the array!
<%= #example %>
Oddly this returns the following:
+show me the array!
+[{"serverclass1"=>nil, "label"=>"https", "port"=>443}, {"serverclass2"=>nil, "label"=>"telnet", "port"=>21}]
Once I have a complete array I'll eventually use this within a for/each loop within ruby, but for the moment this seems to return just the final result and not everything I'd expect.
The problem begins in your YAML data structure, that contains duplicate "label" keys. That is why some of your data is missing in the output.
(See this related Stack Overflow answer for more info.)
Although it is not entirely clear what you are trying to do, it seems to me that you would be better with a YAML data structure like this:
profile::example::firewalls:
serverclass1:
http: 80
https: 443
serverclass2:
ssh: 22
telnet: 21
You could then iterate through that in the ERB template using code like:
<% scope().call_function('lookup',['profile::example::firewalls']).each do |server_class, data| -%>
Server class: <%= server_class %>
<%- data.each do |key, value| -%>
<%= key %> --- <%= value %>
<%- end -%>
<% end -%>
Note also that I removed the deprecated hiera() function and replaced it with lookup().
I have existing puppet modules written in hiera. Basically, data module with param.pp pattern. Everything works fine in puppet 3.x. But after setup with puppet 4.x and ran puppet agent, following error return for hash keys.
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Function Call, Failed to parse template wso2ei/conf/carbon.xml.erb:
Filepath: /etc/puppetlabs/code/environments/production/modules/wso2ei/templates/conf/carbon.xml.erb
Line: 138
Detail: undefined method `[]' for nil:NilClass
at /etc/puppetlabs/code/environments/production/modules/wso2base/manifests/push_templates.pp:23:16 at /etc/puppetlabs/code/environments/production/modules/wso2base/manifests/configure.pp:59 on node puppet4-aa54a7f2-83a6-43d2-b8d7-c15a42591e88.openstacklocal
The particular section of carbon.xml.erb looks like below
<%- if #ports['offset'] -%>
<Offset><%= #ports['offset'] %></Offset>
<%- else -%>
<Offset>0</Offset>
<%- end -%>
hieradata set as below in yaml file
wso2::ports:
offset: 0
param.pp written to read the data
$ports = hiera('wso2::ports')
init.pp set value as below
$ports = $wso2ei::params::ports,
Template not giving any error for a single line data. For an example in carbon.xml.erb
<% if #hostname %>
<HostName><%= #hostname %></HostName>
<%- else -%>
<!--HostName>www.wso2.org</HostName-->
<% end %>
hieradata in yaml file
wso2::hostname: "%{::fqdn}"
All hash keys getting the same error. When I Google, found that # has to replace with scope like below. But there are lots of places to change.
<%- if scope['wso2ei::params::ports']['offset'] -%>
<Offset><%= scope['wso2ei::params::ports']['offset'] %></Offset>
<%- else -%>
<Offset>0</Offset>
<%- end -%>
Is there a way to preserve existing param.pp data module pattern in puppet 4? Appreciate your help.
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.
module/bareos_backup_client/manifests/init.pp:
class bareos_backup_client {
##file { "${fqdn}-bareos-client.conf":
mode => 600,
owner => bareos,
group => bareos,
path => "/etc/bareos/director.d/${fqdn}-client.conf",
content => template("bareos_backup_client/bareos-dir-cliententry.erb"),
tag => 'bareos-client',
notify => Service[bareos-dir],
}
}
module/bareos_backup_client/templates/bareos-dir-cliententry.erb:
<% if #clientrunbeforejob -%>
ClientRunBeforeJob = "<%= #clientrunbeforejob %>"
<% end -%>
<% if #clientrunafterjob -%>
ClientRunAfterJob = "<%= #clientrunafterjob %>"
<% end -%>
manifests/nodes/server_1.pp:
include bareos_backup_client
$clientrunbeforejob = "apple"
Why clientrunbeforejob variable can't inject into erb template?
You try and use dynamic scoping. This has not worked in years, and for good reason!
You will likely want to pass this value as a class parameter.
class bareos_backup_client($clientrunbeforejob) {
...
}
Then declare it like
class { 'bareos_backup_client':
clientrunbeforejob => 'apple'
}
I have an Express.js app set up using EJS templates. I successfully looped through an array with classic JS syntax:
<% for (var i = 0; i < myArray.length; i++) {
this = myArray[i];
// display properties of this
} %>
But I'm wondering, is there a cleaner way to do this?
Specifically, can I use Underscore or Lodash to loop through with .each ? thank you
You can use forEach method
myArray.forEach(function(el, index) {
// el - current element, i - index
});
#wachme's answer is correct, but to stick with the original question, here is the version using Underscore's _.each (and integrated in template syntax):
<% _.each(myArray, function(el, index) { %>
Value is <%= el %>, index is <%= index %>.
<% }) %>
The advantage of Array.prototype.forEach is that you don't need to depend on Underscore in your templates. The advantage of _.each is that it has some additional tricks up its sleeves (for example, it also works on objects) and that it works in older JS environments without any need for polyfills.
As an aside, Underscore's _.template can be used instead of EJS, although it has fewer features. Also, the meaning of <%= and <%− is swapped between the two libraries. Naturally, you can always use _.each in Underscore templates.