resolv-hosts-dynamic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 625a6c978f45ec588d4b5711ba9812ff771df9bd
4
+ data.tar.gz: d8fe024b406abc13f2b5a673cc7a7966d01259d5
5
+ SHA512:
6
+ metadata.gz: ddfc51c87e75e33ae548e17f9dd08ce5423a5a6c765d275419c521ba6cef2d5819547bfd7dcfcd707a622ebc91fb3dd45fa14cda7b24090bb4cd4a8751551b39
7
+ data.tar.gz: ccefb782906119fd46b398159d1e1f09d7a5aae83685187cbc2829a0a077634859eff689295312788d91b458aa8c50f97b369ba808367d253e37e50e9a393414
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format
2
+ documentation
3
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in resolv-hosts-dynamic.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Chris Reeves
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # Resolv::Hosts::Dynamic
2
+
3
+ Dynamic in-memory 'hosts' file for resolving hostnames. Injects entries into
4
+ an in-memory 'hosts' file which can later be used for name resolution without
5
+ having to modify the system hosts file. This is an extension to the standard
6
+ ruby Resolv library and is useful for over-riding name resolution during
7
+ testing.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'resolv-hosts-dynamic'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install resolv-hosts-dynamic
24
+
25
+ ## Usage
26
+
27
+ ### Adding entries to the dynamic host resolver
28
+
29
+ Entries can be added during class instantiation or at any point afterwards
30
+ (via the `add_address` function) if we've still got a handle on the object. An
31
+ entry consists of a hash with the `addr` and `hostname` properties, plus an
32
+ optional `aliases` property. Entries added during class instantiation can be
33
+ in the form of a single entry or an array of entries. `add_address` only
34
+ accepts a single entry at a time.
35
+
36
+ ```ruby
37
+ require 'resolv-hosts-dynamic'
38
+
39
+ res = Resolv::Hosts::Dynamic.new([
40
+ {
41
+ 'addr' => '127.1.2.3',
42
+ 'hostname' => 'host.example.com',
43
+ },
44
+ {
45
+ 'addr' => '127.4.5.6',
46
+ 'hostname' => 'host2.example.com',
47
+ 'aliases' => 'host2',
48
+ },
49
+ ])
50
+
51
+ res.add_address({
52
+ 'addr' => '127.7.8.9',
53
+ 'hostname' => 'host3.example.com',
54
+ 'aliases' => [ 'host3', 'www.example.com' ],
55
+ })
56
+ ```
57
+
58
+ ### Resolving hostnames/IPs
59
+
60
+ This class can be used on its own or within the standard ruby Resolv library.
61
+
62
+ On its own:
63
+ ```ruby
64
+ require 'resolv-hosts-dynamic'
65
+
66
+ res = Resolv::Hosts::Dynamic.new({
67
+ 'addr' => '127.1.2.3',
68
+ 'hostname' => 'host.example.com',
69
+ })
70
+
71
+ res.getaddress('host.example.com')
72
+ res.getname('127.1.2.3')
73
+ ```
74
+
75
+ Within the standard ruby Resolv library:
76
+ ```ruby
77
+ require 'resolv-hosts-dynamic'
78
+
79
+ res = Resolv.new([
80
+ Resolv::Hosts::Dynamic.new({
81
+ 'addr' => '127.1.2.3',
82
+ 'hostname' => 'host.example.com',
83
+ }),
84
+ Resolv::Hosts.new,
85
+ Resolv::DNS.new,
86
+ ])
87
+
88
+ res.getaddress('host.example.com')
89
+ res.getname('127.1.2.3')
90
+
91
+ res.getaddresses('rubygems.org')
92
+ ```
93
+
94
+ Replacing the default resolver in the standard ruby Resolv library (using
95
+ `resolve-replace`):
96
+ ```ruby
97
+ require 'resolv-hosts-dynamic'
98
+ require 'resolv-replace'
99
+
100
+ dynres = Resolv::Hosts::Dynamic.new({
101
+ 'addr' => '127.1.2.3',
102
+ 'hostname' => 'host.example.com',
103
+ })
104
+
105
+ Resolv::DefaultResolver.replace_resolvers([
106
+ dynres,
107
+ Resolv::Hosts.new,
108
+ Resolv::DNS.new,
109
+ ])
110
+
111
+ Resolv.getaddress('host.example.com')
112
+ Resolv.getname('127.1.2.3')
113
+ Resolv.getaddresses('www.google.com')
114
+
115
+ dynres.add_address({
116
+ 'addr' => '127.4.5.6',
117
+ 'hostname' => 'www.google.com',
118
+ })
119
+
120
+ Resolv.getaddresses('www.google.com')
121
+ ```
122
+
123
+ ## Contributing
124
+
125
+ 1. Fork it ( https://github.com/chris-reeves/gem-resolv-hosts-dynamic/fork )
126
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
127
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
128
+ 4. Push to the branch (`git push origin my-new-feature`)
129
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,104 @@
1
+ require 'resolv'
2
+
3
+ class Resolv
4
+ class Hosts
5
+ class Dynamic
6
+
7
+ def initialize(hosts = [])
8
+ @mutex = Mutex.new
9
+ @name2addr = {}
10
+ @addr2name = {}
11
+
12
+ hosts = [hosts] if !hosts.is_a? Array
13
+
14
+ hosts.each { |host|
15
+ self.add_address(host)
16
+ }
17
+ end
18
+
19
+ ##
20
+ # Adds +host+ to the custom resolver.
21
+
22
+ def add_address(host)
23
+ @mutex.synchronize {
24
+ addr = host['addr']
25
+ hostname = host['hostname']
26
+ aliases = host['aliases']
27
+
28
+ raise "Must specify 'addr' for host" unless addr
29
+ raise "Must specify 'hostname' for host" unless hostname
30
+
31
+ addr.untaint
32
+ hostname.untaint
33
+
34
+ # So that aliases can be passed a string or an array of strings
35
+ aliases = [aliases] if aliases.is_a? String
36
+
37
+ @addr2name[addr] = [] unless @addr2name.include? addr
38
+ @addr2name[addr] << hostname
39
+ @addr2name[addr] += aliases if aliases
40
+ @name2addr[hostname] = [] unless @name2addr.include? hostname
41
+ @name2addr[hostname] << addr
42
+ aliases.each {|n|
43
+ n.untaint
44
+ @name2addr[n] = [] unless @name2addr.include? n
45
+ @name2addr[n] << addr
46
+ } if aliases
47
+ }
48
+ end
49
+
50
+ ##
51
+ # Gets the IP address of +name+ from the custom resolver.
52
+
53
+ def getaddress(name)
54
+ each_address(name) {|address| return address}
55
+ raise ResolvError.new("No dynamic hosts entry for name: #{name}")
56
+ end
57
+
58
+ ##
59
+ # Gets all IP addresses for +name+ from the custom resolver.
60
+
61
+ def getaddresses(name)
62
+ ret = []
63
+ each_address(name) {|address| ret << address}
64
+ return ret
65
+ end
66
+
67
+ ##
68
+ # Iterates over all IP addresses for +name+ retrieved from the custom resolver.
69
+
70
+ def each_address(name, &proc)
71
+ if @name2addr.include?(name)
72
+ @name2addr[name].each(&proc)
73
+ end
74
+ end
75
+
76
+ ##
77
+ # Gets the hostname of +address+ from the custom resolver.
78
+
79
+ def getname(address)
80
+ each_name(address) {|name| return name}
81
+ raise ResolvError.new("No dynamic hosts entry for address: #{address}")
82
+ end
83
+
84
+ ##
85
+ # Gets all hostnames for +address+ from the custom resolver.
86
+
87
+ def getnames(address)
88
+ ret = []
89
+ each_name(address) {|name| ret << name}
90
+ return ret
91
+ end
92
+
93
+ ##
94
+ # Iterates over all hostnames for +address+ retrieved from the custom resolver.
95
+
96
+ def each_name(address, &proc)
97
+ if @addr2name.include?(address)
98
+ @addr2name[address].each(&proc)
99
+ end
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "resolv-hosts-dynamic"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Chris Reeves"]
9
+ spec.email = ["chris.reeves@york.ac.uk"]
10
+ spec.summary = %q{Dynamic in-memory 'hosts' file for resolving hostnames.}
11
+ spec.description = %q{Dynamic in-memory 'hosts' file for resolving hostnames. Injects entries into an in-memory 'hosts' file which can later be used for name resolution without having to modify the system hosts file. This is an extension to the standard ruby Resolv library and is useful for over-riding name resolution during testing.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec"
23
+ end
@@ -0,0 +1,287 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resolv::Hosts::Dynamic do
4
+
5
+ describe '#initialize' do
6
+ context 'with an empty params list' do
7
+ res = Resolv::Hosts::Dynamic.new
8
+
9
+ it 'should have empty lookup maps' do
10
+ expect(
11
+ res.instance_variable_get(:@name2addr).empty?
12
+ ).to eq true
13
+
14
+ expect(
15
+ res.instance_variable_get(:@addr2name).empty?
16
+ ).to eq true
17
+ end
18
+ end
19
+
20
+ context 'with a single (hash) param' do
21
+ res = Resolv::Hosts::Dynamic.new({
22
+ 'addr' => '127.1.2.3',
23
+ 'hostname' => 'host.example.com',
24
+ })
25
+
26
+ it 'should have a single record in the name2addr map' do
27
+ expect(
28
+ res.instance_variable_get(:@name2addr).size
29
+ ).to eq 1
30
+ end
31
+
32
+ it 'should have a single record in the addr2name map' do
33
+ expect(
34
+ res.instance_variable_get(:@addr2name).size
35
+ ).to eq 1
36
+ end
37
+ end
38
+
39
+ context 'with a single (array) param' do
40
+ res = Resolv::Hosts::Dynamic.new([
41
+ {
42
+ 'addr' => '127.1.2.3',
43
+ 'hostname' => 'host.example.com',
44
+ },
45
+ {
46
+ 'addr' => '127.4.5.6',
47
+ 'hostname' => 'host2.example.com',
48
+ },
49
+ {
50
+ 'addr' => '127.7.8.9',
51
+ 'hostname' => 'host3.example.com',
52
+ },
53
+ ])
54
+
55
+ it 'should have three records in the name2addr map' do
56
+ expect(
57
+ res.instance_variable_get(:@name2addr).size
58
+ ).to eq 3
59
+ end
60
+
61
+ it 'should have three records in the addr2name map' do
62
+ expect(
63
+ res.instance_variable_get(:@addr2name).size
64
+ ).to eq 3
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#add_address' do
70
+ context 'with a simple hostname -> address map' do
71
+ res = Resolv::Hosts::Dynamic.new
72
+
73
+ res.add_address({
74
+ 'addr' => '127.1.2.3',
75
+ 'hostname' => 'host.example.com',
76
+ })
77
+
78
+ it 'should map the hostname to the address' do
79
+ expect(
80
+ res.instance_variable_get(:@name2addr)['host.example.com']
81
+ ).to eq(['127.1.2.3'])
82
+ end
83
+
84
+ it 'should map the address to the hostname' do
85
+ expect(
86
+ res.instance_variable_get(:@addr2name)['127.1.2.3']
87
+ ).to eq(['host.example.com'])
88
+ end
89
+ end
90
+
91
+ context 'with a hostname plus a single alias' do
92
+ res = Resolv::Hosts::Dynamic.new
93
+
94
+ res.add_address({
95
+ 'addr' => '127.1.2.3',
96
+ 'hostname' => 'host.example.com',
97
+ 'aliases' => 'host',
98
+ })
99
+
100
+ it 'should map the hostname to the address' do
101
+ expect(
102
+ res.instance_variable_get(:@name2addr)['host.example.com']
103
+ ).to eq(['127.1.2.3'])
104
+ end
105
+
106
+ it 'should map the alias to the address' do
107
+ expect(
108
+ res.instance_variable_get(:@name2addr)['host']
109
+ ).to eq(['127.1.2.3'])
110
+ end
111
+
112
+ it 'should map the address to the hostname and alias' do
113
+ expect(
114
+ res.instance_variable_get(:@addr2name)['127.1.2.3']
115
+ ).to eq(['host.example.com', 'host'])
116
+ end
117
+ end
118
+
119
+ context 'with a hostname plus multiple aliases' do
120
+ res = Resolv::Hosts::Dynamic.new
121
+
122
+ res.add_address({
123
+ 'addr' => '127.1.2.3',
124
+ 'hostname' => 'host.example.com',
125
+ 'aliases' => [ 'host', 'host2' ],
126
+ })
127
+
128
+ it 'should map the hostname to the address' do
129
+ expect(
130
+ res.instance_variable_get(:@name2addr)['host.example.com']
131
+ ).to eq(['127.1.2.3'])
132
+ end
133
+
134
+ it 'should map both aliases to the address' do
135
+ expect(
136
+ res.instance_variable_get(:@name2addr)['host']
137
+ ).to eq(['127.1.2.3'])
138
+
139
+ expect(
140
+ res.instance_variable_get(:@name2addr)['host2']
141
+ ).to eq(['127.1.2.3'])
142
+ end
143
+
144
+ it 'should map the address to the hostname and the aliases' do
145
+ expect(
146
+ res.instance_variable_get(:@addr2name)['127.1.2.3']
147
+ ).to eq(['host.example.com', 'host', 'host2'])
148
+ end
149
+ end
150
+
151
+ context 'with multiple hostnames for the same address added in separate calls' do
152
+ res = Resolv::Hosts::Dynamic.new
153
+
154
+ res.add_address({
155
+ 'addr' => '127.1.2.3',
156
+ 'hostname' => 'host.example.com',
157
+ })
158
+
159
+ res.add_address({
160
+ 'addr' => '127.1.2.3',
161
+ 'hostname' => 'host2.example.com',
162
+ })
163
+
164
+ it 'should map both hostnames to the address' do
165
+ expect(
166
+ res.instance_variable_get(:@name2addr)['host.example.com']
167
+ ).to eq(['127.1.2.3'])
168
+
169
+ expect(
170
+ res.instance_variable_get(:@name2addr)['host2.example.com']
171
+ ).to eq(['127.1.2.3'])
172
+ end
173
+
174
+ it 'should map the address to both hostnames' do
175
+ expect(
176
+ res.instance_variable_get(:@addr2name)['127.1.2.3']
177
+ ).to eq(['host.example.com', 'host2.example.com'])
178
+ end
179
+ end
180
+
181
+ context 'with multiple addresses for the same hostname' do
182
+ res = Resolv::Hosts::Dynamic.new
183
+
184
+ res.add_address({
185
+ 'addr' => '127.1.2.3',
186
+ 'hostname' => 'host.example.com',
187
+ })
188
+
189
+ res.add_address({
190
+ 'addr' => '127.4.5.6',
191
+ 'hostname' => 'host.example.com',
192
+ })
193
+
194
+ it 'should map the hostname to both addresses' do
195
+ expect(
196
+ res.instance_variable_get(:@name2addr)['host.example.com']
197
+ ).to eq(['127.1.2.3', '127.4.5.6'])
198
+ end
199
+
200
+ it 'should map both addresses to the hostname' do
201
+ expect(
202
+ res.instance_variable_get(:@addr2name)['127.1.2.3']
203
+ ).to eq(['host.example.com'])
204
+
205
+ expect(
206
+ res.instance_variable_get(:@addr2name)['127.4.5.6']
207
+ ).to eq(['host.example.com'])
208
+ end
209
+ end
210
+ end
211
+
212
+ # takes the first ip if there are multiple IPs
213
+ describe 'resolver methods' do
214
+ dynres = Resolv::Hosts::Dynamic.new
215
+
216
+ # address with multiple names
217
+ dynres.add_address({
218
+ 'addr' => '127.1.2.3',
219
+ 'hostname' => 'host.example.com',
220
+ 'aliases' => 'host'
221
+ })
222
+
223
+ # name with multiple addresses
224
+ dynres.add_address({
225
+ 'addr' => '127.4.5.6',
226
+ 'hostname' => 'host.example.com',
227
+ })
228
+
229
+ res = Resolv.new([dynres])
230
+
231
+ describe '#getaddress' do
232
+ it 'resolves host.example.com to a single address' do
233
+ expect(
234
+ res.getaddress('host.example.com')
235
+ ).to eq '127.1.2.3'
236
+ end
237
+
238
+ it 'raises ResolvError if the name can not be looked up' do
239
+ expect{
240
+ res.getaddress('no.such.host.')
241
+ }.to raise_error(Resolv::ResolvError)
242
+ end
243
+ end
244
+
245
+ describe '#getaddresses' do
246
+ it 'resolves host.example.com to multiple addresses' do
247
+ expect(
248
+ res.getaddresses('host.example.com')
249
+ ).to eq [ '127.1.2.3', '127.4.5.6' ]
250
+ end
251
+
252
+ it 'resolves to no addresses if the name can not be looked up' do
253
+ expect(
254
+ res.getaddresses('no.such.host.').empty?
255
+ ).to be true
256
+ end
257
+ end
258
+
259
+ describe '#getname' do
260
+ it 'resolves 127.1.2.3 to a single hostname' do
261
+ expect(
262
+ res.getname('127.1.2.3')
263
+ ).to eq 'host.example.com'
264
+ end
265
+
266
+ it 'raises ResolvError if the address can not be looked up' do
267
+ expect{
268
+ res.getname('127.7.8.9')
269
+ }.to raise_error(Resolv::ResolvError)
270
+ end
271
+ end
272
+
273
+ describe '#getnames' do
274
+ it 'resolves 127.1.2.3 to a single hostname' do
275
+ expect(
276
+ res.getnames('127.1.2.3')
277
+ ).to eq [ 'host.example.com', 'host' ]
278
+ end
279
+
280
+ it 'resolves to no hostnames if the address can not be looked up' do
281
+ expect(
282
+ res.getnames('127.7.8.9').empty?
283
+ ).to be true
284
+ end
285
+ end
286
+ end
287
+ end
@@ -0,0 +1 @@
1
+ require 'resolv-hosts-dynamic'
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resolv-hosts-dynamic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Reeves
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-08 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Dynamic in-memory 'hosts' file for resolving hostnames. Injects entries
56
+ into an in-memory 'hosts' file which can later be used for name resolution without
57
+ having to modify the system hosts file. This is an extension to the standard ruby
58
+ Resolv library and is useful for over-riding name resolution during testing.
59
+ email:
60
+ - chris.reeves@york.ac.uk
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".gitignore"
66
+ - ".rspec"
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - lib/resolv-hosts-dynamic.rb
72
+ - resolv-hosts-dynamic.gemspec
73
+ - spec/resolv-hosts-dynamic_spec.rb
74
+ - spec/spec_helper.rb
75
+ homepage: ''
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.4.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Dynamic in-memory 'hosts' file for resolving hostnames.
99
+ test_files:
100
+ - spec/resolv-hosts-dynamic_spec.rb
101
+ - spec/spec_helper.rb