furnish-ip 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/CHANGELOG.md +28 -0
- data/Gemfile +0 -2
- data/Guardfile +1 -1
- data/furnish-ip.gemspec +3 -3
- data/lib/furnish/ip.rb +56 -5
- data/lib/furnish/ip/version.rb +1 -1
- data/lib/furnish/provisioners/auto_ip.rb +65 -19
- data/lib/furnish/provisioners/ip.rb +45 -20
- data/test/test_auto_ip_provisioner.rb +76 -2
- data/test/test_ip_lib.rb +5 -5
- data/test/test_ip_provisioner.rb +106 -11
- metadata +13 -33
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjEyYTIzYTc1ZjYxNTI2YTU0NTZlODMwMDE4MjJiYzliNDMxZDUwNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjdhMmIxMjU0YTA2MGU0NDMxMDI3YmI4M2Q3NmY2NTBjMGVlZDlmYQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YTllZWEwMDU2ZDNhZGY3YWIwNWY5MjEyYjgyNDEyMDI0ZDllZTM2ZGVkNzBj
|
10
|
+
YmQ3MmFjOTJiZWMxYzg0MzNiOTNkYjM0YmNiZWQxNWEzZDhkNDUwMDVjNDRj
|
11
|
+
YThmNDZlYjFmZjc2MmE0YmE2MjdjNGEwZWVjYTg2OTIwMTVmY2U=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZmQyYzA3ZjE2M2I2YzQ0MzM3ODVlZjE1MmE5ZDk1YTUxMmVhMGZiOWVkM2U0
|
14
|
+
MGE3MjFhOTIyMTNlODI5NjA2MTU4NWQ1ZjEzNDc3ODcxOGQ4ZWY2MWY4ZGVm
|
15
|
+
OTc2Y2YyZDgwOWI2MWM1Y2VkNjliMGRhZDNhN2NiYmNhMWNmZDE=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
* 0.1.0 (04/10/2013)
|
2
|
+
* Now supports Furnish 0.1.0, include protocol and property definitions and
|
3
|
+
all Provisioners inherit from Furnish::Provisioner::API. Recovery is still
|
4
|
+
unsupported at this time.
|
5
|
+
* Furnish::IP API changes:
|
6
|
+
* #unused_ip now takes an optional argument -- if a group name is supplied,
|
7
|
+
saves it to the group list and allocates it before returning it.
|
8
|
+
* #replace_group is sugar to ensure the group for a given name is entirely
|
9
|
+
swapped out with a provided group. Does not modify allocations.
|
10
|
+
* #assign_group_ips no longer takes a splatted list, requires
|
11
|
+
set/array/single item. Converted to set before injecting, returns set it
|
12
|
+
injected.
|
13
|
+
* #assign_group_ips now has an optional third argument. When true, will
|
14
|
+
attempt to determine if what it added modified the counts of allocated
|
15
|
+
and the group. If these numbers did not change after addition, will
|
16
|
+
raise. Used in the above unused_ip changes to try and get close to atomic
|
17
|
+
changes.
|
18
|
+
* #remove_from_group subtracts the set of ips from the group.
|
19
|
+
* #deallocate removes an IP from the allocated set.
|
20
|
+
* Both IP and AutoIP provisioners now track what IPs that specific
|
21
|
+
provisioner is responsible for. On shutdown, they will remove only those
|
22
|
+
IPs from the group. If the group is empty at that point, the group will be
|
23
|
+
destroyed.
|
24
|
+
* AutoIP had an issue which was surfaced by the above fix where two AutoIP
|
25
|
+
provisioners would compete for address space and end up trying to add the
|
26
|
+
same IPs, resulting in a number of allocated IPs that were less than
|
27
|
+
requested. Testing indicates this problem is resolved, but issues may still
|
28
|
+
arise.
|
1
29
|
* 0.0.3 (03/25/2013)
|
2
30
|
* Several fixes around the encoding of IP addresses -- fixes Ruby 2.0.0-p0
|
3
31
|
issues.
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/furnish-ip.gemspec
CHANGED
@@ -17,13 +17,13 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.add_dependency 'furnish', '~> 0.0
|
21
|
-
gem.add_dependency 'palsy', '~> 0.0.
|
20
|
+
gem.add_dependency 'furnish', '~> 0.1.0'
|
21
|
+
gem.add_dependency 'palsy', '~> 0.0.4'
|
22
22
|
|
23
23
|
gem.add_development_dependency 'rake'
|
24
24
|
gem.add_development_dependency 'minitest', '~> 4.5.0'
|
25
25
|
gem.add_development_dependency 'guard-minitest'
|
26
|
-
gem.add_development_dependency 'guard-rake'
|
26
|
+
gem.add_development_dependency 'guard-rake', '~> 0.0.8'
|
27
27
|
gem.add_development_dependency 'rdoc', '~> 4'
|
28
28
|
gem.add_development_dependency 'rb-fsevent'
|
29
29
|
gem.add_development_dependency 'simplecov'
|
data/lib/furnish/ip.rb
CHANGED
@@ -56,6 +56,13 @@ module Furnish # :nodoc:
|
|
56
56
|
allocated.add(ip.encode("UTF-8"))
|
57
57
|
end
|
58
58
|
|
59
|
+
#
|
60
|
+
# Deallocates IPs from the global allocation pool. Always succeeds.
|
61
|
+
#
|
62
|
+
def deallocate(ip)
|
63
|
+
allocated.delete(ip.encode("UTF-8"))
|
64
|
+
end
|
65
|
+
|
59
66
|
#
|
60
67
|
# Predicate to determine whether or not an IP is already allocated.
|
61
68
|
#
|
@@ -68,9 +75,11 @@ module Furnish # :nodoc:
|
|
68
75
|
# un-used IP is. Will raise ArgumentError if #new is not provided with an
|
69
76
|
# IPAddr object (see the documentation there for details).
|
70
77
|
#
|
78
|
+
# If a name is supplied, it will add it to the group IP registry for that name.
|
79
|
+
#
|
71
80
|
# Will raise RuntimeError if the subnet is exhausted.
|
72
81
|
#
|
73
|
-
def unused_ip
|
82
|
+
def unused_ip(name=nil)
|
74
83
|
unless subnet
|
75
84
|
raise ArgumentError, "#{self.class}#unused_ip requires an IPAddr object to work"
|
76
85
|
end
|
@@ -82,7 +91,12 @@ module Furnish # :nodoc:
|
|
82
91
|
subnet_range.count.times do
|
83
92
|
this_ip = net.to_s.encode("UTF-8")
|
84
93
|
|
85
|
-
|
94
|
+
begin
|
95
|
+
unless allocated.include?(this_ip)
|
96
|
+
return name ? assign_group_ips(name, this_ip, true).first : this_ip
|
97
|
+
end
|
98
|
+
rescue
|
99
|
+
end
|
86
100
|
|
87
101
|
net = net.succ
|
88
102
|
|
@@ -102,20 +116,57 @@ module Furnish # :nodoc:
|
|
102
116
|
groups[name] || Set.new
|
103
117
|
end
|
104
118
|
|
119
|
+
#
|
120
|
+
# Overwrite a group for name with a given group.
|
121
|
+
#
|
122
|
+
def replace_group(name, group)
|
123
|
+
groups[name] = group
|
124
|
+
end
|
125
|
+
|
105
126
|
#
|
106
127
|
# Assign one or more ips to a group. This method is additive, so multiple
|
107
128
|
# calls will grow the group, not replace it.
|
108
129
|
#
|
109
|
-
def assign_group_ips(name,
|
130
|
+
def assign_group_ips(name, ips, raise_if_exists=false)
|
110
131
|
group = group_ips(name)
|
111
132
|
|
133
|
+
if ips.kind_of?(Array)
|
134
|
+
ips = Set[*ips]
|
135
|
+
elsif !ips.kind_of?(Set)
|
136
|
+
ips = Set[ips]
|
137
|
+
end
|
138
|
+
|
139
|
+
c_allocated = allocated.count
|
140
|
+
c_group = group.count
|
141
|
+
|
112
142
|
ips.each do |ip|
|
113
143
|
utf8_ip = ip.encode("UTF-8")
|
114
144
|
allocated.add(utf8_ip)
|
115
145
|
group.add(utf8_ip)
|
116
146
|
end
|
117
147
|
|
118
|
-
|
148
|
+
if raise_if_exists
|
149
|
+
raise unless group.count == c_group + ips.count && allocated.count == c_allocated + ips.count
|
150
|
+
end
|
151
|
+
|
152
|
+
replace_group(name, group)
|
153
|
+
|
154
|
+
return ips
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Remove the IPs from the group provided by name, also deallocates them.
|
159
|
+
#
|
160
|
+
def remove_from_group(name, ips)
|
161
|
+
group = group_ips(name)
|
162
|
+
|
163
|
+
ips.each do |ip|
|
164
|
+
utf8_ip = ip.encode("UTF-8")
|
165
|
+
deallocate(utf8_ip)
|
166
|
+
group.delete(utf8_ip)
|
167
|
+
end
|
168
|
+
|
169
|
+
replace_group(name, group)
|
119
170
|
|
120
171
|
return ips
|
121
172
|
end
|
@@ -127,7 +178,7 @@ module Furnish # :nodoc:
|
|
127
178
|
group = group_ips(name)
|
128
179
|
|
129
180
|
group.each do |ip|
|
130
|
-
|
181
|
+
deallocate(ip)
|
131
182
|
end
|
132
183
|
|
133
184
|
groups.delete(name)
|
data/lib/furnish/ip/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'furnish/provisioners/api'
|
1
2
|
require 'furnish/ip'
|
2
3
|
require 'set'
|
3
4
|
|
@@ -9,42 +10,87 @@ module Furnish # :nodoc:
|
|
9
10
|
# is that this will be chained to another provisioner who would accept it
|
10
11
|
# as input during startup.
|
11
12
|
#
|
12
|
-
class AutoIP
|
13
|
+
class AutoIP < API
|
13
14
|
##
|
14
|
-
#
|
15
|
-
|
15
|
+
# :attr: ip
|
16
|
+
#
|
17
|
+
# A Furnish::IP registry object. If a subnet is not assigned to this
|
18
|
+
# object (see Furnish::IP#new), ArgumentError will be raised when
|
19
|
+
# attempting to generate IP addresses.
|
20
|
+
#
|
21
|
+
furnish_property :ip, "A Furnish::IP registry object", Furnish::IP
|
16
22
|
|
17
23
|
##
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# addresses to allocate
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
# :attr: number_of_addresses
|
25
|
+
#
|
26
|
+
# An integer value specifying the number of addresses to allocate at
|
27
|
+
# provisioning time.
|
28
|
+
#
|
29
|
+
furnish_property :number_of_addresses, "An integer indicating the number of addresses to generate", Integer
|
30
|
+
|
31
|
+
configure_startup do
|
32
|
+
accepts_from_any true
|
33
|
+
yields :ips, "Set of strings of recorded IP addresses", Set
|
34
|
+
end
|
35
|
+
|
36
|
+
configure_shutdown do
|
37
|
+
accepts_from_any true
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Create the provisioner, requires :ip be passed and referring to a
|
42
|
+
# Furnish::IP object with subnet semantics (see Furnish::IP#new), and
|
43
|
+
# :number_of_addresses can also be supplied or will default to 1.
|
44
|
+
def initialize(args)
|
45
|
+
super
|
46
|
+
|
47
|
+
unless ip
|
48
|
+
raise ArgumentError, "A Furnish::IP object must be provided"
|
49
|
+
end
|
50
|
+
|
51
|
+
unless ip.subnet
|
52
|
+
raise ArgumentError, "The Furnish::IP object must have a subnet associated"
|
53
|
+
end
|
54
|
+
|
55
|
+
@number_of_addresses ||= 1
|
24
56
|
end
|
25
57
|
|
26
58
|
##
|
27
59
|
# Allocate addresses and forward them on to the next provisioner. Uses
|
28
|
-
# the provisioner group name as the key for the address set.
|
29
|
-
|
30
|
-
|
31
|
-
|
60
|
+
# the provisioner group name as the key for the address set. Fills key
|
61
|
+
# :ips with a Set of IP addresses.
|
62
|
+
def startup(args={})
|
63
|
+
@controlled_ips = Set.new
|
64
|
+
|
65
|
+
number_of_addresses.times do
|
66
|
+
this_ip = ip.unused_ip(furnish_group_name)
|
67
|
+
@controlled_ips.add(this_ip)
|
32
68
|
end
|
33
69
|
|
34
|
-
return
|
70
|
+
return({ :ips => ip.group_ips(furnish_group_name) })
|
35
71
|
end
|
36
72
|
|
37
73
|
##
|
38
|
-
# Release the IP addresses back to the allocator.
|
39
|
-
|
40
|
-
|
41
|
-
|
74
|
+
# Release the IP addresses back to the allocator. Only releases the IPs
|
75
|
+
# that were allocated by this specific provisioner. Destroys the group if
|
76
|
+
# it's empty after releasing.
|
77
|
+
#
|
78
|
+
def shutdown(args={ })
|
79
|
+
if @controlled_ips
|
80
|
+
ip.remove_from_group(furnish_group_name, @controlled_ips)
|
81
|
+
end
|
82
|
+
|
83
|
+
if ip.group_ips(furnish_group_name).empty?
|
84
|
+
ip.decommission_group(furnish_group_name)
|
85
|
+
end
|
86
|
+
|
87
|
+
return { }
|
42
88
|
end
|
43
89
|
|
44
90
|
##
|
45
91
|
# Display the allocated addresses for this group.
|
46
92
|
def report
|
47
|
-
|
93
|
+
ip.group_ips(furnish_group_name).to_a rescue []
|
48
94
|
end
|
49
95
|
end
|
50
96
|
end
|
@@ -1,49 +1,74 @@
|
|
1
|
+
require 'furnish/provisioners/api'
|
1
2
|
require 'furnish/ip'
|
2
3
|
require 'set'
|
3
4
|
|
4
5
|
module Furnish # :nodoc:
|
5
6
|
module Provisioner # :nodoc:
|
6
7
|
#
|
7
|
-
# Static Provisioner against the Furnish::IP registry.
|
8
|
+
# Static Provisioner against the Furnish::IP registry. Place this after
|
9
|
+
# something that yields an IP address to record it in the registry under
|
10
|
+
# the provisioner group's name.
|
8
11
|
#
|
9
|
-
class IP
|
12
|
+
class IP < API
|
10
13
|
##
|
11
|
-
#
|
12
|
-
|
14
|
+
# :attr: ip
|
15
|
+
#
|
16
|
+
# A Furnish::IP object.
|
17
|
+
#
|
18
|
+
furnish_property :ip, "A Furnish::IP registry object", Furnish::IP
|
19
|
+
|
20
|
+
configure_startup do
|
21
|
+
requires :ips, "Set of strings of IP addresses", Set
|
22
|
+
yields :ips, "Set of strings of recorded IP addresses", Set
|
23
|
+
end
|
24
|
+
|
25
|
+
configure_shutdown do
|
26
|
+
accepts_from_any true
|
27
|
+
end
|
13
28
|
|
14
|
-
##
|
15
29
|
#
|
16
|
-
# Create the provisioner
|
17
|
-
#
|
30
|
+
# Create the provisioner, requires :ip be passed and referring to a
|
31
|
+
# Furnish::IP object.
|
18
32
|
#
|
19
|
-
def initialize(
|
20
|
-
|
33
|
+
def initialize(args)
|
34
|
+
super
|
35
|
+
|
36
|
+
unless ip
|
37
|
+
raise ArgumentError, "A Furnish::IP object must be provided"
|
38
|
+
end
|
21
39
|
end
|
22
40
|
|
23
41
|
##
|
24
|
-
# Allocate the
|
25
|
-
#
|
26
|
-
# of the provisioning group.
|
42
|
+
# Allocate the :ips set passed in to a Furnish::IP group named after the
|
43
|
+
# provisioning group.
|
27
44
|
#
|
28
|
-
# Returns the set of IP addresses.
|
45
|
+
# Returns the set of IP addresses in :ips.
|
29
46
|
#
|
30
|
-
def startup(
|
31
|
-
@
|
32
|
-
|
47
|
+
def startup(args={})
|
48
|
+
@controlled_ips = args[:ips]
|
49
|
+
ip.assign_group_ips(furnish_group_name, @controlled_ips)
|
50
|
+
return({ :ips => ip.group_ips(furnish_group_name) })
|
33
51
|
end
|
34
52
|
|
35
53
|
##
|
36
54
|
# Releases the allocated addresses.
|
37
55
|
#
|
38
|
-
def shutdown
|
39
|
-
@
|
40
|
-
|
56
|
+
def shutdown(args={})
|
57
|
+
if @controlled_ips
|
58
|
+
ip.remove_from_group(furnish_group_name, @controlled_ips)
|
59
|
+
end
|
60
|
+
|
61
|
+
if ip.group_ips(furnish_group_name).empty?
|
62
|
+
ip.decommission_group(furnish_group_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
return({ })
|
41
66
|
end
|
42
67
|
|
43
68
|
##
|
44
69
|
# Display the allocated addresses for this group.
|
45
70
|
def report
|
46
|
-
|
71
|
+
ip.group_ips(furnish_group_name).to_a rescue []
|
47
72
|
end
|
48
73
|
end
|
49
74
|
end
|
@@ -3,11 +3,55 @@ require 'helper'
|
|
3
3
|
class TestAutoIPProvisioner < Furnish::RunningSchedulerTestCase
|
4
4
|
def setup
|
5
5
|
super
|
6
|
+
@klass = Furnish::Provisioner::AutoIP
|
6
7
|
@ip = Furnish::IP.new("127.0.0.1/24")
|
7
8
|
end
|
8
9
|
|
9
10
|
def make_provisioner(num=1)
|
10
|
-
|
11
|
+
@klass.new(:ip => @ip, :number_of_addresses => num)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_constructor
|
15
|
+
assert_raises(ArgumentError) { @klass.new({}) }
|
16
|
+
assert_raises(ArgumentError) { @klass.new(:ip => Furnish::IP.new) }
|
17
|
+
prov = @klass.new(:ip => Furnish::IP.new("10.10.10.0/8"))
|
18
|
+
assert_equal(1, prov.number_of_addresses)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_properties
|
22
|
+
assert_equal(
|
23
|
+
{
|
24
|
+
:ip => {
|
25
|
+
:description => "A Furnish::IP registry object",
|
26
|
+
:type => Furnish::IP
|
27
|
+
},
|
28
|
+
:number_of_addresses => {
|
29
|
+
:description => "An integer indicating the number of addresses to generate",
|
30
|
+
:type => Integer
|
31
|
+
}
|
32
|
+
},
|
33
|
+
@klass.furnish_properties
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_protocol
|
38
|
+
assert_equal(
|
39
|
+
{
|
40
|
+
:ips => {
|
41
|
+
:description => "Set of strings of recorded IP addresses",
|
42
|
+
:type => Set
|
43
|
+
}
|
44
|
+
},
|
45
|
+
@klass.startup_protocol[:yields]
|
46
|
+
)
|
47
|
+
|
48
|
+
assert_empty(@klass.startup_protocol[:requires])
|
49
|
+
assert_empty(@klass.startup_protocol[:accepts])
|
50
|
+
|
51
|
+
[:accepts, :yields, :requires].each { |x| assert_empty(@klass.shutdown_protocol[x]) }
|
52
|
+
|
53
|
+
assert(@klass.startup_protocol[:accepts_from_any])
|
54
|
+
assert(@klass.shutdown_protocol[:accepts_from_any])
|
11
55
|
end
|
12
56
|
|
13
57
|
def test_basic_provision
|
@@ -22,7 +66,7 @@ class TestAutoIPProvisioner < Furnish::RunningSchedulerTestCase
|
|
22
66
|
|
23
67
|
first_ip = @ip.group_ips("test1").first
|
24
68
|
|
25
|
-
assert_equal("test1", provisioner.
|
69
|
+
assert_equal("test1", provisioner.furnish_group_name, "name reflects provisioner name")
|
26
70
|
assert_equal([first_ip], provisioner.report, "report reflects provisioned IPs")
|
27
71
|
|
28
72
|
sched.schedule_provision("test2", make_provisioner(10), [])
|
@@ -51,4 +95,34 @@ class TestAutoIPProvisioner < Furnish::RunningSchedulerTestCase
|
|
51
95
|
assert_solved("test1")
|
52
96
|
assert_equal(first_ip, @ip.group_ips("test1").first, "provisioner re-uses deprovisioned IP addresses")
|
53
97
|
end
|
98
|
+
|
99
|
+
def test_multi_provision
|
100
|
+
first = make_provisioner(5)
|
101
|
+
second = make_provisioner(5)
|
102
|
+
|
103
|
+
sched.s("first", first)
|
104
|
+
sched.s("second", second)
|
105
|
+
sched.wait_for("first", "second")
|
106
|
+
assert_solved("first")
|
107
|
+
assert_solved("second")
|
108
|
+
assert_equal(5, @ip.group_ips("first").count)
|
109
|
+
assert_equal(5, @ip.group_ips("second").count)
|
110
|
+
assert_equal(10, @ip.allocated.count)
|
111
|
+
|
112
|
+
sched.deprovision_group("first")
|
113
|
+
|
114
|
+
assert_equal(5, @ip.allocated.count)
|
115
|
+
|
116
|
+
sched.deprovision_group("second")
|
117
|
+
|
118
|
+
assert_equal(0, @ip.allocated.count)
|
119
|
+
|
120
|
+
sched.s("both", [first, second])
|
121
|
+
sched.wait_for("both")
|
122
|
+
assert_equal(10, @ip.group_ips("both").count)
|
123
|
+
assert_equal(10, @ip.allocated.count)
|
124
|
+
sched.teardown
|
125
|
+
assert_equal(0, @ip.group_ips("both").count)
|
126
|
+
assert_equal(0, @ip.allocated.count)
|
127
|
+
end
|
54
128
|
end
|
data/test/test_ip_lib.rb
CHANGED
@@ -72,22 +72,22 @@ class TestIPLib < Furnish::TestCase
|
|
72
72
|
allocated.add(ip_arg)
|
73
73
|
|
74
74
|
assert_equal(
|
75
|
-
[ip_arg],
|
75
|
+
Set[ip_arg],
|
76
76
|
ip.assign_group_ips("foo", ip_arg),
|
77
|
-
"single argument is
|
77
|
+
"single argument is returned as a set"
|
78
78
|
)
|
79
79
|
|
80
80
|
assert_equal(Set[ip_arg], ip.group_ips("foo"), "returned as set from group_ips")
|
81
81
|
|
82
82
|
unused_ip = ip.unused_ip
|
83
|
-
ip_arg = [unused_ip, unused_ip.succ, unused_ip.succ.succ]
|
83
|
+
ip_arg = Set[unused_ip, unused_ip.succ, unused_ip.succ.succ]
|
84
84
|
|
85
85
|
ip_arg.each { |i| allocated.add(i) }
|
86
86
|
|
87
87
|
assert_equal(
|
88
88
|
ip_arg,
|
89
|
-
ip.assign_group_ips("bar",
|
90
|
-
"
|
89
|
+
ip.assign_group_ips("bar", ip_arg.to_a),
|
90
|
+
"set is returned when array passed"
|
91
91
|
)
|
92
92
|
|
93
93
|
assert_equal(Set[*ip_arg], ip.group_ips("bar"), "returned as set from group_ips")
|
data/test/test_ip_provisioner.rb
CHANGED
@@ -1,19 +1,31 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'ipaddr'
|
3
|
+
require 'furnish/provisioners/api'
|
4
|
+
require 'set'
|
3
5
|
|
4
|
-
class IPReturningProvisioner
|
5
|
-
|
6
|
+
class IPReturningProvisioner < Furnish::Provisioner::API
|
7
|
+
furnish_property :ips, "An array of IP addresses as strings", Array
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
configure_startup do
|
10
|
+
accepts_from_any true
|
11
|
+
yields :ips, "A set of IP addresses as strings", Set
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
configure_shutdown do
|
15
|
+
accepts_from_any true
|
13
16
|
end
|
14
17
|
|
15
|
-
def
|
16
|
-
|
18
|
+
def initialize(args)
|
19
|
+
super
|
20
|
+
@ips = Set[*ips]
|
21
|
+
end
|
22
|
+
|
23
|
+
def startup(args={})
|
24
|
+
return({ :ips => ips })
|
25
|
+
end
|
26
|
+
|
27
|
+
def shutdown(args={})
|
28
|
+
return({ })
|
17
29
|
end
|
18
30
|
|
19
31
|
def report
|
@@ -24,16 +36,62 @@ end
|
|
24
36
|
class TestIPProvisioner < Furnish::RunningSchedulerTestCase
|
25
37
|
def setup
|
26
38
|
super
|
39
|
+
@klass = Furnish::Provisioner::IP
|
27
40
|
@ip = Furnish::IP.new
|
28
41
|
end
|
29
42
|
|
30
43
|
def make_provisioner(*ips)
|
31
44
|
[
|
32
|
-
IPReturningProvisioner.new(
|
33
|
-
|
45
|
+
IPReturningProvisioner.new(:ips => ips),
|
46
|
+
@klass.new(:ip => @ip)
|
34
47
|
]
|
35
48
|
end
|
36
49
|
|
50
|
+
def test_constructor
|
51
|
+
assert_raises(ArgumentError) { @klass.new({ }) }
|
52
|
+
@klass.new(:ip => Furnish::IP.new)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_properties
|
56
|
+
assert_equal(
|
57
|
+
{
|
58
|
+
:ip => {
|
59
|
+
:description => "A Furnish::IP registry object",
|
60
|
+
:type => Furnish::IP
|
61
|
+
}
|
62
|
+
},
|
63
|
+
@klass.furnish_properties
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_protocol
|
68
|
+
assert_equal(
|
69
|
+
{
|
70
|
+
:ips => {
|
71
|
+
:description => "Set of strings of IP addresses",
|
72
|
+
:type => Set
|
73
|
+
}
|
74
|
+
},
|
75
|
+
@klass.startup_protocol[:requires]
|
76
|
+
)
|
77
|
+
|
78
|
+
assert_equal(
|
79
|
+
{
|
80
|
+
:ips => {
|
81
|
+
:description => "Set of strings of recorded IP addresses",
|
82
|
+
:type => Set
|
83
|
+
}
|
84
|
+
},
|
85
|
+
@klass.startup_protocol[:yields]
|
86
|
+
)
|
87
|
+
|
88
|
+
assert_empty(@klass.startup_protocol[:accepts])
|
89
|
+
|
90
|
+
[:accepts, :yields, :requires].each { |x| assert_empty(@klass.shutdown_protocol[x]) }
|
91
|
+
|
92
|
+
assert(@klass.shutdown_protocol[:accepts_from_any])
|
93
|
+
end
|
94
|
+
|
37
95
|
def test_basic_provision
|
38
96
|
ipaddr = IPAddr.new("127.0.0.1/24")
|
39
97
|
ips = (0..4).map { ipaddr = ipaddr.succ; ipaddr.to_s }
|
@@ -48,7 +106,7 @@ class TestIPProvisioner < Furnish::RunningSchedulerTestCase
|
|
48
106
|
assert_equal(count, @ip.group_ips("test1").count, "#{count} IPs were allocated")
|
49
107
|
assert_equal(count, @ip.allocated.count, "#{count} IPs were allocated")
|
50
108
|
|
51
|
-
assert_equal("test1", provisioner.last.
|
109
|
+
assert_equal("test1", provisioner.last.furnish_group_name, "name reflects group name")
|
52
110
|
assert_equal(ips, provisioner.last.report, "report reflects ip list")
|
53
111
|
|
54
112
|
ips = (0..4).map { ipaddr = ipaddr.succ; ipaddr.to_s }
|
@@ -74,4 +132,41 @@ class TestIPProvisioner < Furnish::RunningSchedulerTestCase
|
|
74
132
|
assert_empty(@ip.group_ips("test1"), "torn down group is empty")
|
75
133
|
assert_equal(0, @ip.allocated.count, "count is zero after deprovisioning all groups")
|
76
134
|
end
|
135
|
+
|
136
|
+
def test_multi_provision
|
137
|
+
ipaddr = IPAddr.new("127.0.0.1/24")
|
138
|
+
first_ips = (0..4).map { ipaddr = ipaddr.succ; ipaddr.to_s }
|
139
|
+
first = make_provisioner(*first_ips)
|
140
|
+
second_ips = (0..4).map { ipaddr = ipaddr.succ; ipaddr.to_s }
|
141
|
+
second = make_provisioner(*second_ips)
|
142
|
+
|
143
|
+
sched.s("first", first)
|
144
|
+
sched.wait_for("first")
|
145
|
+
assert_solved("first")
|
146
|
+
assert_equal(first_ips.count, @ip.group_ips("first").count, "#{first_ips.count} IPs were allocated")
|
147
|
+
assert_equal(first_ips.count, @ip.allocated.count, "#{first_ips.count} IPs were allocated")
|
148
|
+
sched.deprovision_group("first")
|
149
|
+
assert_equal(0, @ip.group_ips("first").count, "count is zero after deprovision")
|
150
|
+
assert_equal(0, @ip.allocated.count, "count is zero after deprovision")
|
151
|
+
|
152
|
+
sched.s("second", second)
|
153
|
+
sched.wait_for("second")
|
154
|
+
assert_solved("second")
|
155
|
+
assert_equal(second_ips.count, @ip.group_ips("second").count, "#{second_ips.count} IPs were allocated")
|
156
|
+
assert_equal(second_ips.count, @ip.allocated.count, "#{second_ips.count} IPs were allocated")
|
157
|
+
sched.deprovision_group("second")
|
158
|
+
assert_equal(0, @ip.group_ips("second").count, "count is zero after deprovision")
|
159
|
+
assert_equal(0, @ip.allocated.count, "count is zero after deprovision")
|
160
|
+
|
161
|
+
sched.s("test1", first + second)
|
162
|
+
sched.wait_for("test1")
|
163
|
+
|
164
|
+
assert_solved("test1")
|
165
|
+
total = first_ips.count + second_ips.count
|
166
|
+
assert_equal(total, @ip.group_ips("test1").count, "#{total} IPs were allocated")
|
167
|
+
assert_equal(total, @ip.allocated.count, "#{total} IPs were allocated")
|
168
|
+
sched.deprovision_group("test1")
|
169
|
+
assert_equal(0, @ip.group_ips("test1").count, "count is zero after deprovision")
|
170
|
+
assert_equal(0, @ip.allocated.count, "count is zero after deprovision")
|
171
|
+
end
|
77
172
|
end
|
metadata
CHANGED
@@ -1,52 +1,46 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: furnish-ip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Erik Hollensbe
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-04-10 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: furnish
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.0
|
19
|
+
version: 0.1.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.0
|
26
|
+
version: 0.1.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: palsy
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.0.
|
33
|
+
version: 0.0.4
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: 0.0.
|
40
|
+
version: 0.0.4
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ! '>='
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ! '>='
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,7 +55,6 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: minitest
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ~>
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -78,7 +69,6 @@ dependencies:
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: guard-minitest
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - ! '>='
|
84
74
|
- !ruby/object:Gem::Version
|
@@ -86,7 +76,6 @@ dependencies:
|
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - ! '>='
|
92
81
|
- !ruby/object:Gem::Version
|
@@ -94,23 +83,20 @@ dependencies:
|
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: guard-rake
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ~>
|
100
88
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
89
|
+
version: 0.0.8
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ~>
|
108
95
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
96
|
+
version: 0.0.8
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: rdoc
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ~>
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ~>
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -126,7 +111,6 @@ dependencies:
|
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: rb-fsevent
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
115
|
- - ! '>='
|
132
116
|
- !ruby/object:Gem::Version
|
@@ -134,7 +118,6 @@ dependencies:
|
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
122
|
- - ! '>='
|
140
123
|
- !ruby/object:Gem::Version
|
@@ -142,7 +125,6 @@ dependencies:
|
|
142
125
|
- !ruby/object:Gem::Dependency
|
143
126
|
name: simplecov
|
144
127
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
128
|
requirements:
|
147
129
|
- - ! '>='
|
148
130
|
- !ruby/object:Gem::Version
|
@@ -150,7 +132,6 @@ dependencies:
|
|
150
132
|
type: :development
|
151
133
|
prerelease: false
|
152
134
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
135
|
requirements:
|
155
136
|
- - ! '>='
|
156
137
|
- !ruby/object:Gem::Version
|
@@ -180,27 +161,26 @@ files:
|
|
180
161
|
- test/test_ip_provisioner.rb
|
181
162
|
homepage: ''
|
182
163
|
licenses: []
|
164
|
+
metadata: {}
|
183
165
|
post_install_message:
|
184
166
|
rdoc_options: []
|
185
167
|
require_paths:
|
186
168
|
- lib
|
187
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
-
none: false
|
189
170
|
requirements:
|
190
171
|
- - ! '>='
|
191
172
|
- !ruby/object:Gem::Version
|
192
173
|
version: '0'
|
193
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
-
none: false
|
195
175
|
requirements:
|
196
176
|
- - ! '>='
|
197
177
|
- !ruby/object:Gem::Version
|
198
178
|
version: '0'
|
199
179
|
requirements: []
|
200
180
|
rubyforge_project:
|
201
|
-
rubygems_version:
|
181
|
+
rubygems_version: 2.0.3
|
202
182
|
signing_key:
|
203
|
-
specification_version:
|
183
|
+
specification_version: 4
|
204
184
|
summary: Generic IP allocator for the Furnish provisioning system
|
205
185
|
test_files:
|
206
186
|
- test/helper.rb
|