summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuho Mäkinen <juho.makinen@applifier.com>2016-11-04 13:28:07 +0200
committerRomain Tartière <romain@blogreen.org>2017-08-30 09:14:12 +0200
commiteb017ad756f4ba8db98d20dbb777baddb6836d01 (patch)
tree0e4d1182fde04d1d398572863b71749eaf409430
parent032e8247f7840a490b226d6fbee89b4799b88660 (diff)
downloadipaddress-eb017ad756f4ba8db98d20dbb777baddb6836d01.tar.gz
Add allocate() method
The allocate() method allows to use an IPAddress::IPv4 or ::IPv6 object to allocate individual host addresses so that the IPAddress object tracks the state of which address was previously allocated. Example: ip = IPAddress("10.0.0.0/24") ip.allocate #=> "10.0.0.1/24" ip.allocate #=> "10.0.0.2/24" There is support for both IPv4 and IPv6 with full test coverage.
-rw-r--r--lib/ipaddress/ipv4.rb31
-rw-r--r--lib/ipaddress/ipv6.rb31
-rw-r--r--test/ipaddress/ipv4_test.rb24
-rw-r--r--test/ipaddress/ipv6_test.rb24
4 files changed, 110 insertions, 0 deletions
diff --git a/lib/ipaddress/ipv4.rb b/lib/ipaddress/ipv4.rb
index a123e71..080f3d6 100644
--- a/lib/ipaddress/ipv4.rb
+++ b/lib/ipaddress/ipv4.rb
@@ -89,6 +89,7 @@ module IPAddress;
# 32 bits interger containing the address
@u32 = (@octets[0]<< 24) + (@octets[1]<< 16) + (@octets[2]<< 8) + (@octets[3])
+ @allocator = 0
end # def initialize
#
@@ -1064,6 +1065,36 @@ module IPAddress;
end
#
+ # Allocates a new ip from the current subnet. Optional skip parameter
+ # can be used to skip addresses.
+ #
+ # Will raise StopIteration exception when all addresses have been allocated
+ #
+ # Example:
+ #
+ # ip = IPAddress("10.0.0.0/24")
+ # ip.allocate
+ # #=> "10.0.0.1/24"
+ # ip.allocate
+ # #=> "10.0.0.2/24"
+ # ip.allocate(2)
+ # #=> "10.0.0.5/24"
+ #
+ #
+ # Uses an internal @allocator which tracks the state of allocated
+ # addresses.
+ #
+ def allocate(skip=0)
+ @allocator += 1 + skip
+
+ next_ip = network_u32+@allocator
+ if next_ip > broadcast_u32+1
+ raise StopIteration
+ end
+ self.class.parse_u32(network_u32+@allocator, @prefix)
+ end
+
+ #
# private methods
#
private
diff --git a/lib/ipaddress/ipv6.rb b/lib/ipaddress/ipv6.rb
index 6ae651d..284308c 100644
--- a/lib/ipaddress/ipv6.rb
+++ b/lib/ipaddress/ipv6.rb
@@ -102,6 +102,7 @@ module IPAddress;
end
@prefix = Prefix128.new(netmask ? netmask : 128)
+ @allocator = 0
end # def initialize
@@ -634,6 +635,36 @@ module IPAddress;
def self.parse_hex(hex, prefix=128)
self.parse_u128(hex.hex, prefix)
end
+
+ #
+ # Allocates a new ip from the current subnet. Optional skip parameter
+ # can be used to skip addresses.
+ #
+ # Will raise StopIteration exception when all addresses have been allocated
+ #
+ # Example:
+ #
+ # ip = IPAddress("10.0.0.0/24")
+ # ip.allocate
+ # #=> "10.0.0.1/24"
+ # ip.allocate
+ # #=> "10.0.0.2/24"
+ # ip.allocate(2)
+ # #=> "10.0.0.5/24"
+ #
+ #
+ # Uses an internal @allocator which tracks the state of allocated
+ # addresses.
+ #
+ def allocate(skip=0)
+ @allocator += 1 + skip
+
+ next_ip = network_u128+@allocator
+ if next_ip > broadcast_u128
+ raise StopIteration
+ end
+ self.class.parse_u128(next_ip, @prefix)
+ end
private
diff --git a/test/ipaddress/ipv4_test.rb b/test/ipaddress/ipv4_test.rb
index 19264e2..df60bb1 100644
--- a/test/ipaddress/ipv4_test.rb
+++ b/test/ipaddress/ipv4_test.rb
@@ -595,6 +595,30 @@ class IPv4Test < Minitest::Test
assert_equal "192.168.200.0/24", ip.to_string
end
+ def test_allocate_addresses
+ ip = @klass.new("10.0.0.0/24")
+ ip1 = ip.allocate
+ ip2 = ip.allocate
+ ip3 = ip.allocate
+ assert_equal "10.0.0.1/24", ip1.to_string
+ assert_equal "10.0.0.2/24", ip2.to_string
+ assert_equal "10.0.0.3/24", ip3.to_string
+ end
+
+ def test_allocate_can_skip_addresses
+ ip = @klass.new("10.0.0.0/24")
+ ip1 = ip.allocate(2)
+ assert_equal "10.0.0.3/24", ip1.to_string
+ end
+
+ def test_allocate_will_raise_stopiteration
+ ip = @klass.new("10.0.0.0/30")
+ ip.allocate(3)
+ assert_raises (StopIteration) do
+ ip.allocate
+ end
+ end
+
end # class IPv4Test
diff --git a/test/ipaddress/ipv6_test.rb b/test/ipaddress/ipv6_test.rb
index 7eaa765..3990129 100644
--- a/test/ipaddress/ipv6_test.rb
+++ b/test/ipaddress/ipv6_test.rb
@@ -234,6 +234,30 @@ class IPv6Test < Minitest::Test
assert_equal expected, arr
end
+ def test_allocate_addresses
+ ip = @klass.new("2001:db8::4/125")
+ ip1 = ip.allocate
+ ip2 = ip.allocate
+ ip3 = ip.allocate
+ assert_equal "2001:db8::1", ip1.compressed
+ assert_equal "2001:db8::2", ip2.compressed
+ assert_equal "2001:db8::3", ip3.compressed
+ end
+
+ def test_allocate_can_skip_addresses
+ ip = @klass.new("2001:db8::4/125")
+ ip1 = ip.allocate(2)
+ assert_equal "2001:db8::3", ip1.compressed
+ end
+
+ def test_allocate_will_raise_stopiteration
+ ip = @klass.new("2001:db8::4/125")
+ ip.allocate(6)
+ assert_raises (StopIteration) do
+ ip.allocate
+ end
+ end
+
def test_method_compare
ip1 = @klass.new("2001:db8:1::1/64")
ip2 = @klass.new("2001:db8:2::1/64")