resolv-srv 0.0.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b52d06ac3497bab2fa8922e14a2c2bcb1d9fb639
4
+ data.tar.gz: b3af0aaa18a42710a43312089286807e1b75fe0d
5
+ SHA512:
6
+ metadata.gz: 039252fd5c46c66b71ca38b444c364ca93294b00e151f1ced4b99a66ae73b3e8652c6e3234570266ef1ec00e915e3a84c4a33fd20dddd77e3e54505745bf1018
7
+ data.tar.gz: 86e6293c859759d2c3b43a2db1e1428d002a0f6e1d932242e102daa563b6c9c6c4c473c4c05e79c8e2f672adb4dadb6e69ea7340d18f4c054921696ce6fbd5fe
@@ -0,0 +1 @@
1
+ --protected --private --main README.md lib/**/*.rb - NEWS.md LICENSE
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2015 Jeremy Bopp
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 NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/NEWS.md ADDED
@@ -0,0 +1,11 @@
1
+ # News and Notifications by Version
2
+
3
+ This file lists noteworthy changes which may affect users of this project. More
4
+ detailed information is available in the rest of the documentation.
5
+
6
+ **NOTE:** Date stamps in the following entries are in YYYY/MM/DD format.
7
+
8
+
9
+ ## v0.0.1 (2015/08/03)
10
+
11
+ * Birthday
@@ -0,0 +1,135 @@
1
+ # Resolv SRV
2
+
3
+ Resolve and iterate over SRV DNS records correctly.
4
+
5
+ ## Links
6
+
7
+ * Homepage :: https://github.com/javanthropus/resolv-srv
8
+ * Source :: https://github.com/javanthropus/resolv-srv.git
9
+
10
+ ## Description
11
+
12
+ This gem patches the Resolv::DNS class in stdlib to include a method to resolve
13
+ and iterate over SRV records according to their relative priorities and weights.
14
+
15
+ ## Features
16
+
17
+ * Iterate over SRV resources in order by priority and randomly in proportion to
18
+ weight.
19
+
20
+ ## Known Bugs/Limitations
21
+
22
+ * None so far...
23
+
24
+ ## Synopsis
25
+
26
+ Look up your user information in Active Directory (assumes `/etc/ssl/certs`
27
+ contains the internal CA certificate for the domain):
28
+
29
+ ```ruby
30
+ #!/usr/bin/env ruby
31
+
32
+ require 'net/ldap'
33
+ require 'pp'
34
+ require 'resolv-srv'
35
+
36
+ def search_ldap(domain, username, password, search_args = {})
37
+ base = domain.split('.').map { |n| "dc=#{n}" }.join(',')
38
+ Resolv::DNS.open do |dns|
39
+ dns.each_srv_resource('ldap', 'tcp', domain) do |srv|
40
+ begin
41
+ Net::LDAP.open(
42
+ host: srv.target.to_s,
43
+ port: srv.port,
44
+ base: base,
45
+ auth: {
46
+ method: :simple,
47
+ username: username,
48
+ password: password,
49
+ },
50
+ encryption: {
51
+ method: :start_tls,
52
+ tls_options: { ca_path: '/etc/ssl/certs' }
53
+ },
54
+ ) do |ldap|
55
+ return ldap.search(search_args)
56
+ end
57
+ rescue Net::LDAP::Error, OpenSSL::SSL::SSLError
58
+ puts "Failed with host #{srv.target} on port #{srv.port}: #{$!}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ print 'AD Domain: '
65
+ domain = gets.chomp
66
+ print 'AD Username: '
67
+ username = gets.chomp
68
+ print "AD Password (#{username}): "
69
+ password = ($stdin.tty? ? $stdin.noecho(&:gets) : $stdin.gets).chomp
70
+ puts
71
+
72
+ pp search_ldap(
73
+ domain,
74
+ "#{username}@#{domain}",
75
+ password,
76
+ filter: "sAMAccountName=#{username}"
77
+ )
78
+ ```
79
+
80
+ ## Requirements
81
+
82
+ None
83
+
84
+ ## Contributing
85
+
86
+ Contributions for bug fixes, documentation, extensions, tests, etc. are
87
+ encouraged.
88
+
89
+ 1. Clone the repository.
90
+ 2. Fix a bug or add a feature.
91
+ 3. Add tests for the fix or feature.
92
+ 4. Make a pull request.
93
+
94
+ ## Development
95
+
96
+ After checking out the source, run:
97
+
98
+ $ bundle install
99
+ $ bundle exec rake test yard
100
+
101
+ This will install all dependencies, run the tests/specs, and generate the
102
+ documentation.
103
+
104
+ ## Authors
105
+
106
+ Thanks to all contributors. Without your help this project would not exist.
107
+
108
+ * Jeremy Bopp :: jeremy@bopp.net
109
+
110
+ ## License
111
+
112
+ ```
113
+ (The MIT License)
114
+
115
+ Copyright (c) 2015 Jeremy Bopp
116
+
117
+ Permission is hereby granted, free of charge, to any person obtaining
118
+ a copy of this software and associated documentation files (the
119
+ 'Software'), to deal in the Software without restriction, including
120
+ without limitation the rights to use, copy, modify, merge, publish,
121
+ distribute, sublicense, and/or sell copies of the Software, and to
122
+ permit persons to whom the Software is furnished to do so, subject to
123
+ the following conditions:
124
+
125
+ The above copyright notice and this permission notice shall be
126
+ included in all copies or substantial portions of the Software.
127
+
128
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
129
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
130
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
131
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
132
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
133
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
134
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
135
+ ```
@@ -0,0 +1,220 @@
1
+ # encoding: UTF-8
2
+ # -*- ruby -*-
3
+
4
+ require 'erb'
5
+ require 'rake/testtask'
6
+ require 'rubygems/package_task'
7
+ require 'rake/clean'
8
+ require 'yard'
9
+
10
+ # Load the gemspec file for this project.
11
+ GEMSPEC = Dir['*.gemspec'].first
12
+ SPEC = eval(File.read(GEMSPEC), nil, GEMSPEC)
13
+
14
+ # A dynamically generated list of files that should match the manifest (the
15
+ # combined contents of SPEC.files and SPEC.test_files). The idea is for this
16
+ # list to contain all project files except for those that have been explicitly
17
+ # excluded. This list will be compared with the manifest from the SPEC in order
18
+ # to help catch the addition or removal of files to or from the project that
19
+ # have not been accounted for either by an exclusion here or an inclusion in the
20
+ # SPEC manifest.
21
+ #
22
+ # NOTE:
23
+ # It is critical that the manifest is *not* automatically generated via globbing
24
+ # and the like; otherwise, this will yield a simple comparison between
25
+ # redundantly generated lists of files that probably will not protect the
26
+ # project from the unintentional inclusion or exclusion of files in the
27
+ # distribution.
28
+ PKG_FILES = FileList.new(Dir.glob('**/*', File::FNM_DOTMATCH)) do |files|
29
+ # Exclude anything that doesn't exist as well as directories.
30
+ files.exclude {|file| ! File.exist?(file) || File.directory?(file)}
31
+ # Exclude Git administrative files.
32
+ files.exclude(%r{(^|[/\\])\.git(ignore|modules|keep)?([/\\]|$)})
33
+ # Exclude editor swap/temporary files.
34
+ files.exclude('**/.*.sw?')
35
+ # Exclude the gemspec file.
36
+ files.exclude(GEMSPEC)
37
+ # Exclude the README template file.
38
+ files.exclude('README.md.erb')
39
+ # Exclude resources for bundler.
40
+ files.exclude('Gemfile', 'Gemfile.lock')
41
+ files.exclude(%r{^.bundle([/\\]|$)})
42
+ files.exclude(%r{^vendor/bundle([/\\]|$)})
43
+ # Exclude generated content, except for the README file.
44
+ files.exclude(%r{^(pkg|doc|.yardoc)([/\\]|$)})
45
+ # Exclude Rubinius compiled Ruby files.
46
+ files.exclude('**/*.rbc')
47
+ end
48
+
49
+ # Make sure that :clean and :clobber will not whack the repository files.
50
+ CLEAN.exclude('.git/**')
51
+ # Vim swap files are fair game for clean up.
52
+ CLEAN.include('**/.*.sw?')
53
+
54
+ # Returns the value of the VERSION environment variable as a Gem::Version object
55
+ # assuming it is set and a valid Gem version string. Otherwise, raises an
56
+ # exception.
57
+ def get_version_argument
58
+ version = ENV['VERSION']
59
+ if version.to_s.empty?
60
+ raise "No version specified: Add VERSION=X.Y.Z to the command line"
61
+ end
62
+ begin
63
+ Gem::Version.create(version.dup)
64
+ rescue ArgumentError
65
+ raise "Invalid version specified in `VERSION=#{version}'"
66
+ end
67
+ end
68
+
69
+ # Performs an in place, per line edit of the file indicated by _path_ by calling
70
+ # the sub method on each line and passing _pattern_, _replacement_, and _b_ as
71
+ # arguments.
72
+ def file_sub(path, pattern, replacement = nil, &b)
73
+ tmp_path = "#{path}.tmp"
74
+ File.open(path) do |infile|
75
+ File.open(tmp_path, 'w') do |outfile|
76
+ infile.each do |line|
77
+ outfile.write(line.sub(pattern, replacement, &b))
78
+ end
79
+ end
80
+ end
81
+ File.rename(tmp_path, path)
82
+ end
83
+
84
+ # Updates the version string in the gemspec file to the string in _version_.
85
+ def set_version(version)
86
+ file_sub(GEMSPEC, /(\.version\s*=\s*).*/, "\\1'#{version}'")
87
+ end
88
+
89
+ # Returns a string that is line wrapped at word boundaries, where each line is
90
+ # no longer than _line_width_ characters.
91
+ #
92
+ # This is mostly lifted directly from ActionView::Helpers::TextHelper.
93
+ def word_wrap(text, line_width = 80)
94
+ text.split("\n").collect do |line|
95
+ line.length > line_width ?
96
+ line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip :
97
+ line
98
+ end * "\n"
99
+ end
100
+
101
+ desc 'Alias for build:gem'
102
+ task :build => 'build:gem'
103
+
104
+ # Build related tasks.
105
+ namespace :build do
106
+ # Create the gem and package tasks.
107
+ Gem::PackageTask.new(SPEC).define
108
+
109
+ # Ensure that the manifest is consulted when building the gem. Any
110
+ # generated/compiled files should be available at that time.
111
+ task :gem => :check_manifest
112
+
113
+ desc 'Verify the manifest'
114
+ task :check_manifest do
115
+ manifest_files = (SPEC.files + SPEC.test_files).sort.uniq
116
+ pkg_files = PKG_FILES.sort.uniq
117
+ if manifest_files != pkg_files then
118
+ common_files = manifest_files & pkg_files
119
+ manifest_files -= common_files
120
+ pkg_files -= common_files
121
+ message = ["The manifest does not match the automatic file list."]
122
+ unless manifest_files.empty? then
123
+ message << " Extraneous files:\n " + manifest_files.join("\n ")
124
+ end
125
+ unless pkg_files.empty?
126
+ message << " Missing files:\n " + pkg_files.join("\n ")
127
+ end
128
+ raise message.join("\n")
129
+ end
130
+ end
131
+
132
+ # Creates the README.md file from its template and other sources.
133
+ file 'README.md' => ['README.md.erb', 'LICENSE', GEMSPEC] do
134
+ spec = SPEC
135
+ File.open('README.md', 'w') do |readme|
136
+ readme.write(
137
+ ERB.new(File.read('README.md.erb'), nil, '-').result(binding)
138
+ )
139
+ end
140
+ end
141
+ end
142
+
143
+ # Ensure that the clobber task also clobbers package files.
144
+ task :clobber => 'build:clobber_package'
145
+
146
+ # Create the documentation task.
147
+ YARD::Rake::YardocTask.new
148
+ # Ensure that the README file is (re)generated first.
149
+ task :yard => 'README.md'
150
+
151
+ # Gem related tasks.
152
+ namespace :gem do
153
+ desc 'Alias for build:gem'
154
+ task :build => 'build:gem'
155
+
156
+ desc 'Publish the gemfile'
157
+ task :publish => ['version:check', :test, 'repo:tag', :build] do
158
+ sh "gem push pkg/#{SPEC.name}-#{SPEC.version}*.gem"
159
+ end
160
+ end
161
+
162
+ Rake::TestTask.new do |t|
163
+ t.pattern = 'spec/**/*_spec.rb'
164
+ end
165
+
166
+ # Version string management tasks.
167
+ namespace :version do
168
+ desc 'Set the version for the project to a specified version'
169
+ task :set do
170
+ set_version(get_version_argument)
171
+ end
172
+
173
+ desc 'Set the version for the project back to 0.0.0'
174
+ task :reset do
175
+ set_version('0.0.0')
176
+ end
177
+
178
+ desc 'Check that all version strings are correctly set'
179
+ task :check => ['version:check:spec', 'version:check:news']
180
+
181
+ namespace :check do
182
+ desc 'Check that the version in the gemspec is correctly set'
183
+ task :spec do
184
+ version = get_version_argument
185
+ if version != SPEC.version
186
+ raise "The given version `#{version}' does not match the gemspec version `#{SPEC.version}'"
187
+ end
188
+ end
189
+
190
+ desc 'Check that the NEWS.md file mentions the version'
191
+ task :news do
192
+ version = get_version_argument
193
+ begin
194
+ File.open('NEWS.md') do |news|
195
+ unless news.each_line.any? {|l| l =~ /^## v#{Regexp.escape(version.to_s)} /}
196
+ raise "The NEWS.md file does not mention version `#{version}'"
197
+ end
198
+ end
199
+ rescue Errno::ENOENT
200
+ raise 'No NEWS.md file found'
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ # Repository and workspace management tasks.
207
+ namespace :repo do
208
+ desc 'Tag the current HEAD with the version string'
209
+ task :tag => :check_workspace do
210
+ version = get_version_argument
211
+ sh "git tag -s -m 'Release v#{version}' v#{version}"
212
+ end
213
+
214
+ desc 'Ensure the workspace is fully committed and clean'
215
+ task :check_workspace => ['README.md'] do
216
+ unless `git status --untracked-files=all --porcelain`.empty?
217
+ raise 'Workspace has been modified. Commit pending changes and try again.'
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,67 @@
1
+ require 'resolv'
2
+
3
+ ##
4
+ # A monkey patch for Resolv::DNS that provides a mostly RFC-compliant method for
5
+ # resolving SRV records.
6
+ class Resolv::DNS
7
+ ##
8
+ # Iterates over SRV resources for _service_ operating over _protocol_ within
9
+ # _domain_, first in order of priority and then randomly within a priority in
10
+ # proportion to weight.
11
+ #
12
+ # *NOTE:* The algorithm used causes resources with weight 0 to be selected
13
+ # before resources with higher weights slightly more often than they would be
14
+ # if strict RFC compliance were enforced.
15
+ #
16
+ # @param service [String] The service type, such as +ldap+ or +http+.
17
+ # @param protocol [String] The protocol for connections, such as +tcp+ or
18
+ # +udp+.
19
+ # @param domain [String] The DNS domain in which to search for records.
20
+ #
21
+ # @yield Resolv::DNS::Resource::IN::SRV
22
+ def each_srv_resource(service, protocol, domain)
23
+ if service.nil? || service.empty? || service.index('.')
24
+ raise ArgumentError, "Invalid service name: #{service.inspect}"
25
+ end
26
+ if protocol.nil? || protocol.empty? || protocol.index('.')
27
+ raise ArgumentError, "Invalid protocol name: #{protocol.inspect}"
28
+ end
29
+
30
+ name = "_#{service}._#{protocol}.#{domain}"
31
+
32
+ # Fetch the resources.
33
+ getresources(name, Resolv::DNS::Resource::IN::SRV).
34
+ # Group and sort them by priority.
35
+ sort_by!(&:priority).chunk(&:priority).sort.
36
+ # Iterate over the lists of resources at each priority level.
37
+ each do |priority, available|
38
+ # NOTE:
39
+ # All weight processing is shifted to be 1-based rather than 0-based.
40
+ # Because of the way selection is handled, this avoids needing to shuffle
41
+ # or sort the array elements by weight while ensuring that resources with
42
+ # weight 0 avoid ALWAYS being selected last. The trade-off is that
43
+ # resources with weight 0 may be selected before other resources slightly
44
+ # more often than otherwise.
45
+
46
+ # Tracks the total weight of all resources remaining in the available
47
+ # list.
48
+ total_weight = available.inject(0) { |sum, e| sum + e.weight + 1 }
49
+
50
+ until available.empty?
51
+ # Randomly select from the available list such that the probability of
52
+ # selecting a resource is proportional to the resource's weight.
53
+ selector = Integer(rand * total_weight) + 1
54
+ selected_idx = available.find_index do |e|
55
+ selector -= e.weight + 1
56
+ selector <= 0
57
+ end
58
+ selected = available.delete_at(selected_idx)
59
+
60
+ # Account for the removal of a resource from the available list.
61
+ total_weight -= selected.weight + 1
62
+
63
+ yield(selected)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,146 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/mock'
3
+ require 'minitest/spec'
4
+
5
+ require 'resolv-srv'
6
+
7
+ describe "each_srv_resource" do
8
+ before do
9
+ @dns = Resolv::DNS.new
10
+ domain = 'example.com'
11
+ hostname_template = "foo%i-%i-%i.#{domain}"
12
+ @prioritized_weights = [
13
+ [0, 0, 100, 400, 400],
14
+ [100],
15
+ [400, 400],
16
+ [1, 2, 3, 4, 5],
17
+ ]
18
+ @srv_resources =
19
+ @prioritized_weights.
20
+ to_enum(:each_with_index).
21
+ flat_map do |weights, priority|
22
+ weights.each_with_index.map do |weight, n|
23
+ Resolv::DNS::Resource::IN::SRV.new(
24
+ priority, weight, 12345, hostname_template % [n, priority, weight]
25
+ )
26
+ end
27
+ end.shuffle
28
+ end
29
+
30
+ after do
31
+ @dns.close
32
+ end
33
+
34
+ it 'raises an exception if the service name is invalid' do
35
+ -> {
36
+ @dns.each_srv_resource('bad.service.name', 'tcp', 'example.com') {}
37
+ }.must_raise(ArgumentError)
38
+ end
39
+
40
+ it 'raises an exception if the service name is empty' do
41
+ -> {
42
+ @dns.each_srv_resource('', 'tcp', 'example.com') {}
43
+ }.must_raise(ArgumentError)
44
+ end
45
+
46
+ it 'raises an exception if the service name is nil' do
47
+ -> {
48
+ @dns.each_srv_resource(nil, 'tcp', 'example.com') {}
49
+ }.must_raise(ArgumentError)
50
+ end
51
+
52
+ it 'raises an exception if the protocol name is invalid' do
53
+ -> {
54
+ @dns.each_srv_resource('ldap', 'bad.protocol.name', 'example.com') {}
55
+ }.must_raise(ArgumentError)
56
+ end
57
+
58
+ it 'raises an exception if the protocol name is empty' do
59
+ -> {
60
+ @dns.each_srv_resource('ldap', '', 'example.com') {}
61
+ }.must_raise(ArgumentError)
62
+ end
63
+
64
+ it 'raises an exception if the protocol name is nil' do
65
+ -> {
66
+ @dns.each_srv_resource('ldap', nil, 'example.com') {}
67
+ }.must_raise(ArgumentError)
68
+ end
69
+
70
+ it 'orders by priority' do
71
+ @dns.stub(:getresources, @srv_resources) do
72
+ @dns.to_enum(:each_srv_resource, 'ldap', 'tcp', 'example.com').
73
+ map do |srv|
74
+ srv.priority
75
+ end.
76
+ must_equal(
77
+ @prioritized_weights.
78
+ to_enum(:each_with_index).
79
+ flat_map do |weights, priority|
80
+ [priority] * weights.size
81
+ end
82
+ )
83
+ end
84
+ end
85
+
86
+ it 'orders randomly in proportion to weight' do
87
+ results = Hash.new do |h, priority|
88
+ h[priority] = Hash.new do |h2, srv|
89
+ h2[srv] = Array.new(@prioritized_weights[priority].size, 0)
90
+ end
91
+ end
92
+
93
+ rounds = 100_000
94
+ @dns.stub(:getresources, @srv_resources) do
95
+ rounds.times do
96
+ selection = -1
97
+ old_priority = 0
98
+ @dns.each_srv_resource('ldap', 'tcp', 'example.com') do |srv|
99
+ if srv.priority != old_priority
100
+ old_priority = srv.priority
101
+ selection = 0
102
+ else
103
+ selection += 1
104
+ end
105
+
106
+ results[srv.priority][srv][selection] += 1
107
+ end
108
+ end
109
+ end
110
+
111
+ results.each do |priority, srv_selections|
112
+ srv_selections.each do |srv, selections|
113
+ selections.each_with_index do |hits, position|
114
+ expected = expected_probability(
115
+ position, srv.weight, @prioritized_weights[priority]
116
+ )
117
+ actual = Float(hits) / rounds
118
+ actual.must_be_close_to(expected, 0.02)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def expected_probability(position, selected_weight, weights)
125
+ return first_probability(selected_weight, weights) if position == 0
126
+
127
+ simple_remove(weights, selected_weight).inject(0) do |sum, w|
128
+ sum +
129
+ first_probability(w, weights) *
130
+ expected_probability(
131
+ position - 1, selected_weight, simple_remove(weights, w)
132
+ )
133
+ end
134
+ end
135
+
136
+ def first_probability(selected_weight, weights)
137
+ total_weight = weights.inject(0) { |sum, weight| sum + weight + 1 }
138
+ Float(selected_weight + 1) / total_weight
139
+ end
140
+
141
+ def simple_remove(array, element)
142
+ array = array.dup
143
+ array.delete_at(array.find_index(element))
144
+ array
145
+ end
146
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resolv-srv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Bopp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.1'
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 10.1.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '10.1'
30
+ - - ">"
31
+ - !ruby/object:Gem::Version
32
+ version: 10.1.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: minitest
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.3'
40
+ - - ">"
41
+ - !ruby/object:Gem::Version
42
+ version: 5.3.1
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '5.3'
50
+ - - ">"
51
+ - !ruby/object:Gem::Version
52
+ version: 5.3.1
53
+ - !ruby/object:Gem::Dependency
54
+ name: yard
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: 0.8.7
60
+ - - ">"
61
+ - !ruby/object:Gem::Version
62
+ version: 0.8.7.3
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 0.8.7
70
+ - - ">"
71
+ - !ruby/object:Gem::Version
72
+ version: 0.8.7.3
73
+ - !ruby/object:Gem::Dependency
74
+ name: redcarpet
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '3.1'
80
+ - - ">"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.0
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.1'
90
+ - - ">"
91
+ - !ruby/object:Gem::Version
92
+ version: 3.1.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: github-markup
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '1.0'
100
+ - - ">"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.0.2
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.0'
110
+ - - ">"
111
+ - !ruby/object:Gem::Version
112
+ version: 1.0.2
113
+ - !ruby/object:Gem::Dependency
114
+ name: pry
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ description: |
128
+ This gem patches the Resolv::DNS class in stdlib to include a method to resolve
129
+ and iterate over SRV records according to their relative priorities and weights.
130
+ email:
131
+ - jeremy@bopp.net
132
+ executables: []
133
+ extensions: []
134
+ extra_rdoc_files: []
135
+ files:
136
+ - ".yardopts"
137
+ - LICENSE
138
+ - NEWS.md
139
+ - README.md
140
+ - Rakefile
141
+ - lib/resolv-srv.rb
142
+ - spec/each_srv_resource_spec.rb
143
+ homepage: https://github.com/javanthropus/resolv-srv
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.6
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Resolve and iterate over SRV DNS records correctly.
167
+ test_files:
168
+ - spec/each_srv_resource_spec.rb