Reputation: 11666
I have a couple machines, each with multiple network interfaces:
lead$ ip addr
2: enp0s2: ...
inet 10.1.1.11/24 brd 10.1.1.255 scope global enp0s2
3: enp0s3: ...
inet 10.2.2.11/24 brd 10.2.2.255 scope global enp0s3
iron$ ip addr
2: enp0s99: ...
inet 10.1.1.12/24 brd 10.1.1.255 scope global enp0s99
3: enp0s3: ...
inet 10.2.2.12/24 brd 10.2.2.255 scope global enp0s3
Note that on lead
, 10.1.1.0/24
is on enp0s2
, but on
iron
, 10.1.1.0/24
is on enp0s99
.
In Puppet, how would I get the IP address(es) (or interface name)
corresponding to the subnet 10.1.1.0/24
? Using $::ipaddress_enp0s2
clearly won't work, as the interface name is different across machines.
What I want is something like $::ipaddress_10_1_1_0
(with the value
10.1.1.11
on lead
and the value 10.1.1.12
on iron
).
For reference: In Ansible, I would do something like:
- shell: "ip route get 10.1.1.0 | awk '{print $6}'"
register: ipaddr
- debug:
msg: "{{ ipaddr.stdout }} is my IP on 10.1.1.0/24"
Upvotes: 2
Views: 2361
Reputation: 8223
You will need to use the same approach in Puppet, using custom facts to create your own.
Upvotes: 2
Reputation: 11666
Puppet Labs actually has an implementation of exactly this in their puppetlabs-openstack module:
require "ipaddr"
module Puppet::Parser::Functions
newfunction(:ip_for_network, :type => :rvalue, :doc => <<-EOS
Returns an ip address for the given network in cidr notation
ip_for_network("127.0.0.0/24") => 127.0.0.1
EOS
) do |args|
addresses_in_range = []
range = IPAddr.new(args[0])
facts = compiler.node.facts.values
ip_addresses = facts.select { |key, value| key.match /^ipaddress/ }
ip_addresses.each do |pair|
key = pair[0]
string_address = pair[1]
ip_address = IPAddr.new(string_address)
if range.include?(ip_address)
addresses_in_range.push(string_address)
end
end
return addresses_in_range.first
end
end
Rather than making a custom fact, this loops over the existing facts and finds ones that look like IP addresses.
Upvotes: 2