furnish-ip 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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=
@@ -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
@@ -2,5 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in furnish-ip.gemspec
4
4
  gemspec
5
-
6
- gem 'guard-rake', :git => "https://github.com/erikh/guard-rake", :branch => "failure_ok"
data/Guardfile CHANGED
@@ -5,6 +5,6 @@ guard 'minitest' do
5
5
  watch(%r!^test/(?:mt_cases|helper)\.rb!) { "test" }
6
6
  end
7
7
 
8
- guard 'rake', :failure_ok => true, :run_on_all => false, :task => 'rdoc_cov' do
8
+ guard 'rake', :run_on_all => false, :task => 'rdoc_cov' do
9
9
  watch(%r!^lib/(.*)([^/]+)\.rb!)
10
10
  end
@@ -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.4'
21
- gem.add_dependency 'palsy', '~> 0.0.2'
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'
@@ -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
- return this_ip unless allocated.include?(this_ip)
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, *ips)
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
- groups[name] = group
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
- allocated.delete(ip)
181
+ deallocate(ip)
131
182
  end
132
183
 
133
184
  groups.delete(name)
@@ -1,6 +1,6 @@
1
1
  module Furnish
2
2
  class IP
3
3
  # Version for furnish-ip
4
- VERSION = "0.0.3"
4
+ VERSION = "0.1.0"
5
5
  end
6
6
  end
@@ -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
- # The name of the provisioner group, set at scheduling time.
15
- attr_accessor :name
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
- # Create the provisioner. Takes a Furnish::IP object that has subnet
19
- # semantics (see Furnish::IP#new for more information) and a number of
20
- # addresses to allocate, default 1.
21
- def initialize(ip, number_of_addresses=1)
22
- @ip = ip
23
- @number_of_addresses = number_of_addresses
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
- def startup(*args)
30
- @number_of_addresses.times do
31
- @ip.assign_group_ips(name, @ip.unused_ip)
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 @ip.group_ips(name)
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
- def shutdown
40
- @ip.decommission_group(name)
41
- return true
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
- @ip.group_ips(name).to_a
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
- # The name of the provisioner group, set at scheduling time.
12
- attr_accessor :name
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. Takes a Furnish::IP object, and uses no
17
- # auto-allocation features.
30
+ # Create the provisioner, requires :ip be passed and referring to a
31
+ # Furnish::IP object.
18
32
  #
19
- def initialize(ip)
20
- @ip = ip
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 results passed to the argument list (presumably from a
25
- # previously-run provisioner) in a Furnish::IP group named after the name
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(*args)
31
- @ip.assign_group_ips(name, *args.flatten)
32
- return @ip.group_ips(name)
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
- @ip.decommission_group(name)
40
- return true
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
- @ip.group_ips(name).to_a
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
- Furnish::Provisioner::AutoIP.new(@ip, num)
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.name, "name reflects provisioner name")
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
@@ -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 return as an array"
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", *ip_arg),
90
- "array is returned when multiple arguments passed"
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")
@@ -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
- attr_accessor :name
6
+ class IPReturningProvisioner < Furnish::Provisioner::API
7
+ furnish_property :ips, "An array of IP addresses as strings", Array
6
8
 
7
- def initialize(*ips)
8
- @ips = ips
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
- def startup(*args)
12
- return @ips
14
+ configure_shutdown do
15
+ accepts_from_any true
13
16
  end
14
17
 
15
- def shutdown
16
- return true
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(*ips),
33
- Furnish::Provisioner::IP.new(@ip)
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.name, "name reflects group name")
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.3
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-03-25 00:00:00.000000000 Z
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.4
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.4
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.2
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.2
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: '0'
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: '0'
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: 1.8.25
181
+ rubygems_version: 2.0.3
202
182
  signing_key:
203
- specification_version: 3
183
+ specification_version: 4
204
184
  summary: Generic IP allocator for the Furnish provisioning system
205
185
  test_files:
206
186
  - test/helper.rb