teamd-discover 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 475a9d668c3b134380f379ee0e6e5a29f132d80f
4
+ data.tar.gz: a4cffdd56fdb1feba6117ba4651d28be43e30c2c
5
+ SHA512:
6
+ metadata.gz: b69d8b309f35b19b7e41f5b1bc43f8bb00d394c743d65a84f1e0c1e3ad915b5eac1818c7ab4ac50c12a084ad9ab90fcf0c75802ab3e7de4d1f29e5e939077ef9
7
+ data.tar.gz: 17a1d049a46dc2f2cd896b03b2073b244a0c072d8f51e941b8d767c49b6f2b8bdcaff2a2e277ed7cf64ca072c63ad0460d1799a2b5d4170bc8b36dd97584ce6e
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ teamd-discover
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.2.2
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teamd-discover.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Teamd::Discover
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/teamd/discover`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'teamd-discover'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install teamd-discover
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/teamd-discover/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "teamd/discover"
5
+ require "pry"
6
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "teamd/discover/cli"
5
+ Teamd::Discover::Cli.start
@@ -0,0 +1,26 @@
1
+ require "thor"
2
+ require "teamd/discover"
3
+
4
+ module Teamd
5
+ module Discover
6
+ class Cli < Thor
7
+ def self.peer
8
+ @peer ||= Teamd::Discover::Peer.new
9
+ end
10
+ default_task :node
11
+ desc "node","Discover local cluster data"
12
+ def node
13
+ Cli.peer.serve
14
+ end
15
+ desc "announce","One shot announcement"
16
+ def announce
17
+ Cli.peer.announce
18
+ end
19
+ desc "discover","One shot discovery"
20
+ def discover
21
+ STDERR.write "discovering\n"
22
+ Cli.peer.discover
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ require "ostruct"
2
+
3
+ module Teamd
4
+ module Discover
5
+ class Cluster < OpenStruct
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require "teamd/discover/message/packet"
2
+
3
+ module Teamd
4
+ module Discover
5
+ class Message
6
+ class ClusterAnnouncement < Packet
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require "teamd/discover/message/packet"
2
+
3
+ module Teamd
4
+ module Discover
5
+ class Message
6
+ class DiscoveryRequest < Packet
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require "recursive-open-struct"
2
+ require "securerandom"
3
+ require "json"
4
+
5
+ module Teamd
6
+ module Discover
7
+ class Message
8
+ class Packet < RecursiveOpenStruct
9
+ def initialize params={}
10
+ params[:tid] = Peer.tid
11
+ super params
12
+ end
13
+ def pack
14
+ Message.pack @table
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ require "json"
2
+
3
+ require "teamd/discover/message/discovery_request"
4
+ require "teamd/discover/message/cluster_announcement"
5
+
6
+ module Teamd
7
+ module Discover
8
+ class Message
9
+ class InvalidMessage < Exception; end
10
+
11
+ class << self
12
+ def unpack data
13
+ begin
14
+ build JSON.parse(data)["teamd"]
15
+ rescue
16
+ raise InvalidMessage
17
+ end
18
+ end
19
+ def pack data
20
+ {teamd:data}.to_json
21
+ end
22
+ def build data={}
23
+ return Message::DiscoveryRequest.new data if data["discovery"]
24
+ return Message::ClusterAnnouncement.new data if data["clusters"]
25
+ end
26
+ end
27
+ def is_discovery?
28
+ self.discovery && self
29
+ end
30
+ def is_announcement?
31
+ self.clusters && self
32
+ end
33
+ def pack
34
+ { teamd: @table }.to_json
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ require "socket"
2
+ require "securerandom"
3
+
4
+ module Teamd
5
+ module Discover
6
+ class Peer
7
+ class << self
8
+ def tid
9
+ @tid ||= SecureRandom.hex(8)
10
+ end
11
+ end
12
+ def initialize
13
+ @transport ||= Teamd::Discover::Transport.new
14
+ @registry ||= Teamd::Discover::Registry.new
15
+ end
16
+ def serve
17
+ keep_alive
18
+ loop do
19
+ message = @transport.receive
20
+ process_discovery if message.is_a? Message::DiscoveryRequest
21
+ process_announcement if message.is_a? Message::ClusterAnnouncement
22
+ end
23
+ end
24
+ def discover timeout=15
25
+ wait timeout
26
+ Thread.new do
27
+ loop do
28
+ message = @transport.receive
29
+ puts message.inspect
30
+ end
31
+ end
32
+ i,_=IO.pipe
33
+ Thread.new { @transport.transmit Message.build("discovery" => true) }
34
+ IO.select([i])
35
+ end
36
+ def announce
37
+ @transport.transmit @registry.pack
38
+ end
39
+ private
40
+ def keep_alive
41
+ Thread.new{i,_=IO.pipe;IO.select([i])}
42
+ end
43
+ def wait timeout
44
+ Thread.new{sleep(timeout); exit(1);}
45
+ end
46
+ def process_discovery
47
+ packet = Message::ClusterAnnouncement.new clusters: @registry.pack
48
+ puts "Announce #{packet}"
49
+ @transport.transmit packet
50
+ end
51
+ def process_announcement
52
+ puts "learning new cluster"
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,24 @@
1
+ require "json"
2
+ require "toml"
3
+ require "ostruct"
4
+
5
+ module Teamd
6
+ module Discover
7
+ class Protocol
8
+ class << self
9
+ def port
10
+ 53235
11
+ end
12
+ end
13
+ def unpack data
14
+ Message.unpack(data)
15
+ end
16
+ def publish
17
+ data
18
+ end
19
+ def discovery
20
+ Message.new(discovery: true)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ module Teamd
2
+ module Discover
3
+ class Registry
4
+ def initialize
5
+ @clusters ||= []
6
+ add_cluster_from_environment
7
+ add_clusters_from_files "/etc/teamd/config*"
8
+ add_clusters_from_files "/run/teamd/config"
9
+ end
10
+ def add cluster
11
+ @clusters << cluster unless find cluster
12
+ end
13
+ def remove matching_property
14
+ @clusters.delete_if do |cluster|
15
+ [cluster.name,cluster.token].include? matching_property
16
+ end
17
+ end
18
+ def find c
19
+ @clusters.each do |d|
20
+ return true if d.name == c.name
21
+ return true if d.token == c.token
22
+ end
23
+ false
24
+ end
25
+ def pack
26
+ @clusters.collect do |cluster|
27
+ [cluster.name,cluster.token]
28
+ end.to_h
29
+ end
30
+ private
31
+ def add_cluster_from_environment
32
+ uri = URI ENV['ETCD_DISCOVERY'] rescue nil
33
+ token = uri.path.split("/").last rescue nil
34
+ domain = Socket.gethostname.split(".",2).last rescue ""
35
+ add Cluster.new(name: domain, token: token) if token && domain
36
+ end
37
+ def add_clusters_from_files pattern
38
+ Dir.glob(pattern).each do |file|
39
+ raw_data = File.read(file)
40
+ data ||= Toml.read raw_data rescue nil
41
+ data ||= JSON.read raw_data rescue nil
42
+ data ||= YAML.read raw_data rescue nil
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,64 @@
1
+ require "socket"
2
+
3
+ module Teamd
4
+ module Discover
5
+ class Transport
6
+ def initialize
7
+ BasicSocket.do_not_reverse_lookup = true
8
+ @protocol ||= Protocol.new
9
+ end
10
+ def transmit message
11
+ into_network.push [message.pack,all]
12
+ end
13
+ def receive
14
+ loop do
15
+ data,_ = from_network.pop
16
+ packet = @protocol.unpack data
17
+ next if packet.tid == Peer.tid
18
+ return packet
19
+ end
20
+ end
21
+ def into_network
22
+ start_sender
23
+ @into_network ||= Queue.new
24
+ end
25
+ def from_network
26
+ start_listener
27
+ @from_network ||= Queue.new
28
+ end
29
+ private
30
+ def start_listener
31
+ @listener ||= Thread.new do
32
+ socket = UDPSocket.new
33
+ socket.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
34
+ socket.bind(any,port)
35
+ loop do
36
+ from_network.push socket.recvfrom(mtu)
37
+ end
38
+ end
39
+ end
40
+ def start_sender
41
+ @sender ||= Thread.new do
42
+ socket = UDPSocket.new
43
+ socket.setsockopt Socket::SOL_SOCKET,Socket::SO_BROADCAST,true
44
+ loop do
45
+ data,addr = into_network.pop
46
+ socket.send data,0,addr,port
47
+ end
48
+ end
49
+ end
50
+ def any
51
+ '0.0.0.0'
52
+ end
53
+ def all
54
+ '<broadcast>'
55
+ end
56
+ def mtu
57
+ 1500
58
+ end
59
+ def port
60
+ Teamd::Discover::Protocol.port
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ module Teamd
2
+ module Discover
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require "teamd/discover/version"
2
+
3
+ require "teamd/discover/cluster"
4
+ require "teamd/discover/message"
5
+ require "teamd/discover/peer"
6
+ require "teamd/discover/protocol"
7
+ require "teamd/discover/registry"
8
+ require "teamd/discover/transport"
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'teamd/discover/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "teamd-discover"
8
+ spec.version = Teamd::Discover::VERSION
9
+ spec.authors = ["Mathias Kaufmann"]
10
+ spec.email = ["me@stei.gr"]
11
+
12
+ spec.summary = %q{Teamd Cluster Discover Tool}
13
+ spec.description = %q{Teamd Cluster Discover Tool}
14
+ spec.homepage = "https://teamd.stei.gr/discover"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "bundler", "~> 1.9"
22
+ spec.add_dependency "thor"
23
+ spec.add_dependency "toml-rb"
24
+ spec.add_dependency "recursive-open-struct"
25
+
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "pry"
28
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: teamd-discover
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mathias Kaufmann
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-26 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.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: toml-rb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: recursive-open-struct
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Teamd Cluster Discover Tool
98
+ email:
99
+ - me@stei.gr
100
+ executables:
101
+ - teamd-discover
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".ruby-gemset"
107
+ - ".ruby-version"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - README.md
111
+ - Rakefile
112
+ - bin/console
113
+ - bin/setup
114
+ - exe/teamd-discover
115
+ - lib/teamd/discover.rb
116
+ - lib/teamd/discover/cli.rb
117
+ - lib/teamd/discover/cluster.rb
118
+ - lib/teamd/discover/message.rb
119
+ - lib/teamd/discover/message/cluster_announcement.rb
120
+ - lib/teamd/discover/message/discovery_request.rb
121
+ - lib/teamd/discover/message/packet.rb
122
+ - lib/teamd/discover/peer.rb
123
+ - lib/teamd/discover/protocol.rb
124
+ - lib/teamd/discover/registry.rb
125
+ - lib/teamd/discover/transport.rb
126
+ - lib/teamd/discover/version.rb
127
+ - teamd-discover.gemspec
128
+ homepage: https://teamd.stei.gr/discover
129
+ licenses: []
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.4.6
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Teamd Cluster Discover Tool
151
+ test_files: []