Skip to content

Commit

Permalink
Add Extlib::CIDR DataType
Browse files Browse the repository at this point in the history
Example:
```
$ip = Extlib::CIDR('192.168.1.0/24')
notice $ip.host_min, $ip.host_max
```
  • Loading branch information
jay7x committed Apr 1, 2024
1 parent 4b938f9 commit c90c87c
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
52 changes: 52 additions & 0 deletions lib/puppet/datatypes/extlib/cidr.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

# The `Extlib::CIDR` object represents a CIDR.
#
# @param cidr
# @!method address
# @!method canonical
# @!method netmask
# @!method family
# @!method prefix_length
# @!method first
# @!method last
# @!method host_rewind
# @!method host_next
# @!method host_prev
# @!method host_count
# @!method host_min
# @!method host_max
# @!method to_i
# @!method compare
# @!method include
#
Puppet::DataTypes.create_type('Extlib::CIDR') do
interface <<-PUPPET
attributes => {
cidr => String[1],
},
functions => {
address => Callable[[], String[1]],
canonical => Callable[[], String[1]],
netmask => Callable[[], String[1]],
family => Callable[[], String[1]],
prefix_length => Callable[[], Integer[0]],
first => Callable[[], String[1]],
last => Callable[[], String[1]],
host_rewind => Callable[[String[1]], String[1]],
host_next => Callable[[], Optional[String[1]]],
host_prev => Callable[[], Optional[String[1]]],
host_count => Callable[[], Integer[0]],
host_min => Callable[[], String[1]],
host_max => Callable[[], String[1]],
to_i => Callable[[], Integer[0]],
compare => Callable[[Variant[Extlib::CIDR, String[1]]], Integer[-1,1]],
include => Callable[[Variant[Extlib::CIDR, String[1]]], Boolean],
}
PUPPET

load_file('puppet_x/extlib/cidr')

PuppetX::Extlib::CIDR.include(Puppet::Pops::Types::PuppetObject)
implementation_class PuppetX::Extlib::CIDR
end
121 changes: 121 additions & 0 deletions lib/puppet_x/extlib/cidr.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# frozen_string_literal: true

require 'ipaddr'

module PuppetX
class Extlib
class CIDR
attr_reader :ip

def initialize(cidr)
@ip = IPAddr.new(cidr)
@first = @ip.to_range.first
@last = @ip.to_range.last

if (@ip.ipv4? && @ip.prefix.between?(31, 32)) || (@ip.ipv6? && @ip.prefix.between?(127, 128))
@host_min = @first
@host_max = @last
else
@host_min = IPAddr.new(@first.to_i + 1, @ip.family)
@host_max = IPAddr.new(@last.to_i - 1, @ip.family)
end
@host_current = @host_min
end

def address
@ip.to_s
end

def canonical
@ip.to_string
end

def netmask
@ip.inspect.gsub(%r{.*/(.*)>}, '\1')
end

# ipv4/ipv6
def family
@ip.inspect.split(':')[1].strip.downcase
end

def prefix_length
@ip.prefix
end

def first
@first.to_s
end

def last
@last.to_s
end

def host_rewind(new_ip)
raise ArgumentError, "IP should be between #{@host_min} and #{@host_max}" unless new_ip.between?(@host_min, @host_max)

@host_current = IPAddr.new(new_ip)
new_ip.to_s
end

def host_next
host_next_by_step(1)
end

def host_prev
host_next_by_step(-1)
end

def host_next_by_step(step = 1)
ret_ip = @host_current
next_ip = IPAddr.new(@host_current.to_i + step, @ip.family)
# If our CIDR is just an IP address then just return next one.
# Don't care about network range.
if (@ip.ipv4? && @ip.prefix == 32) || (@ip.ipv6? && @ip.prefix == 128) || @host_current.between?(@host_min, @host_max)
@host_current = next_ip
return ret_ip.to_s
end
nil
end

def host_count
@host_max.to_i - @host_min.to_i + 1
end

def host_min
@host_min.to_s
end

def host_max
@host_max.to_s
end

def include?(other)
if other.is_a? Extlib::CIDR
@ip.include? other.ip
else
@ip.include? IPAddr.new(other)
end
end
alias include include?

def to_s
@ip.to_s
end

def to_i
@ip.to_i
end

# Compare IP addresses
def <=>(other)
@ip.to_i <=> if other.is_a? Extlib::CIDR
other.to_i
else
IPAddr.new(other).to_i
end
end
alias compare <=>
end
end
end

0 comments on commit c90c87c

Please sign in to comment.