Linux – puppet content of /etc/hosts template with facter

hosts-filelinuxpuppet

I have set up a template to set up the content of the /etc/hosts file. Here is my template:

127.0.0.1 localhost.localdomain localhost
<%= scope.lookupvar('ipaddress') %> <%= scope.lookupvar('fqdn') %> <%= scope.lookupvar('hostname') %>

This is correctly working, but I would like, on nodes with more than one network interface, to provide hostname for both IP addresses. I have then tried the following template:

<%= scope.lookupvar('interfaces').each do |interface| %> <%= scope.lookupvar('ipaddress_'+interface) %>

But puppet displays the error on client:

Could not retrieve catalog from remote server: wrong header line format

Of course, I could use what puppet provides to rule hosts file, but something like:

# host entry with multiple aliases
host { 'dashboard':
  ip => [$ipaddress_eth0, $ipaddress_eth1]
  host_aliases => [ 'nagios', 'munin' ],
}

is not allowed (ip can not be an array apparently, and moreover, I have no way to find out whether the node has 2 interfaces or just one).

Thanks for your help!


I have then created this fact, exported to the destination node. It is supposed to return an array of used IP addresses:

Facter.add('network_interfaces') do

result = []

setcode do
  f = File.open('/etc/network/interfaces', 'r')
  f.each_line{|line|
     if line =~ /^.*address ((([0-9]{1,3})\.){3}([0-9]{1,3})).*$/i
        result << $1
     end 
  }   
result
end 

end

Here is the output of facter -p network_interfaces

192.168.10.10
172.23.10.10

Here is my code to create the hosts line:

# host entry with multiple aliases
host { 'dashboard':
  ip => $network_interfaces
  host_aliases => [ 'nagios', 'munin' ],
}

But puppet fails with the error:

Parameter ip failed: Invalid IP address "192.168.10.10172.23.10.10"

Obviously, the ip array returned by the fact is not regarded as an array by puppet but as a regular string.

Is it possible for a fact to return an array instead of string as concatenated elements of the array?

Many thanks!

Best Answer

You have a syntax error in:

<%= scope.lookupvar('interfaces').each do |interface| %> <%= scope.lookupvar('ipaddress_'+interface) %>
  1. You use <%= when you start iterating: it should be <%
  2. You don't close your block

Rewrite like this instead:

<% scope.lookupvar('interfaces').each do |interface| %>
<%= scope.lookupvar('ipaddress_'+interface) %>
<% end %>

Second, interfaces is a String representing all available interfaces on your machine. You need to convert that String into an Enumerable, in which case the #split method comes in handy:

<% scope.lookupvar('interfaces').split(",").each do |interface| %>
<%= scope.lookupvar('ipaddress_'+interface) %>
<% end %>
Related Topic