Snowball
Snowball

Reputation: 11666

Get IP address by subnet in Puppet

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

Answers (2)

Felix Frank
Felix Frank

Reputation: 8223

You will need to use the same approach in Puppet, using custom facts to create your own.

Upvotes: 2

Snowball
Snowball

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

Related Questions