minidisc 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 772484f3ea8aabab0df47ecbdc0f750aa05a615c13deff11cbdaf5528207bac2
4
+ data.tar.gz: 8783d9fe8da2adbd5aacf4cf48e6523a64655c02dff60c1ec2d67f626c265eb3
5
+ SHA512:
6
+ metadata.gz: 4b70e300ada3eb91ec7bbe32df10fd2c8cb3bb86f330e5adbd7c44414babed24246d1bd7bbe00d66f00be86d0256b6b5d231fa7d86717b8cc5cd2bacb2a58ad1
7
+ data.tar.gz: df8811859ef7ad5adf95294477a74ed0f0bf7d3426acca07734db79a58c787a33f4b65cc1e781caf3dfbcaa5405686241950be722c446c421640f028769090a5
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2017-2019 Ari Russo
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,48 @@
1
+ # MiniDisc
2
+
3
+ Mini service discovery in Ruby
4
+
5
+ ## Description
6
+
7
+ I recently extracted MiniDisc from a personal project I've been working on. It offers a single line interface for common patterns in service discovery that I'd been redundantly implementing.
8
+
9
+ Under the hood it wraps the DNSSD gem and is cross compatible with services using that. It adds helpers for common tasks like matching services by name, dynamically overriding discovery, error handling, logging
10
+
11
+ ## Requirements
12
+
13
+ ### Linux
14
+
15
+ * dns-sd
16
+ * avahi 0.6.25+ (plus libavahi-compat-libdnssd-dev on Debian)
17
+
18
+ ## Usage
19
+
20
+ To broadcast a service use something like:
21
+
22
+ ```ruby
23
+ require "minidisc"
24
+
25
+ MiniDisc::Registry.add(:http, 8080, id: "my-service-instance1")
26
+ ```
27
+
28
+ To discover other services use
29
+
30
+ ```ruby
31
+ MiniDisc::Discover.find_all(:http, id: /^my-service/) do |services|
32
+ ...
33
+ end
34
+ ```
35
+
36
+ ## Installation
37
+
38
+ `gem install minidisc`
39
+
40
+ or when Bundler, add this to your Gemfile
41
+
42
+ `gem "minidisc"`
43
+
44
+ ## License
45
+
46
+ Apache 2.0, See LICENSE file
47
+
48
+ Copyright (c) 2017-2019 [Ari Russo](http://arirusso.com)
@@ -0,0 +1,12 @@
1
+ require "dnssd"
2
+ require "logger"
3
+
4
+ require "minidisc/network"
5
+
6
+ require "minidisc/service_type"
7
+ require "minidisc/registry"
8
+ require "minidisc/discover"
9
+
10
+ module MiniDisc
11
+ VERSION = "0.0.4"
12
+ end
@@ -0,0 +1,95 @@
1
+ require "minidisc/discover/network"
2
+
3
+ module MiniDisc
4
+
5
+ class Discover
6
+
7
+ class << self
8
+
9
+ def services(service_type, options = {}, &block)
10
+ ensure_initialized(options)
11
+ service_type = ServiceType.sym_to_dnnsd_string(service_type, options)
12
+ discover(service_type, options, &block)
13
+ @destinations
14
+ end
15
+
16
+ private
17
+
18
+ def ensure_initialized(options)
19
+ @logger ||= options[:logger] || Logger.new(STDOUT)
20
+ @destinations ||= []
21
+ end
22
+
23
+ def discover(service_type, options = {}, &block)
24
+ @destinations = if options[:override].nil?
25
+ from_discovery(service_type, id: options[:id], timeout: options[:timeout], &block)
26
+ else
27
+ from_override(options[:override], &block)
28
+ end
29
+ end
30
+
31
+ def from_override(services, &block)
32
+ i = 0;
33
+ service_objects = services.map do |service|
34
+ Service.new("override_#{i += 1}", service[:host], port: service[:port])
35
+ end
36
+ @logger.info("Destinations: Overriding discovery with #{services.count} services")
37
+ yield(service_objects) if block_given?
38
+ service_objects
39
+ end
40
+
41
+ def match?(match_on, service_name)
42
+ match_on.kind_of?(Regexp) && service_name.match(match_on) ||
43
+ match_on == service_name
44
+ end
45
+
46
+ def from_discovery(service_type, options = {}, &block)
47
+ services = Network.services_with_timeout(service_type, timeout: options[:timeout])
48
+ unless options[:id].nil?
49
+ services.select! do |service|
50
+ match?(options[:id], service[:name])
51
+ end
52
+ end
53
+ service_objects = service_hashes_to_service_objects(services)
54
+ @logger.info("Destinations: Discovered #{services.count} services")
55
+ yield(service_objects) if block_given?
56
+ service_objects
57
+ end
58
+
59
+ def service_hashes_to_service_objects(services)
60
+ services.map do |service|
61
+ Service.new(service[:name], service[:target], port: service[:port])
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ class Service
68
+
69
+ include Comparable
70
+
71
+ attr_reader :id, :host, :port
72
+
73
+ def initialize(id, host, options = {})
74
+ @id = id
75
+ @host = host
76
+ @port = options.fetch(:port, 8080)
77
+ end
78
+
79
+ def <=>(other)
80
+ to_h <=> other.to_h
81
+ end
82
+
83
+ def to_h
84
+ {
85
+ id: @id,
86
+ host: @host,
87
+ port: @port
88
+ }
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,59 @@
1
+ require "timeout"
2
+
3
+ module MiniDisc
4
+
5
+ class Discover
6
+
7
+ module Network
8
+
9
+ DEFAULT_TIMEOUT_LIMIT = 2
10
+
11
+ extend self
12
+
13
+ # @param [String] service_type with protocol eg "_telnet._tcp"
14
+ # @param [Hash] options
15
+ # @option options [Integer] :timeout Timeout in seconds
16
+ # @return [Array<Hash>]
17
+ def services_with_timeout(service_type, options = {}, &block)
18
+ timeout = options[:timeout] || DEFAULT_TIMEOUT_LIMIT
19
+ Timeout::timeout(timeout) do
20
+ result = services(service_type, &block)
21
+ end
22
+ rescue Timeout::Error => e
23
+ result = []
24
+ ensure
25
+ yield(result) if block_given?
26
+ result
27
+ end
28
+
29
+ # @param [String] service_type with protocol eg "_telnet._tcp"
30
+ # @return [Array<Hash>]
31
+ def services(service_type)
32
+ Thread.abort_on_exception = true
33
+ replies = {}
34
+ DNSSD.browse!(service_type) do |reply|
35
+ replies[reply.name] = reply
36
+ if !reply.flags.more_coming?
37
+ available_replies = replies.select do |_, service|
38
+ service.flags.add?
39
+ end
40
+ return available_replies.map do |_, service|
41
+ resolve = service.resolve
42
+ {
43
+ name: service.name,
44
+ target: resolve.target,
45
+ port: resolve.port
46
+ }
47
+ end
48
+ end
49
+
50
+ end
51
+ rescue Errno::EBADF, DNSSD::ServiceNotRunningError
52
+ []
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,15 @@
1
+ module MiniDisc
2
+ module Network
3
+
4
+ extend self
5
+
6
+ def add(*a, &block)
7
+ Registry.add(*a, &block)
8
+ end
9
+
10
+ def find_all(*a, &block)
11
+ Discover.services(*a, &block)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module MiniDisc
2
+
3
+ module Registry
4
+
5
+ # Register a service
6
+ # @param [Integer] port
7
+ # @return [Discovery]
8
+ def self.add(service_type, port, options = {})
9
+ ensure_logger
10
+ @services ||= []
11
+ service = Registry::Service.new(service_type, port, options)
12
+ service.register(logger: @logger)
13
+ @services << service
14
+ service
15
+ end
16
+
17
+ private
18
+
19
+ def self.ensure_logger(options = {})
20
+ @logger ||= options[:logger] || Logger.new(STDOUT)
21
+ end
22
+
23
+ class Service
24
+
25
+ attr_reader :id, :logger, :port
26
+
27
+ # @param [Symbol] service_type eg :telnet
28
+ # @param [Integer] port
29
+ def initialize(service_type, port, options = {})
30
+ @id = options.fetch(:id, object_id.to_s)
31
+ @port = port
32
+ @service_type = ServiceType.sym_to_dnnsd_string(service_type, options)
33
+ end
34
+
35
+ def registered?
36
+ @registered
37
+ end
38
+
39
+ # Register this service
40
+ # @return [Boolean]
41
+ def register(options = {})
42
+ DNSSD.register(@id, @service_type, nil, @port) do
43
+ properties = "id=#{@id} port=#{@port} service_type=#{@service_type}"
44
+ unless options[:logger].nil?
45
+ options[:logger].info("MiniDisc::Registry::Service#register: #{properties}")
46
+ end
47
+ end
48
+ @registered = true
49
+ rescue Errno::EBADF
50
+ @registered = false
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,13 @@
1
+ module MiniDisc
2
+
3
+ module ServiceType
4
+
5
+ def self.sym_to_dnnsd_string(service_type, options = {})
6
+ protocol = options.fetch(:protocol, :tcp).to_s
7
+ protocol.gsub!(/\_/, "-")
8
+ "_#{service_type}._#{protocol}"
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,47 @@
1
+ require "helper"
2
+
3
+ describe MiniDisc::Discover::Network do
4
+ describe "services_with_timeout" do
5
+ let!(:start_time) { Time.now }
6
+ let(:block) do
7
+ ->(service_type) do
8
+ loop {}
9
+ :done
10
+ end
11
+ end
12
+
13
+ before do
14
+ expect(MiniDisc::Discover::Network).to(receive(:services, &block))
15
+ end
16
+
17
+ context "with block" do
18
+
19
+ before do
20
+ MiniDisc::Discover::Network.services_with_timeout(:http) do |result|
21
+ @result = result
22
+ end
23
+ end
24
+
25
+ it "times out and returns empty array" do
26
+ expect(@result).to_not(eql(:done))
27
+ expect(@result).to(be_kind_of(Array))
28
+ expect(@result).to(be_empty)
29
+ end
30
+
31
+ end
32
+
33
+ context "without block" do
34
+
35
+ before do
36
+ @result = MiniDisc::Discover::Network.services_with_timeout(:http)
37
+ end
38
+
39
+ it "times out and returns empty array" do
40
+ expect(@result).to_not(eql(:done))
41
+ expect(@result).to(be_kind_of(Array))
42
+ expect(@result).to(be_empty)
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,120 @@
1
+ require "helper"
2
+
3
+ describe MiniDisc::Discover do
4
+ describe ".services" do
5
+
6
+ context "from override file" do
7
+ let(:host) { "something.local." }
8
+ let(:port) { "80" }
9
+ let(:config_service) do
10
+ {
11
+ host: host,
12
+ port: port
13
+ }
14
+ end
15
+
16
+ let(:destinations) do
17
+ MiniDisc::Discover.services(:http, override: [config_service])
18
+ end
19
+
20
+ it "populates" do
21
+ expect(destinations).to_not(be_nil)
22
+ expect(destinations).to_not(be_empty)
23
+ end
24
+
25
+ it "has correct data" do
26
+ expect(destinations.count).to(eq(1))
27
+ destination = destinations.first
28
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
29
+ expect(destination.id).to(eq("override_1"))
30
+ expect(destination.host).to(eq(host))
31
+ expect(destination.port).to(eq(port))
32
+ end
33
+ end
34
+
35
+ context "from discovery" do
36
+ let(:name) { "minidisc-test_service" }
37
+ let(:host) { "testservice.local." }
38
+ let(:port) { "8080" }
39
+ let(:service) do
40
+ {
41
+ name: name,
42
+ target: host,
43
+ port: port
44
+ }
45
+ end
46
+
47
+ before(:each) do
48
+ expect(MiniDisc::Discover::Network).to(receive(:services_with_timeout).at_least(:once).and_return([service]))
49
+ end
50
+
51
+ context "with id matching" do
52
+ let(:destinations) do
53
+ MiniDisc::Discover.services(:http, match: /minidisc\-.+/)
54
+ end
55
+
56
+ it "populates" do
57
+ expect(destinations).to_not(be_nil)
58
+ expect(destinations).to_not(be_empty)
59
+ end
60
+
61
+ it "has correct data" do
62
+ expect(destinations.count).to(eq(1))
63
+ destination = destinations.first
64
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
65
+ expect(destination.id).to(eq(name))
66
+ expect(destination.host).to(eq(host))
67
+ expect(destination.port).to(eq(port))
68
+ end
69
+ end
70
+
71
+ context "without id matching" do
72
+ let(:destinations) { MiniDisc::Discover.services(:http) }
73
+
74
+ it "populates" do
75
+ expect(destinations).to_not(be_nil)
76
+ expect(destinations).to_not(be_empty)
77
+ end
78
+
79
+ it "has correct data" do
80
+ expect(destinations.count).to(eq(1))
81
+ destination = destinations.first
82
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
83
+ expect(destination.id).to(eq(name))
84
+ expect(destination.host).to(eq(host))
85
+ expect(destination.port).to(eq(port))
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "#to_h" do
92
+ let(:id) { "minidisc-test" }
93
+ let(:host) { "test.local." }
94
+ let(:port) { 8000 }
95
+ let(:destination) do
96
+ MiniDisc::Discover::Service.new(id, host, port: port)
97
+ end
98
+ let(:hash) { destination.to_h }
99
+
100
+ it "converts to hash" do
101
+ expect(hash).to_not(be_nil)
102
+ expect(hash).to(be_kind_of(Hash))
103
+ expect(hash[:id]).to_not(be_nil)
104
+ expect(hash[:host]).to_not(be_nil)
105
+ expect(hash[:port]).to_not(be_nil)
106
+ end
107
+
108
+ it "matches object" do
109
+ expect(hash[:id]).to(eq(destination.id))
110
+ expect(hash[:host]).to(eq(destination.host))
111
+ expect(hash[:port]).to(eq(destination.port))
112
+ end
113
+
114
+ it "has correct data" do
115
+ expect(hash[:id]).to(eq(id))
116
+ expect(hash[:host]).to(eq(host))
117
+ expect(hash[:port]).to(eq(port))
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.join("..", "lib"))
2
+
3
+ require "rspec"
4
+ require "minidisc"
@@ -0,0 +1,111 @@
1
+ require "helper"
2
+
3
+ describe MiniDisc::Network do
4
+ describe ".add" do
5
+ let(:port) { 4040 }
6
+ let(:service_type) { :http }
7
+
8
+ describe "#register" do
9
+ let(:args) do
10
+ [kind_of(String), "_http._tcp", nil, port]
11
+ end
12
+
13
+ before(:each) do
14
+ expect(DNSSD).to(receive(:register).with(*args).and_return(true))
15
+ end
16
+
17
+ it "registers" do
18
+ service = MiniDisc::Network.add(service_type, port)
19
+ expect(service.registered?).to(be(true))
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ describe ".find_all" do
26
+
27
+ context "from override file" do
28
+ let(:host) { "something.local." }
29
+ let(:port) { "80" }
30
+ let(:config_service) do
31
+ {
32
+ host: host,
33
+ port: port
34
+ }
35
+ end
36
+
37
+ let(:destinations) do
38
+ MiniDisc::Network.find_all(:http, override: [config_service])
39
+ end
40
+
41
+ it "populates" do
42
+ expect(destinations).to_not(be_nil)
43
+ expect(destinations).to_not(be_empty)
44
+ end
45
+
46
+ it "has correct data" do
47
+ expect(destinations.count).to(eq(1))
48
+ destination = destinations.first
49
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
50
+ expect(destination.id).to(eq("override_1"))
51
+ expect(destination.host).to(eq(host))
52
+ expect(destination.port).to(eq(port))
53
+ end
54
+ end
55
+
56
+ context "from discovery" do
57
+ let(:name) { "minidisc-test_service" }
58
+ let(:host) { "testservice.local." }
59
+ let(:port) { "8080" }
60
+ let(:service) do
61
+ {
62
+ name: name,
63
+ target: host,
64
+ port: port
65
+ }
66
+ end
67
+
68
+ before(:each) do
69
+ expect(MiniDisc::Discover::Network).to(receive(:services_with_timeout).at_least(:once).and_return([service]))
70
+ end
71
+
72
+ context "with id matching" do
73
+ let(:destinations) do
74
+ MiniDisc::Network.find_all(:http, match: /minidisc\-.+/)
75
+ end
76
+
77
+ it "populates" do
78
+ expect(destinations).to_not(be_nil)
79
+ expect(destinations).to_not(be_empty)
80
+ end
81
+
82
+ it "has correct data" do
83
+ expect(destinations.count).to(eq(1))
84
+ destination = destinations.first
85
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
86
+ expect(destination.id).to(eq(name))
87
+ expect(destination.host).to(eq(host))
88
+ expect(destination.port).to(eq(port))
89
+ end
90
+ end
91
+
92
+ context "without id matching" do
93
+ let(:destinations) { MiniDisc::Discover.services(:http) }
94
+
95
+ it "populates" do
96
+ expect(destinations).to_not(be_nil)
97
+ expect(destinations).to_not(be_empty)
98
+ end
99
+
100
+ it "has correct data" do
101
+ expect(destinations.count).to(eq(1))
102
+ destination = destinations.first
103
+ expect(destination).to(be_kind_of(MiniDisc::Discover::Service))
104
+ expect(destination.id).to(eq(name))
105
+ expect(destination.host).to(eq(host))
106
+ expect(destination.port).to(eq(port))
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,84 @@
1
+ require "helper"
2
+
3
+ describe MiniDisc::Registry do
4
+ let(:id) { "test-1"}
5
+ let(:port) { 4040 }
6
+ let(:service_type) { :http }
7
+
8
+ describe ".add" do
9
+ describe "with id specified" do
10
+ let(:discovery) { MiniDisc::Registry.add(service_type, port, id: id) }
11
+
12
+ it "populates" do
13
+ expect(discovery.id).to_not(be_nil)
14
+ expect(discovery.port).to_not(be_nil)
15
+ end
16
+
17
+ it "has correct values" do
18
+ expect(discovery.id).to(eq(id))
19
+ expect(discovery.port).to(eq(port))
20
+ end
21
+ end
22
+
23
+ describe "with id not specified" do
24
+ let(:discovery) { MiniDisc::Registry.add(service_type, port) }
25
+
26
+ it "populates" do
27
+ expect(discovery.id).to_not(be_nil)
28
+ expect(discovery.port).to_not(be_nil)
29
+ end
30
+
31
+ it "has correct values" do
32
+ expect(discovery.id).to(include(discovery.object_id.to_s))
33
+ expect(discovery.port).to(eq(port))
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "Service" do
39
+ describe "#initialize" do
40
+ describe "with id specified" do
41
+ let(:discovery) { MiniDisc::Registry::Service.new(service_type, port, id: id) }
42
+
43
+ it "populates" do
44
+ expect(discovery.id).to_not(be_nil)
45
+ expect(discovery.port).to_not(be_nil)
46
+ end
47
+
48
+ it "has correct values" do
49
+ expect(discovery.id).to(eq(id))
50
+ expect(discovery.port).to(eq(port))
51
+ end
52
+ end
53
+
54
+ describe "with id not specified" do
55
+ let(:discovery) { MiniDisc::Registry::Service.new(service_type, port) }
56
+
57
+ it "populates" do
58
+ expect(discovery.id).to_not(be_nil)
59
+ expect(discovery.port).to_not(be_nil)
60
+ end
61
+
62
+ it "has correct values" do
63
+ expect(discovery.id).to(include(discovery.object_id.to_s))
64
+ expect(discovery.port).to(eq(port))
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#register" do
70
+ let(:discovery) { MiniDisc::Registry::Service.new(service_type, port) }
71
+ let(:args) do
72
+ [discovery.id, "_http._tcp", nil, port]
73
+ end
74
+
75
+ before(:each) do
76
+ expect(DNSSD).to(receive(:register).with(*args).and_return(true))
77
+ end
78
+
79
+ it "registers and returns true" do
80
+ expect(discovery.register).to(be(true))
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ require "helper"
2
+
3
+ describe MiniDisc::ServiceType do
4
+ describe "#sym_to_dnnsd_string" do
5
+ context "without protocol" do
6
+ let(:input) { :http }
7
+ let(:result) { MiniDisc::ServiceType.sym_to_dnnsd_string(:http) }
8
+
9
+ it "has the correct service type part and tcp as defult protocol part" do
10
+ expect(result).to(eq("_http._tcp"))
11
+ end
12
+
13
+ end
14
+
15
+ context "with protocol" do
16
+ let(:input) { :example }
17
+ let(:protocol) { :udp }
18
+ let(:result) { MiniDisc::ServiceType.sym_to_dnnsd_string(input, protocol: protocol) }
19
+
20
+ it "reflects when udp is passed in" do
21
+ expect(result).to(eq("_example._udp"))
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minidisc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Ari Russo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dnssd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '10.4'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 10.4.2
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '10.4'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 10.4.2
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 3.5.0
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.5'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 3.5.0
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '3.5'
73
+ description: Mini service discovery
74
+ email:
75
+ - ari.russo@gmail.com
76
+ executables: []
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - LICENSE
81
+ - README.md
82
+ - lib/minidisc.rb
83
+ - lib/minidisc/discover.rb
84
+ - lib/minidisc/discover/network.rb
85
+ - lib/minidisc/network.rb
86
+ - lib/minidisc/registry.rb
87
+ - lib/minidisc/service_type.rb
88
+ - spec/discover/network_spec.rb
89
+ - spec/discover_spec.rb
90
+ - spec/helper.rb
91
+ - spec/network_spec.rb
92
+ - spec/registry_spec.rb
93
+ - spec/service_type_spec.rb
94
+ homepage: http://github.com/arirusso/minidisc
95
+ licenses:
96
+ - Apache-2.0
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: 1.3.6
112
+ requirements: []
113
+ rubygems_version: 3.0.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Mini service discovery
117
+ test_files: []