0

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!

Sven
  • 97,248
  • 13
  • 177
  • 225
philippe
  • 2,131
  • 4
  • 30
  • 53

2 Answers2

3

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 %>
  • Oki thanks for your answer; I have not read properly your code, this is changed now, but my trouble is not solved: It seems that scope.lookupvar('ipaddress_'+interface) is always translated as eth0,eth1,lo as if there were no loop! There are 3 iterations (as expected as there are 3 elements in the array) but the first returns 'undefined' and the others ''. If I put only interfaces instead of scope.lookupvar('ipaddress_'+interfaces) i get 'eth0,eth1,lo' then '' for the two following lines. I wonder what i get wrong – philippe Sep 13 '12 at 07:55
0

Ok so according to man hosts, for each host a single line should be present.

There should not be more than one IP address for each hosts.

I have done the following: If I can find a production interface on my nodes, I use this one, otherwise, I use the default interface which is for management.

My fact looks like this:

Facter.add('ip_prod') do
require 'facter/util/ip'
confine :interface => "eth0,eth1,lo"
setcode do
    ip = Facter::Util::IP.get_interface_value('eth1', 'ipaddress')
    ip
end
end

This one is only loaded if there are eth0 and eth1 as physical interfaces.

As hosts template; I use this:

<% if @ip_prod %>
<%= ip_prod %> <%= scope.lookupvar('fqdn') %> <%= scope.lookupvar('hostname') %>
<% else %>
<%= ip_admin %> <%= scope.lookupvar('fqdn') %> <%= scope.lookupvar('hostname') %>
<% end%>

I run into each network interface possible and assign it if the related fact exists, else I use the "default" fact which assign the management IP in this file.

Thanks for your help, hoping it could help someone else :)

philippe
  • 2,131
  • 4
  • 30
  • 53