I can't speak for John but I can take a guess at what he was getting at regarding hashes getting complicated. You can use Hiera to store complex information structures like the one below:
postfix_additional_settings:
smtp_tls_security_level: encrypt
tls_random_source: dev:/dev/urandom
smtpd_use_tls: "yes"
smtpd_tls_loglevel: 1
Then inside a Puppet manifest or template you can retrieve and handle the hash in a more concise manner than requesting each postfix configuration key individually. The Puppet and template snippet below will put any Postfix options I add to the hash above into my
main.cf file without me having to go in and edit the postfix module itself:
Manifest:
$postfix_additional_settings = hiera_hash('postfix_additional_settings', undef)
$postfix_main_conf_file = '/etc/postfix/
main.cf'
file { $postfix_main_conf_file:
content => template("${module_name}/${postfix_main_conf_file}.erb"),
}
Template snippet:
###############################################################################
# Everything below here comes from the Hiera postfix_additional_settings hash #
###############################################################################
<% if @postfix_additional_settings %>
<% postfix_additional_settings.sort.each do |key, val| -%>
<% if val -%>
<%=key%> = <%=val%>
<% end -%>
<% end -%>
<% end -%>
That's not too bad for a Postfix config where all the keys are unique and there's only one level of depth. I don't have to have much complexity in my template file to handle the different types of Postfix options my sites have, that's all in Hiera.
Now here's a more complex Template where we write a HAProxy configuration file. This hash:
haproxy_listen_hash:
something:
bind:
ssl:
1.1.1.1:443 ssl crt /etc/pki/tls/private/1.1.1.1.pem
servers:
opts:
mode: tcp
Feeds this template:
<% haproxy_listen_hash.sort.each do |key, listen_hash| -%>
listen <%= key %>
<% listen_hash.sort.each do |key, val| -%>
<% if key == "bind" -%>
# Bind to these addresses
# -----------------------
<% val.sort.each do |subkey, subval| -%>
# <%= subkey %>
bind <%= subval %>
<% end -%>
<% elsif key == "servers" -%>
# Forward traffic to these servers
# --------------------------------
<% val.sort.each do |subkey, subval| -%>
server <%= subkey %> <%= subval %>
<% end -%>
<% elsif key == "opts" -%>
# Extra options
# -------------
<% val.sort.each do |subkey, subval| -%>
<%= subkey %> <%= subval %><% if subkey == "stick-table" && haproxy_peers %> peers mypeers<% end %>
<% end -%>
<% elsif key == "stats" -%>
<% val.sort.each do |subkey, subval| -%>
stats <%= subkey %> <%= subval %>
<% end -%>
<% end -%>
<% end -%>
<% end -%>
It still works well for our purposes, but it's starting to get quite complicated. There are so many nested hashes the template is difficult to read. We do manage to preserve just raw haproxy information in Hiera though.
If you need to go there, using the hiera_hash function adds even more complexity. This will flatten Hiera keys top down through your Hierarchy into a single hash, useful for overriding different portions of your default hash in other parts of your hierarchy.
-Luke