noah 0.0.5-jruby → 0.1-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/.gemtest +0 -0
  2. data/.gitignore +10 -0
  3. data/LICENSE +201 -0
  4. data/README.md +68 -212
  5. data/Rakefile +65 -41
  6. data/TODO.md +65 -0
  7. data/bin/noah +2 -1
  8. data/bin/noah-watcher.rb +103 -0
  9. data/config.ru +6 -3
  10. data/config/warble.rb +18 -0
  11. data/examples/README.md +116 -0
  12. data/examples/cluster.ru +2 -0
  13. data/examples/custom-watcher.rb +10 -0
  14. data/examples/httpclient-server.rb +7 -0
  15. data/examples/httpclient.rb +12 -0
  16. data/examples/httpclient2.rb +28 -0
  17. data/examples/js/FABridge.js +1452 -0
  18. data/examples/js/WebSocketMain.swf +830 -0
  19. data/examples/js/swfobject.js +851 -0
  20. data/examples/js/web_socket.js +312 -0
  21. data/examples/logger.rb +11 -0
  22. data/examples/reconfiguring-sinatra-watcher.rb +11 -0
  23. data/examples/reconfiguring-sinatra.rb +33 -0
  24. data/examples/simple-post.rb +17 -0
  25. data/examples/websocket.html +24 -0
  26. data/examples/websocket.rb +41 -0
  27. data/lib/noah.rb +6 -8
  28. data/lib/noah/app.rb +20 -268
  29. data/lib/noah/application_routes.rb +70 -0
  30. data/lib/noah/ark.rb +0 -0
  31. data/lib/noah/configuration_routes.rb +81 -0
  32. data/lib/noah/custom_watcher.rb +79 -0
  33. data/lib/noah/ephemeral_routes.rb +47 -0
  34. data/lib/noah/helpers.rb +37 -14
  35. data/lib/noah/host_routes.rb +69 -0
  36. data/lib/noah/models.rb +86 -5
  37. data/lib/noah/models/applications.rb +41 -0
  38. data/lib/noah/models/configurations.rb +49 -0
  39. data/lib/noah/models/ephemerals.rb +54 -0
  40. data/lib/noah/models/hosts.rb +56 -0
  41. data/lib/noah/models/services.rb +54 -0
  42. data/lib/noah/models/watchers.rb +62 -0
  43. data/lib/noah/passthrough.rb +11 -0
  44. data/lib/noah/service_routes.rb +71 -0
  45. data/lib/noah/validations.rb +1 -0
  46. data/lib/noah/validations/watcher_validations.rb +48 -0
  47. data/lib/noah/version.rb +1 -1
  48. data/lib/noah/watcher_routes.rb +45 -0
  49. data/noah.gemspec +25 -17
  50. data/spec/application_spec.rb +30 -30
  51. data/spec/configuration_spec.rb +78 -14
  52. data/spec/ephemeral_spec.rb +59 -0
  53. data/spec/host_spec.rb +21 -21
  54. data/spec/noahapp_application_spec.rb +6 -6
  55. data/spec/noahapp_configuration_spec.rb +5 -5
  56. data/spec/noahapp_ephemeral_spec.rb +115 -0
  57. data/spec/noahapp_host_spec.rb +3 -3
  58. data/spec/noahapp_service_spec.rb +10 -10
  59. data/spec/noahapp_watcher_spec.rb +123 -0
  60. data/spec/service_spec.rb +27 -27
  61. data/spec/spec_helper.rb +13 -22
  62. data/spec/support/db/.keep +0 -0
  63. data/spec/support/test-redis.conf +8 -0
  64. data/spec/watcher_spec.rb +62 -0
  65. data/views/index.haml +21 -15
  66. metadata +189 -146
  67. data/Gemfile.lock +0 -83
  68. data/doc/coverage/index.html +0 -138
  69. data/doc/coverage/jquery-1.3.2.min.js +0 -19
  70. data/doc/coverage/jquery.tablesorter.min.js +0 -15
  71. data/doc/coverage/lib-helpers_rb.html +0 -393
  72. data/doc/coverage/lib-models_rb.html +0 -1449
  73. data/doc/coverage/noah_rb.html +0 -2019
  74. data/doc/coverage/print.css +0 -12
  75. data/doc/coverage/rcov.js +0 -42
  76. data/doc/coverage/screen.css +0 -270
  77. data/lib/noah/applications.rb +0 -46
  78. data/lib/noah/configurations.rb +0 -49
  79. data/lib/noah/hosts.rb +0 -54
  80. data/lib/noah/services.rb +0 -57
  81. data/lib/noah/watchers.rb +0 -18
