better_ipaddr 0.1.2

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.
@@ -0,0 +1,142 @@
1
+ require "ipaddr"
2
+ require "better_ipaddr/classes"
3
+
4
+ module BetterIpaddr
5
+ class Space
6
+ include Enumerable
7
+
8
+ attr_reader :networks, :space, :family
9
+
10
+ def initialize(networks, space: nil, family: nil)
11
+ @family = family || infer_address_family(space, *networks)
12
+ @networks = networks.map { |network| import(network) }.sort
13
+ return unless space
14
+ @space = space
15
+ outlier = @networks.find { |net| !@space.cover?(net) }
16
+ return unless outlier
17
+ fail ArgumentError, "Address space #{@space.inspect} does not cover "\
18
+ "network #{outlier.inspect}"
19
+ end
20
+
21
+ def +(other)
22
+ self.class.new(networks + other.networks, family: family)
23
+ end
24
+
25
+ def ==(other)
26
+ networks == other.networks
27
+ end
28
+
29
+ def each
30
+ if block_given?
31
+ networks.each do |network|
32
+ yield network
33
+ end
34
+ else
35
+ networks.each
36
+ end
37
+ end
38
+
39
+ def find_by_minimum_size(size)
40
+ find_all { |net| net.size >= size }.min_by(&:prefix_length)
41
+ end
42
+
43
+ def find_by_minimum_prefix_length(length)
44
+ find_all { |net| net.prefix_length >= length }.min_by(&:prefix_length)
45
+ end
46
+
47
+ def gaps
48
+ gap_networks = if space
49
+ gaps_before + gaps_between + gaps_after
50
+ else
51
+ gaps_between
52
+ end
53
+ self.class.new(gap_networks, family: family)
54
+ end
55
+
56
+ def summarize
57
+ out = []
58
+ networks.each do |network|
59
+ summary = network.summarize_with(out.last)
60
+ if summary
61
+ out[-1] = summary
62
+ summarize_backtrack(out)
63
+ else
64
+ out << network
65
+ end
66
+ end
67
+ export(out)
68
+ end
69
+
70
+ def summarize_backtrack(list)
71
+ loop do
72
+ break unless list.size >= 2
73
+ summary = list[-1].summarize_with(list[-2])
74
+ break unless summary
75
+ list.pop 2
76
+ list << summary
77
+ end
78
+ end
79
+
80
+ def with_space(space)
81
+ export(networks, space: space)
82
+ end
83
+
84
+ private
85
+
86
+ def import(network)
87
+ case network
88
+ when String, Numeric
89
+ IPAddr[network, family]
90
+ else
91
+ network
92
+ end
93
+ end
94
+
95
+ def infer_address_family(*networks)
96
+ example = networks.find { |net| net.respond_to?(:family) }
97
+ return example.family if example
98
+ fail "Unable to infer address family"
99
+ end
100
+
101
+ def export(new_networks, space: nil)
102
+ self.class.new(new_networks, space: space, family: family)
103
+ end
104
+
105
+ def gaps_after
106
+ export([space.last.last, space.last + 1]).gaps
107
+ end
108
+
109
+ def gaps_before
110
+ export([space.first - 1, networks.first]).gaps
111
+ end
112
+
113
+ def gaps_between
114
+ gap_networks = []
115
+ summarize.each_cons(2) do |a, b|
116
+ gap_networks.concat(subnets_between(a, b))
117
+ end
118
+ export(gap_networks)
119
+ end
120
+
121
+ def subnets_between(before, after)
122
+ subnets = []
123
+ candidate = before.last + 1
124
+ while candidate < after
125
+ candidate = max_supernet_between(before, after, candidate)
126
+ break unless candidate
127
+ subnets << candidate
128
+ candidate = candidate.last + 1
129
+ end
130
+ subnets
131
+ end
132
+
133
+ def max_supernet_between(before, after, start)
134
+ next_candidate = start
135
+ until next_candidate.overlap?(before) || next_candidate.overlap?(after)
136
+ candidate = next_candidate
137
+ next_candidate = next_candidate.grow(1)
138
+ end
139
+ candidate
140
+ end
141
+ end # class Space
142
+ end # module BetterIpaddr
@@ -0,0 +1,3 @@
1
+ module BetterIpaddr
2
+ VERSION = "0.1.2"
3
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_ipaddr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Ben Miller
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description:
56
+ email:
57
+ - bmiller@rackspace.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - CODE_OF_CONDUCT.md
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - better_ipaddr.gemspec
70
+ - bin/console
71
+ - bin/setup
72
+ - lib/better_ipaddr.rb
73
+ - lib/better_ipaddr/classes.rb
74
+ - lib/better_ipaddr/core_extension.rb
75
+ - lib/better_ipaddr/methods.rb
76
+ - lib/better_ipaddr/space.rb
77
+ - lib/better_ipaddr/version.rb
78
+ homepage: https://github.com/bjmllr/better_ipaddr
79
+ licenses:
80
+ - GPL-3.0
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.5.1
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: IPAddr enhancements for network management.
102
+ test_files: []
103
+ has_rdoc: