noah 0.0.5-jruby → 0.1-jruby

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.
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