etcd-discovery 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f181a1f205a862c7cd79ab91c0c57fce2d783224
4
+ data.tar.gz: 9b9e09314de9574c470be1d642e1e0dafd32c16f
5
+ SHA512:
6
+ metadata.gz: 7b4582670d24dabcdd52a1cc928247dae9588796a8eb43e7f3635cd242b4365bd877e9d903f818a94009cb0d23be3844a3cde6c938ccbb423f572306a3e13e0d
7
+ data.tar.gz: e21168f6a1c61168cc4e9ac45ee6ad6828571ba1ffc1bad42afc710434b1561f3228910a93f78f1dc46a35e083cd4f2ac73a73d1cf3fd8baac540c54985221ea
@@ -0,0 +1,31 @@
1
+ ## Require files from etcd-discovery
2
+
3
+ require 'etcd'
4
+ require 'json'
5
+
6
+ dir = File.join File.dirname(__FILE__), "etcd-discovery"
7
+ Dir["#{dir}/*.rb"].each do |file|
8
+ require file
9
+ end
10
+
11
+ module EtcdDiscovery
12
+ attr_writer :config
13
+
14
+ def self.config
15
+ @config ||= Config.new
16
+ end
17
+
18
+ def self.configure(&block)
19
+ yield config if block_given?
20
+ config.validate
21
+ end
22
+
23
+ # For a cleaner API
24
+ def self.get(service)
25
+ Service.get(service)
26
+ end
27
+
28
+ def self.register(service, host)
29
+ Thread.new { Service.register(service, host) }
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module EtcdDiscovery
2
+ module Client
3
+ def self.create(config)
4
+ if config.use_ssl
5
+ Etcd.client host: config.host, port: config.port do |config|
6
+ config.use_ssl = true
7
+ config.ca_file = File.expand_path(ENV["ETCD_CACERT"], __FILE__)
8
+ config.ssl_cert = OpenSSL::X509::Certificate.new(File.read(ENV["ETCD_TLS_CERT"]))
9
+ config.ssl_key = OpenSSL::PKey::RSA.new(File.read(ENV["ETCD_TLS_KEY"]))
10
+ end
11
+ else
12
+ Etcd.client host: config.host, port: config.port
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ module EtcdDiscovery
2
+ class InvalidSSLConfig < RuntimeError
3
+ end
4
+
5
+ class Config
6
+ attr_accessor :use_ssl, :cacert, :ssl_key, :ssl_cert
7
+ attr_accessor :register_ttl, :register_renew
8
+ attr_accessor :host, :port
9
+
10
+ def initialize
11
+ @use_ssl = false
12
+ @host = "localhost"
13
+ @port = "4001"
14
+ @register_ttl = 10
15
+ @register_renew = 8
16
+ end
17
+
18
+ def validate
19
+ if use_ssl
20
+ if cacert.nil? or !File.exists? cacert
21
+ raise InvalidSSLConfig, "cacert"
22
+ elsif ssl_key.nil? or !File.exists? ssl_key
23
+ raise InvalidSSLConfig, "ssl_key"
24
+ elsif ssl_cert.nil? or !File.exists? ssl_cert
25
+ raise InvalidSSLConfig, "ssl_cert"
26
+ end
27
+ end
28
+ end
29
+
30
+ def client
31
+ @client ||= Client.create self
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ class Hash
2
+ def capitalize_keys
3
+ new_hash = {}
4
+ self.each do |k,v|
5
+ new_hash[k.to_s.capitalize] = v
6
+ end
7
+ return new_hash
8
+ end
9
+ end
10
+
11
+ module EtcdDiscovery
12
+ class Host
13
+ attr_accessor :hostname, :port, :user, :password
14
+
15
+ def initialize(arg)
16
+ if arg.is_a? Etcd::Node
17
+ params = JSON.parse arg.value
18
+ elsif arg.is_a? Hash
19
+ params = arg.capitalize_keys
20
+ else
21
+ raise TypeError, "requires a Etcd::Node or a Hash, not a #{arg.class}"
22
+ end
23
+ @hostname = params['Name']
24
+ @port = params['Port']
25
+ @user = params['User']
26
+ @password = params['Password']
27
+
28
+ if @hostname.nil? or @hostname.empty?
29
+ @hostname = Socket.gethostname
30
+ end
31
+ end
32
+
33
+ def to_json
34
+ {"Name" => @hostname, "Port" => @port, "User" => @user, "Password" => @password}.to_json
35
+ end
36
+
37
+ def to_uri
38
+ URI("http://#{user}:#{password}@#{hostname}:#{port}")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ module EtcdDiscovery
2
+ class ServiceNotFound < RuntimeError
3
+ end
4
+
5
+ class Service
6
+ def self.get(service)
7
+ raise TypeError, "service should be a String, is a #{service.class}" unless service.is_a? String
8
+
9
+ client = EtcdDiscovery.config.client
10
+ begin
11
+ node = client.get("/services/#{service}", recursive: true)
12
+ rescue Etcd::KeyNotFound
13
+ raise ServiceNotFound, service
14
+ end
15
+ if node.children.length == 0
16
+ raise ServiceNotFound, service
17
+ end
18
+
19
+ hosts = []
20
+ node.children.each do |c|
21
+ hosts << Host.new(c)
22
+ end
23
+ return hosts
24
+ end
25
+
26
+ def self.register(service, host)
27
+ if host.is_a? Hash
28
+ h = Host.new host
29
+ elsif host.is_a? Etcd::Host
30
+ h = host
31
+ else
32
+ raise TypeError, "host should be a Hash or a Etcd::Host, is a #{host.class}"
33
+ end
34
+
35
+ config = EtcdDiscovery.config
36
+ client = config.client
37
+ value = h.to_json
38
+
39
+ while true
40
+ client.set("/services/#{service}/#{h.hostname}", value: value, ttl: config.register_ttl)
41
+ sleep config.register_renew
42
+ end
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etcd-discovery
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Léo Unbekandt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby implementation of a service discovery tool based on etcd
14
+ email: leo.unbekandt@appsdeck.eu
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/etcd-discovery.rb
20
+ - lib/etcd-discovery/client.rb
21
+ - lib/etcd-discovery/config.rb
22
+ - lib/etcd-discovery/host.rb
23
+ - lib/etcd-discovery/service.rb
24
+ homepage: http://github.com/Appsdeck/etcd-discovery-ruby
25
+ licenses:
26
+ - BSD
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.2.2
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Service discovery based on etcd
48
+ test_files: []