Hash of hashes to file template

70 views
Skip to first unread message

Ciro Iriarte

unread,
Oct 5, 2014, 6:55:55 PM10/5/14
to puppet...@googlegroups.com
Hi!, I'm starting to work with hiera and file templates, how would be the best way to transform this hiera output:

myanycast::bird::ospf:
  myinstance:
    tick: 2
    rfc1583compat: 'yes'
    export: 'all'
    area:
      990:
        stub: 'no'
        interface:
          eth0:
            hello: 10
            retransmit: 6
            cost: 10
            transmit_delay: 5
            dead_count: 5
            dead: 40
            wait: 50
            type: 'broadcast'

To this in the final configuration file using templates?:

protocol ospf myinstance:
  tick 2;
  rfc1583compat yes;
  export all;
  area 990 {
    stub no;
    interface "eth0" {
      hello 10;
      retransmit 6;
      cost 10;
      transmit delay 5;
      dead count 5;
      dead 40;
      wait 50;
      type broadcast;
      };
  };
}

There can be many areas per instance, and many interfaces per area.

Also, something that I noticed about hashes is that each hiera query (at least by hand) gives me the same data in different order. Can this trigger a different md5 for the file and force a service reload each 30 minutes even there are no configuration changes?

Regards,
Ciro

Poil

unread,
Oct 6, 2014, 1:51:39 AM10/6/14
to puppet...@googlegroups.com
Hi,

Something like this :
<% if @ospf and @ospf != "" -%>
    <% @ospf.sort.map do |iname,instance| -%>
  protocol ospf <% iname =%>:
    (...)

But I think you can probably use create_resource()

Best regards,
--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/ee60bb31-1cc7-4b92-8030-f9a6bc14fd20%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

jcbollinger

unread,
Oct 6, 2014, 9:52:05 AM10/6/14
to puppet...@googlegroups.com


On Sunday, October 5, 2014 5:55:55 PM UTC-5, Ciro Iriarte wrote:
Hi!, I'm starting to work with hiera and file templates, how would be the best way to transform this hiera output:

myanycast::bird::ospf:
  myinstance:
    tick: 2
    rfc1583compat: 'yes'
    export: 'all'
    area:
      990:
        stub: 'no'
        interface:
          eth0:
            hello: 10
            retransmit: 6
            cost: 10
            transmit_delay: 5
            dead_count: 5
            dead: 40
            wait: 50
            type: 'broadcast'

To this in the final configuration file using templates?:

protocol ospf myinstance:
  tick 2;
  yes;
  export all;
  area 990 {
    stub no;
    interface "eth0" {
      hello 10;
      retransmit 6;
      cost 10;
      transmit delay 5;
      dead count 5;
      dead 40;
      wait 50;
      type broadcast;
      };
  };
}

There can be many areas per instance, and many interfaces per area.


If you haven't already, you should read the documentation.  Here's a partial implementation to give you the idea:

modules/manycast/manifests/bird.pp
----
class manycast::bird(
  $ospf,
  # ...
) {
  # Not sure what file you want to manage...
  file { '/etc/bird/ospf.conf':
    ensure => 'file',
    content => template('manycast/ospf.conf.erb'),
    # ...
  }
}


modules/manycast/templates/ospf.conf.erb
----
<%
  @ospf.sort.each_pair do | instance, instance_data |
-%>
protocol ospf <%= instance %>:
  tick <%= instance_data.tick %>;
  <%= instance_data.rfc1583compat %>;
  export <%= instance_data.export %>;
<%
    instance_data.area.sort.each_pair do | area, area_details |
-%>
  area <%= area %> {
    stub <%= area_details.stub %>;
<%
 # Fill in the rest ...
-%>
  };
<%
    end
  end if @ospf and @ospf.is_a Hash
 -%>



Also, something that I noticed about hashes is that each hiera query (at least by hand) gives me the same data in different order. Can this trigger a different md5 for the file and force a service reload each 30 minutes even there are no configuration changes?


Yes, reordering the content of a file changes its MD5.  If you have a service that receives events from this file, then such a reordering will cause Puppet to restart the service.  Even if not, one generally wants to avoid the noise arising from meaningless resource modifications.  That is the template's purpose for sorting the hashes.


John

Ciro Iriarte

unread,
Oct 6, 2014, 2:47:31 PM10/6/14
to puppet...@googlegroups.com
Trying this approach I get "Detail: undefined method `each_pair' for #<Array:0x7f19bc81d288>" using this code:


<% if (@ospfconfig.is_a?(Hash)) and (@ospfconfig.count > 0) -%>
<% @ospfconfig.sort.each do |instance,instparam| -%>
protocol ospf <%= instance %> {

}
<% end -%>
<% end -%>

Can it be a Ruby version thing?

Regards,
Ciro

Henrik Lindberg