@@ -0,0 +1,54 @@
1
+ module Noah
2
+ class Ephemeral < Model
3
+
4
+ attribute :path
5
+ attribute :data
6
+ attribute :lifetime
7
+
8
+ index :path
9
+
10
+ def validate
11
+ super
12
+ assert_present :path
13
+ assert_unique :path
14
+ end
15
+
16
+ def name
17
+ @name = path
18
+ end
19
+
20
+ def to_hash
21
+ h = {:path => path, :data => data, :created_at => created_at, :updated_at => updated_at}
22
+ super.merge(h)
23
+ end
24
+
25
+ class << self
26
+ def find_or_create(opts = {})
27
+ begin
28
+ path, data = opts[:path], opts[:data]
29
+ find(:path => path).first.nil? ? (eph = new(:path => path)) : (eph = find(:path => path).first)
30
+ eph.data = data
31
+ if eph.valid?
32
+ eph.save
33
+ end
34
+ eph
35
+ rescue Exception => e
36
+ e.message
37
+ end
38
+ end
39
+ end
40
+
41
+ protected
42
+ def save_hook
43
+ # called after any create,update,delete
44
+ # logic needed to expire any orphaned ephemerals
45
+ end
46
+
47
+ private
48
+ def path_protected?(path_part)
49
+ # Check for protected paths in ephemeral nodes
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,56 @@
1
+ require File.join(File.dirname(__FILE__), 'services')
2
+ module Noah
3
+ class Host < Model
4
+ # Host model
5
+ # @return {Host} a {Host} object
6
+
7
+ attribute :name
8
+ attribute :status
9
+ collection :services, Service
10
+
11
+ index :name
12
+ index :status
13
+
14
+ def validate
15
+ super
16
+ assert_present :name
17
+ assert_present :status
18
+ assert_unique :name
19
+ assert_member :status, ["up","down","pending"]
20
+ end
21
+
22
+ # @return [Hash] A hash representation of a {Host}
23
+ def to_hash
24
+ arr = []
25
+ services.sort.each {|s| arr << s.to_hash}
26
+ h = {:name => name, :status => status, :created_at => created_at, :updated_at => updated_at, :services => arr}
27
+ super.merge(h)
28
+ end
29
+
30
+ class << self
31
+ def find_or_create(opts = {})
32
+ begin
33
+ # exclude requested status from lookup
34
+ h = find(opts.reject{|key,value| key == :status}).first
35
+ host = h.nil? ? create(opts) : h
36
+ host.status = opts[:status]
37
+ if host.valid?
38
+ host.save
39
+ end
40
+ host
41
+ rescue Exception => e
42
+ e.message
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ class Hosts
50
+ # @param [Hash] optional filters for results
51
+ # @return [Array] Array of {Host} objects
52
+ def self.all(options = {})
53
+ options.empty? ? Noah::Host.all.sort : Noah::Host.find(options).sort
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,54 @@
1
+ module Noah
2
+
3
+ class Service < Model
4
+
5
+ attribute :name
6
+ attribute :status
7
+ reference :host, Host
8
+
9
+ index :name
10
+ index :status
11
+
12
+ def validate
13
+ super
14
+ assert_present :name
15
+ assert_present :status
16
+ assert_present :host_id
17
+ assert_unique [:name, :host_id]
18
+ assert_member :status, ["up", "down", "pending"]
19
+ end
20
+
21
+ def to_hash
22
+ Host[host_id].nil? ? host_name=nil : host_name=Host[host_id].name
23
+ super.merge(:name => name, :status => status, :updated_at => updated_at, :host => host_name)
24
+ end
25
+
26
+ class << self
27
+ def find_or_create(opts = {})
28
+ begin
29
+ # convert passed host object to host_id if passed
30
+ if opts.has_key?(:host)
31
+ opts.merge!({:host_id => opts[:host].id})
32
+ opts.reject!{|key, value| key == :host}
33
+ end
34
+ # exclude requested status from lookup
35
+ s = find(opts.reject{|key,value| key == :status}).first
36
+ service = s.nil? ? create(opts) : s
37
+ service.status = opts[:status]
38
+ if service.valid?
39
+ service.save
40
+ end
41
+ service
42
+ rescue Exception => e
43
+ e.message
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ class Services
50
+ def self.all(options = {})
51
+ options.empty? ? Service.all.sort : Service.find(options).sort
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,62 @@
1
+ require 'digest/sha1'
2
+ module Noah
3
+ class Watcher < Model #NYI
4
+ # Don't trust anything in here yet
5
+ # I'm still trying a few things
6
+ include WatcherValidations
7
+
8
+ attribute :pattern
9
+ attribute :endpoint
10
+ attribute :name
11
+
12
+ index :pattern
13
+ index :endpoint
14
+
15
+ def validate
16
+ super
17
+ assert_present :endpoint
18
+ assert_present :pattern
19
+ assert_unique [:endpoint, :pattern]
20
+ assert_not_superset
21
+ assert_not_subset
22
+ end
23
+
24
+ def name
25
+ @name = Base64.encode64("#{pattern}|#{endpoint}").gsub("\n","")
26
+ end
27
+
28
+ def to_hash
29
+ h = {:pattern => pattern, :name => name, :endpoint => endpoint, :created_at => created_at, :updated_at => updated_at}
30
+ super.merge(h)
31
+ end
32
+
33
+ class << self
34
+ def find_by_name(name)
35
+ pattern, endpoint = Base64.decode64(name).split('|')
36
+ find(:pattern => pattern, :endpoint => endpoint).first
37
+ end
38
+
39
+ def watch_list
40
+ arr = []
41
+ watches = self.all.sort_by(:pattern)
42
+ watches.each {|w| arr << w.name}
43
+ arr
44
+ end
45
+ end
46
+
47
+ private
48
+ # Not sure about these next two.
49
+ # Could get around patterns changing due to namespace changes
50
+ def path_to_pattern
51
+ end
52
+
53
+ def pattern_to_path
54
+ end
55
+ end
56
+
57
+ class Watchers
58
+ def self.all(options = {})
59
+ options.empty? ? Watcher.all.sort : Watcher.find(options).sort
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ module Noah
2
+ module Passthrough
3
+ def passthrough(*methods)
4
+ methods.each do |method|
5
+ raise ArgumentError if ! method.is_a?(Symbol)
6
+ meth = method.to_s
7
+ self.class_eval("def #{meth}(*args); self.class.#{meth}(*args); end")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,71 @@
1
+ class Noah::App
2
+ # Service URIs
3
+
4
+ # get named {Service} for named {Host}
5
+ get '/s/:servicename/:hostname/?' do |servicename, hostname|
6
+ hs = host_service(hostname, servicename)
7
+ if hs.nil?
8
+ halt 404
9
+ else
10
+ hs.to_json
11
+ end
12
+ end
13
+
14
+ get '/s/:servicename/?' do |servicename|
15
+ s = services(:name => servicename)
16
+ s.map {|x| x.to_hash}
17
+ if s.empty?
18
+ halt 404
19
+ else
20
+ s.to_json
21
+ end
22
+ end
23
+
24
+ get '/s/?' do
25
+ if services.empty?
26
+ halt 404
27
+ else
28
+ services.map {|s| s.to_hash}
29
+ services.to_json
30
+ end
31
+ end
32
+
33
+ put '/s/:servicename/watch' do |servicename|
34
+ required_params = ["endpoint"]
35
+ data = JSON.parse(request.body.read)
36
+ (data.keys.sort == required_params.sort) ? (s = Noah::Service.find(:name => servicename).first) : (raise "Missing Parameters")
37
+ s.nil? ? (halt 404) : (w = s.watch!(:endpoint => data['endpoint']))
38
+ w.to_json
39
+ end
40
+
41
+ put '/s/:servicename/?' do |servicename|
42
+ required_params = ["status", "host", "name"]
43
+ data = JSON.parse(request.body.read)
44
+ if data.keys.sort == required_params.sort
45
+ h = Noah::Host.find(:name => data['host']).first || (raise "Invalid Host")
46
+ service = Noah::Service.find_or_create(:name => servicename, :status => data['status'], :host => h)
47
+ if service.valid?
48
+ action = service.is_new? ? "create" : "update"
49
+ service.save
50
+ r = {"action" => action, "result" => "success", "id" => service.id, "host" => h.name, "name" => service.name}
51
+ r.to_json
52
+ else
53
+ raise "#{format_errors(service)}"
54
+ end
55
+ else
56
+ raise "Missing Parameters"
57
+ end
58
+ end
59
+
60
+ delete '/s/:servicename/:hostname/?' do |servicename, hostname|
61
+ host = Noah::Host.find(:name => hostname).first || (halt 404)
62
+ service = Noah::Service.find(:name => servicename, :host_id => host.id).first || (halt 404)
63
+ if host && service
64
+ service.delete
65
+ r = {"action" => "delete", "result" => "success", "id" => service.id, "host" => host.name, "service" => servicename}
66
+ r.to_json
67
+ else
68
+ halt 404
69
+ end
70
+ end
71
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'validations','watcher_validations')
@@ -0,0 +1,48 @@
1
+ module Noah
2
+ module WatcherValidations
3
+
4
+ def assert_not_subset(error = [:pattern, :already_provided])
5
+ self.instance_of?(Noah::Watcher) ? (assert endpoint_covered?, error) : (assert false, "Validation not applicable")
6
+ end
7
+
8
+ def assert_not_superset(error = [:pattern, :replaces_existing])
9
+ self.instance_of?(Noah::Watcher) ? (assert endpoint_overrides?, error) : (assert false, "Validation not applicable")
10
+ end
11
+
12
+ def assert_valid_watch(error = [:pattern, :invalid_format])
13
+ self.instance_of?(Noah::Watcher) ? (assert pattern_valid?, error) : (assert false, "Validation not applicable")
14
+ end
15
+
16
+ private
17
+ def endpoint_covered?
18
+ watches = Watcher.all.find(:endpoint => self.endpoint).sort
19
+ watches.each do |w|
20
+ if (w.pattern.size < self.pattern.size) && self.pattern.match(/^#{w.pattern}/)
21
+ return false
22
+ end
23
+ end
24
+ rescue ArgumentError
25
+ return false
26
+ end
27
+
28
+ def endpoint_overrides?
29
+ watches = Watcher.all.find(:endpoint => self.endpoint).sort
30
+ watches.each do |w|
31
+ if (w.pattern.size > self.pattern.size) && w.pattern.match(/^#{self.pattern}/)
32
+ return false
33
+ end
34
+ end
35
+ rescue ArgumentError
36
+ return false
37
+ end
38
+
39
+ def pattern_valid?
40
+ unless self.pattern.match(/^\/\/noah\/.*\/$/)
41
+ return false
42
+ end
43
+ rescue ArgumentError
44
+ return false
45
+ end
46
+
47
+ end
48
+ end
data/lib/noah/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1"
3
3
  end
@@ -0,0 +1,45 @@
1
+ class Noah::App
2
+
3
+ get '/w/:name' do |name|
4
+ w = Noah::Watcher.find_by_name(name)
5
+ w.nil? ? (halt 404) : w.to_json
6
+ end
7
+
8
+ get '/w/?' do
9
+ w = Noah::Watcher.all.sort_by(:pattern)
10
+ if w.size == 0
11
+ halt 404
12
+ else
13
+ w.to_json
14
+ end
15
+ end
16
+
17
+ put '/w/?' do
18
+ required_params = %w[endpoint pattern]
19
+ data = JSON.parse(request.body.read)
20
+ (data.keys.sort == required_params.sort) ? (pattern, endpoint = data['pattern'],data['endpoint']) : (raise "Missing Parameters")
21
+ w = Noah::Watcher.create(:pattern => pattern, :endpoint => endpoint)
22
+ if w.valid?
23
+ w.save
24
+ r = {"action" => "create", "result" => "success"}.merge(w.to_hash)
25
+ r.to_json
26
+ else
27
+ raise "#{format_errors(w)}"
28
+ end
29
+ end
30
+
31
+ delete '/w/?' do
32
+ required_params = %w[endpoint pattern]
33
+ data = JSON.parse(request.body.read)
34
+ (data.keys.sort == required_params.sort) ? (pattern, endpoint = data['pattern'],data['endpoint']) : (raise "Missing Parameters")
35
+ w = Noah::Watcher.find(:pattern => pattern, :endpoint => endpoint).first
36
+ if w.nil?
37
+ halt 404
38
+ else
39
+ w.delete
40
+ r = {"result" => "success", "action" => "delete"}.merge(w.to_hash)
41
+ r.to_json
42
+ end
43
+ end
44
+
45
+ end
data/noah.gemspec CHANGED
@@ -5,8 +5,9 @@ require "noah/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "noah"
7
7
  s.version = Noah::VERSION
8
- s.platform = RUBY_ENGINE
9
- s.authors = ["lusis"]
8
+ #s.platform = Gem::Platform::RUBY
9
+ s.platform = "jruby"
10
+ s.authors = ["John E. Vincent"]
10
11
  s.email = ["lusis.org+rubygems.org@gmail.com"]
11
12
  s.homepage = "https://github.com/lusis/noah"
12
13
  s.summary = %q{Application registry based on Apache Zookeeper}
@@ -19,26 +20,33 @@ Gem::Specification.new do |s|
19
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
21
  s.require_paths = ["lib"]
21
22
 
22
- s.add_dependency("rake", ["= 0.8.7"])
23
+ s.add_dependency("eventmachine", ["1.0.0.beta.3"])
24
+ s.add_dependency("em-http-request", ["1.0.0.beta.3"])
25
+ s.add_dependency("redis", ["= 2.1.1"])
26
+ s.add_dependency("nest", ["= 1.1.0"])
27
+ s.add_dependency("rack", ["= 1.2.1"])
28
+ s.add_dependency("tilt", ["= 1.2.2"])
23
29
  s.add_dependency("sinatra", ["= 1.1.2"])
24
- s.add_dependency("sinatra-namespace", ["0.6.1"])
25
30
  s.add_dependency("ohm", ["= 0.1.3"])
26
- s.add_dependency("ohm-contrib", ["= 0.1.0"])
31
+ s.add_dependency("ohm-contrib", ["= 0.1.1"])
27
32
  s.add_dependency("haml", ["= 3.0.25"])
28
33
  s.add_dependency("vegas", ["= 0.1.8"])
29
- s.add_dependency("yajl-ruby", ["= 0.7.9"]) if s.platform.to_s == 'ruby'
30
- s.add_dependency("jruby-json", ["= 1.5.0"]) if s.platform.to_s == 'jruby'
31
- s.add_dependency("thin", ["= 1.2.7"]) if s.platform.to_s == 'ruby'
32
- s.add_dependency("json-jruby", ["= 1.4.6"]) if s.platform.to_s == 'jruby'
33
- s.add_dependency("jruby-openssl", ["= 0.7.3"]) if s.platform.to_s == 'jruby'
34
34
 
35
+
36
+ if RUBY_PLATFORM =~ /java/
37
+ s.add_dependency("jruby-openssl")
38
+ s.add_dependency("json")
39
+ s.add_development_dependency("warbler", ["= 1.2.1"])
40
+ else
41
+ s.add_dependency("hiredis", ["= 0.3.1"])
42
+ s.add_dependency("yajl-ruby")
43
+ s.add_dependency("SystemTimer") if RUBY_VERSION =~ /1.8/
44
+ s.add_dependency("thin")
45
+ end
46
+
47
+ s.add_development_dependency("diff-lcs", ["= 1.1.2"])
35
48
  s.add_development_dependency("sinatra-reloader", ["= 0.5.0"])
36
- s.add_development_dependency("rspec", ["= 2.4.0"])
37
- s.add_development_dependency("rcov", ["= 0.9.9"]) if s.platform.to_s == 'ruby'
49
+ s.add_development_dependency("rspec", ["~> 2.5"])
50
+ s.add_development_dependency("rcov", ["= 0.9.9"])
38
51
  s.add_development_dependency("rack-test", ["= 0.5.7"])
39
- s.add_development_dependency("ZenTest", ["= 4.4.2"])
40
- s.add_development_dependency("autotest", ["= 4.4.6"])
41
- s.add_development_dependency("autotest-growl", ["= 0.2.9"])
42
- s.add_development_dependency("warbler", ["= 1.2.1"]) if s.platform.to_s == 'java'
43
-
44
52
  end