Ask Your Question

How to loop trough nested hash in epp?

asked 2018-09-11 09:11:05 -0600

Jan Huijsmans gravatar image


At the company I'm working at we have a script to automate the creation of symbolic links. This script is fed it's input from a puppet module. The current version of the module uses files, but it is a wish to separate the code from the config, so the module can be shared, but the config can be kept. I've already setup a data structure that can be used and I build an erb template to provide the the main configuration. However, the current module has an option to 'add' files in a directory with user specified name, but same layout, so I'm now trying to rewrite the erb to an epp to provide the same output as the erb, but with the flexibility to add additional configurations.

The datastructure:

      source: 'source1'
      target: 'target1'
      source: 'source2'
      target: 'target2'
      source: 'source3'
      target: 'target3'

The erb:

<% @var.each do |section, entries| %>
[<%= section %>]
<% entries.each do |entry, config| %>
<% config['source'] %> = <% config['target'] %>
<% end -%>
<% end %>

The output

source1 = target1
source2 = target2

source3 = target3

The 'part.1' key is needed as 'source' is not unique, 1 keyword is used to indicate that all files need to be linked to target dir. It was added to have a unique hash key, but is ignored in the output.

I've rewritten the erb to the epp below

<% | Hash[String, Hash[String, Hash[String, String]]] $var | -%>
<% include stdlib %>
<% $var.keys.sort.each do |$section, $entries| { %>
[<%= $section %>]
<% $entries.keys.sort,each do |$entry, $config| { %>
<% $config['source'] %> = <% $config['target'] %>
<% } -%>
<% } %>

This should be correct, at least when I check with the very limited examples online, but it doesn't behave as I expect it to. This epp template results in an error that the 2nd keys operation expects a hash. When I remove the 2nd loop, just to see which sections i get, the output is as below.




Which looks more like an array index then the content of the keys. When I remove the sort.each, as I don't care about the sort order and each looks like you loop trough an array, the resulting output is empty. Thinking I'm using keys function wrong I even tried the code below:

<% | Hash[String, Hash[String, Hash[String, String]]] $var | -%>
<% include stdlib %>
<% $var.keys.each do |$section| { %>
[<%= $section %>]
<% $var[$section].keys.each do |$entry| { %>
<% $var[$section][$entry]['source'] %> = <% $var[$section][$entry]['target'] %>
<% } -%>
<% } %>

But still the output is empty. A lookup of mod::var gives the expected output on the puppet server. (btw output is empty means in all cases 'mod::var is not used', comment lines printed by the template are given, including if it's using an epp or erb template)

init.pp section for this template:

file { 'name':
    ensure  => present,
    content => epp('template.epp', {
                 var => $var,

Puppet version 4.10.9 on RHEL 6 and 7.

I would like to get the epp working and resulting in the ... (more)

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2018-09-11 09:24:19 -0600

Jan Huijsmans gravatar image

I need to stop doing this, answering my own questions while I type them...

<% | Hash[String, Hash[String, Hash[String, String]]] $var | -%>
<% include stdlib %>
<% $var.keys.each do |$section| { %>
[<%= $section %>]
<% $var[$section].keys.each do |$entry| { %>
<% $var[$section][$entry]['source'] %> = <% $var[$section][$entry]['target'] %>
<% } -%>
<% } %>

Is the correct template... Now next step in my manifest, use it correctly for the additional files data structure. (design a data structure that fits)

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2018-09-11 09:11:05 -0600

Seen: 79 times

Last updated: Sep 11