unread,
Oct 6, 2014, 7:29:05 PM10/6/14
to puppet...@googlegroups.com
> <https://docs.puppetlabs.com/guides/templating.html>. Here's a
> * # Fill in the rest ...
> *-%>
> };
> <%
> end
> end if @ospf and @ospf.is_a Hash
> -%>
>
>
>
> Also, something that I noticed about hashes is that each hiera
> query (at least by hand) gives me the same data in different
> order. Can this trigger a different md5 for the file and force a
> service reload each 30 minutes even there are no configuration
> changes?
>
>
>
> Yes, reordering the content of a file changes its MD5. If you have
> a service that receives events from this file, then such a
> reordering will cause Puppet to restart the service. Even if not,
> one generally wants to avoid the noise arising from meaningless
> resource modifications. That is the template's purpose for sorting
> the hashes.
>
>
> John
>
>
> Trying this approach I get "Detail: undefined method `each_pair' for
> #<Array:0x7f19bc81d288>" using this code:
>
>
> <% if (@ospfconfig.is_a?(Hash)) and (@ospfconfig.count > 0) -%>
> <% @ospfconfig.sort.each do |instance,instparam| -%>
> protocol ospf <%= instance %> {
>
> }
> <% end -%>
> <% end -%>
>
> Can it be a Ruby version thing?
>
Use each_slice(2), it should be available in Rubies back to 1.8.7

- henrik

> Regards,
> Ciro
>
> --
> You received this message because you are subscribed to the Google
> Groups "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to puppet-users...@googlegroups.com
> <mailto:puppet-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/puppet-users/3fc2f5c1-532a-4de0-b461-10708dd5d9df%40googlegroups.com
> <https://groups.google.com/d/msgid/puppet-users/3fc2f5c1-532a-4de0-b461-10708dd5d9df%40googlegroups..com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.


--

Visit my Blog "Puppet on the Edge"
http://puppet-on-the-edge.blogspot.se/

Ciro Iriarte

unread,
Oct 7, 2014, 8:36:21 AM10/7/14
to puppet...@googlegroups.com

Well, not sure if it's the prettiest alternative, but got a functional configuration file with this code:

###
### OSPF Routing
###
<% if (@ospfconfig.is_a?(Hash)) and (@ospfconfig.count > 0) -%>
  <% @ospfconfig.keys.sort.each do |key| -%>
    protocol ospf
    <%= key %>
    {
    <% ospfconfig[key].keys.sort.each do |param| -%>
      <% if param !='area' -%>
        <%= param -%>
        <%= ospfconfig[key][param] -%>;
      <% else -%>
        <% ospfconfig[key][param].keys.sort.each do |areaid| -%>
          <%= param -%>
          <%= areaid -%>
          {
          <% ospfconfig[key][param][areaid].keys.sort.each do |areakey| -%>
            <% if areakey != 'interface' %>
              <%= areakey -%>
              <%= ospfconfig[key][param][areaid][areakey] -%>;
            <% else -%>
              <% ospfconfig[key][param][areaid][areakey].keys.sort.each do |ifkey| -%>
                <%= areakey -%>
                <%= ifkey -%>
                {
                <% ospfconfig[key][param][areaid][areakey][ifkey].keys.sort.each do |ifparam| -%>
                  <%= ifparam -%>
                  <%= ospfconfig[key][param][areaid][areakey][ifkey][ifparam] -%>;
                <%end -%>
                };
              <%end -%>
            <%end -%>
          <%end -%>
          };
        <%end -%>
      <%end -%>
    <%end -%>
    }
  <% end -%>
<% end -%>

Regards,
Ciro
 

jcbollinger

unread,
Oct 7, 2014, 9:21:15 AM10/7/14
to puppet...@googlegroups.com


On Monday, October 6, 2014 1:47:31 PM UTC-5, Ciro Iriarte wrote:
 
Trying this approach I get "Detail: undefined method `each_pair' for #<Array:0x7f19bc81d288>" using this code:


<% if (@ospfconfig.is_a?(Hash)) and (@ospfconfig.count > 0) -%>
<% @ospfconfig.sort.each do |instance,instparam| -%>
protocol ospf <%= instance %> {

}
<% end -%>
<% end -%>



Well, you didn't get such an error with that code, as it doesn't use each_pair.  You can use Hash.each(), but in that case, instead of getting the key and value directly, each item iterated is an array of form [ key, value ].  So you might use this variation:

<%
  @ospf.sort.each do |pair|
    instance = pair[0]
    instance_data = pair[1]
-%>

 
Can it be a Ruby version thing?



Yes.  Hash.each_pair() is new in Ruby 1.9.

Hash.each() exists in 1.8.  I prefer it to Hash.each_slice() for this purpose, though the two would work similarly, because the meaning and behavior of the Hash.each() are clearer to me.


John

Felix Frank

unread,
Oct 21, 2014, 7:54:45 AM10/21/14
to puppet...@googlegroups.com
On 10/07/2014 03:21 PM, jcbollinger wrote:
> Can it be a Ruby version thing?
>
>
>
> Yes. Hash.each_pair() is new in Ruby 1.9.

Uhm, no :-) That would have been bad news for my master.

http://www.ruby-doc.org/core-1.8.7/Hash.html#method-i-each_pair

Also, Hash.each should be functionally equivalent.

http://www.ruby-doc.org/core-1.8.7/Hash.html#method-i-each

Something weird is indeed going on there.

Cheers,
Felix
Reply all
Reply to author
Forward
0 new messages