I did some basic googling, but didn't find an answer yet. I am sorry if
this is a FAQ.
In a manifest for creating an Apache config file, I define a hash like this:
$aliases = {
'/foo/' => '/home/foo/www/',
'/bar/' => '/home/bar/www/',
'/baz/' => '/home/baz/www//'
}
Then, in a template, I have:
<% aliases.each_pair do |key, val| -%>
Alias <%= key %> <%= val %>
<% end -%>
The result is mostly what I expect, but every once in a while, the order
in which the Aliases are generated from the 'each_pair' loop changes,
resulting in a different file.
The Ruby docs state that "hashes enumerate their values in the order that
the corresponding keys were inserted.", but is that not true for Puppet
hashes?
I did stumble across this post:
http://serverfault.com/questions/368784/puppet-and-templates-how-to-loop-sequently-and-not-randomly
which suggests to do something like
<% aliases.sort_by {|key, value| key}.each_pair do |key, val| -%>
<% end -%>
Will it work? Is that a proper solution?
Thanks!
Martijn Grendelman
----- Original Message -----
> From: "Martijn Grendelman" <mar...@iphion.nl>
<snip>
> http://serverfault.com/questions/368784/puppet-and-templates-how-to-loop-sequently-and-not-randomly
>
> which suggests to do something like
>
> <% aliases.sort_by {|key, value| key}.each_pair do |key, val| -%>
> <% end -%>
>
> Will it work? Is that a proper solution?
ruby hashes are not stored in predictable order so this will happen, the proposed
solution should work.
But as always the best is just to test it and see how it goes, it wont bite :)
<% aliases.sort.each do |alias| -%>
Alias <%= alias.first %> <%= alias.last %>
<% end -%>
Regards.
<% aliases.sort_by {|key, value| key}.each do |key, val| -%>
seems to do the trick. 'each_pair' doesn't work here, because the sort_by
returns an array. Again, I learned something :-)
Thanks,
Martijn.
[...]
> >
> > ruby hashes are not stored in predictable order so this will
> > happen, the proposed solution should work.
> >
> > But as always the best is just to test it and see how it goes, it
> > wont bite :)
>
> <% aliases.sort_by {|key, value| key}.each do |key, val| -%>
>
> seems to do the trick. 'each_pair' doesn't work here, because the
> sort_by returns an array. Again, I learned something :-)
...and what about those of us which want the hash entries to appear in
the exact same order they are present in the puppet manifest? From what
I've seen, it was working that way up to 2.6 included, and only gets
"randomized" with puppet 2.7.
I've been doing things like this for a while now :
mm_cfg_settings => {
'ALLOW_SITE_ADMIN_COOKIES' => "Yes",
'PUBLIC_ARCHIVE_URL' => "'https://%(hostname)s/pipermail/%(listname)s'",
'MTA' => "'Postfix'",
'POSTFIX_STYLE_VIRTUAL_DOMAINS' => "'False'",
'DEFAULT_SUBJECT_PREFIX' => "''",
'DEFAULT_REPLY_GOES_TO_LIST' => "1",
},
<% mm_cfg_settings.each do |key,value| -%>
<%= key %> = <%= value %>
<% end -%>
In this particular example, order isn't critical other than for
readability, but I have some others where items must be in the same
order as they appear in the manifest's hash or things will break.
Is there a way to keep using hashes if the order from the manifest must
be kept in a file generated from the template?
Matthias
HelloSorry to ressurect this old thread, but I've just found this issue upgrading from Puppet 2.7.x to Puppet 3. It's true that ruby 1.8 hash order cannot be relied on, but it should always be the same, right? I mean, one doesn't know which order the hash contents will be iterated on, but whatever order ruby chooses should never change.
We had this working with no issues in 2.7.x and ruby 1.8, but now on Puppet 3 we're getting random reorderings. I suspect there's a problem in Puppet in this case.
File a ticket if you wish, but personally, I'm inclined to say that any reliance on iteration order of a hash is dodgy. If iteration order matters then you need to take proactive measures to ensure that you reliably get the (an) order that works for you.