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.
- data/.gemtest +0 -0
- data/.gitignore +10 -0
- data/LICENSE +201 -0
- data/README.md +68 -212
- data/Rakefile +65 -41
- data/TODO.md +65 -0
- data/bin/noah +2 -1
- data/bin/noah-watcher.rb +103 -0
- data/config.ru +6 -3
- data/config/warble.rb +18 -0
- data/examples/README.md +116 -0
- data/examples/cluster.ru +2 -0
- data/examples/custom-watcher.rb +10 -0
- data/examples/httpclient-server.rb +7 -0
- data/examples/httpclient.rb +12 -0
- data/examples/httpclient2.rb +28 -0
- data/examples/js/FABridge.js +1452 -0
- data/examples/js/WebSocketMain.swf +830 -0
- data/examples/js/swfobject.js +851 -0
- data/examples/js/web_socket.js +312 -0
- data/examples/logger.rb +11 -0
- data/examples/reconfiguring-sinatra-watcher.rb +11 -0
- data/examples/reconfiguring-sinatra.rb +33 -0
- data/examples/simple-post.rb +17 -0
- data/examples/websocket.html +24 -0
- data/examples/websocket.rb +41 -0
- data/lib/noah.rb +6 -8
- data/lib/noah/app.rb +20 -268
- data/lib/noah/application_routes.rb +70 -0
- data/lib/noah/ark.rb +0 -0
- data/lib/noah/configuration_routes.rb +81 -0
- data/lib/noah/custom_watcher.rb +79 -0
- data/lib/noah/ephemeral_routes.rb +47 -0
- data/lib/noah/helpers.rb +37 -14
- data/lib/noah/host_routes.rb +69 -0
- data/lib/noah/models.rb +86 -5
- data/lib/noah/models/applications.rb +41 -0
- data/lib/noah/models/configurations.rb +49 -0
- data/lib/noah/models/ephemerals.rb +54 -0
- data/lib/noah/models/hosts.rb +56 -0
- data/lib/noah/models/services.rb +54 -0
- data/lib/noah/models/watchers.rb +62 -0
- data/lib/noah/passthrough.rb +11 -0
- data/lib/noah/service_routes.rb +71 -0
- data/lib/noah/validations.rb +1 -0
- data/lib/noah/validations/watcher_validations.rb +48 -0
- data/lib/noah/version.rb +1 -1
- data/lib/noah/watcher_routes.rb +45 -0
- data/noah.gemspec +25 -17
- data/spec/application_spec.rb +30 -30
- data/spec/configuration_spec.rb +78 -14
- data/spec/ephemeral_spec.rb +59 -0
- data/spec/host_spec.rb +21 -21
- data/spec/noahapp_application_spec.rb +6 -6
- data/spec/noahapp_configuration_spec.rb +5 -5
- data/spec/noahapp_ephemeral_spec.rb +115 -0
- data/spec/noahapp_host_spec.rb +3 -3
- data/spec/noahapp_service_spec.rb +10 -10
- data/spec/noahapp_watcher_spec.rb +123 -0
- data/spec/service_spec.rb +27 -27
- data/spec/spec_helper.rb +13 -22
- data/spec/support/db/.keep +0 -0
- data/spec/support/test-redis.conf +8 -0
- data/spec/watcher_spec.rb +62 -0
- data/views/index.haml +21 -15
- metadata +189 -146
- data/Gemfile.lock +0 -83
- data/doc/coverage/index.html +0 -138
- data/doc/coverage/jquery-1.3.2.min.js +0 -19
- data/doc/coverage/jquery.tablesorter.min.js +0 -15
- data/doc/coverage/lib-helpers_rb.html +0 -393
- data/doc/coverage/lib-models_rb.html +0 -1449
- data/doc/coverage/noah_rb.html +0 -2019
- data/doc/coverage/print.css +0 -12
- data/doc/coverage/rcov.js +0 -42
- data/doc/coverage/screen.css +0 -270
- data/lib/noah/applications.rb +0 -46
- data/lib/noah/configurations.rb +0 -49
- data/lib/noah/hosts.rb +0 -54
- data/lib/noah/services.rb +0 -57
- data/lib/noah/watchers.rb +0 -18
data/Rakefile
CHANGED
@@ -1,48 +1,70 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "lib")))
|
1
2
|
require 'bundler'
|
2
|
-
begin
|
3
|
-
Bundler.setup(:default, :development)
|
4
|
-
rescue Bundler::BundlerError => e
|
5
|
-
$stderr.puts e.message
|
6
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
-
exit e.status_code
|
8
|
-
end
|
9
|
-
require 'rake'
|
10
|
-
|
11
3
|
require 'rspec/core'
|
12
4
|
require 'rspec/core/rake_task'
|
13
5
|
|
6
|
+
REDIS_DIR = File.expand_path(File.join("..", "spec", "support"), __FILE__)
|
7
|
+
REDIS_CNF = File.join(REDIS_DIR, "test-redis.conf")
|
8
|
+
|
14
9
|
Bundler::GemHelper.install_tasks
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
11
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
task :default => :run
|
16
|
+
task :test => :run
|
17
|
+
|
18
|
+
desc "Run tests and manage server start/stop"
|
19
|
+
task :run => [:start, :spec, :stop]
|
20
|
+
|
21
|
+
task :start do
|
22
|
+
puts "Starting redis-server"
|
23
|
+
system "redis-server #{REDIS_CNF}"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :stop do
|
27
|
+
puts "Killing redis"
|
28
|
+
system "killall -TERM redis-server"
|
29
|
+
end
|
30
|
+
|
31
|
+
namespace :coverage do
|
32
|
+
task(:clean) { rm_f "coverage.data" }
|
33
|
+
end
|
34
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
35
|
+
t.rcov = true
|
36
|
+
t.verbose = true
|
37
|
+
t.rcov_opts = %q[--aggregate coverage.data --sort coverage --text-report --exclude "config,.bundle/*,gems/*,spec/*" -o doc/coverage -Ilib -i "noah.rb"]
|
38
|
+
end
|
15
39
|
|
16
40
|
desc "Populate database with sample dataset"
|
17
41
|
task :sample, :redis_url do |t, args|
|
18
|
-
require '
|
19
|
-
begin
|
20
|
-
require 'yajl'
|
21
|
-
rescue LoadError
|
22
|
-
require 'json'
|
23
|
-
end
|
24
|
-
require File.join(File.dirname(__FILE__), 'lib','noah')
|
42
|
+
require 'noah'
|
25
43
|
|
26
|
-
|
27
44
|
Ohm::connect(:url => args.redis_url)
|
28
45
|
Ohm::redis.flushdb
|
46
|
+
puts "Creating watchers..."
|
47
|
+
Noah::Watcher.create :endpoint => "http://localhost:3000/webhook", :pattern => "//noah/application"
|
48
|
+
Noah::Watcher.create :endpoint => "http://localhost:3001/webhook", :pattern => "//noah/configuration"
|
49
|
+
Noah::Watcher.create :endpoint => "http://localhost:3002/webhook", :pattern => "//noah/host"
|
50
|
+
Noah::Watcher.create :endpoint => "http://localhost:3003/webhook", :pattern => "//noah/service"
|
29
51
|
puts "Creating Host entry for 'localhost'"
|
30
|
-
h = Host.create(:name => 'localhost', :status => "up")
|
52
|
+
h = Noah::Host.create(:name => 'localhost', :status => "up")
|
31
53
|
if h.save
|
32
54
|
%w[redis noah].each do |service|
|
33
55
|
puts "Create Service entry for #{service}"
|
34
|
-
s = Service.create(:name => service, :status => "up", :host => h)
|
56
|
+
s = Noah::Service.create(:name => service, :status => "up", :host => h)
|
35
57
|
h.services << s
|
36
58
|
end
|
37
59
|
end
|
38
60
|
|
39
61
|
puts "Creating Application entry for 'noah'"
|
40
|
-
a = Application.create(:name => 'noah')
|
62
|
+
a = Noah::Application.create(:name => 'noah')
|
41
63
|
if a.save
|
42
64
|
puts "Creating Configuration entry for 'noah'"
|
43
|
-
cr = Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0', :application => a)
|
44
|
-
ch = Configuration.create(:name => 'host', :format => 'string', :body => 'localhost', :application => a)
|
45
|
-
cp = Configuration.create(:name => 'port', :format => 'string', :body => '9292', :application => a)
|
65
|
+
cr = Noah::Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0', :application => a)
|
66
|
+
ch = Noah::Configuration.create(:name => 'host', :format => 'string', :body => 'localhost', :application => a)
|
67
|
+
cp = Noah::Configuration.create(:name => 'port', :format => 'string', :body => '9292', :application => a)
|
46
68
|
%w[cr ch cp].each do |c|
|
47
69
|
a.configurations << eval(c)
|
48
70
|
end
|
@@ -50,10 +72,10 @@ task :sample, :redis_url do |t, args|
|
|
50
72
|
|
51
73
|
puts "Creating sample entries - Host and Service"
|
52
74
|
%w[host1.domain.com host2.domain.com host3.domain.com].each do |host|
|
53
|
-
h = Host.create(:name => host, :status => "up")
|
75
|
+
h = Noah::Host.create(:name => host, :status => "up")
|
54
76
|
if h.save
|
55
77
|
%w[http https smtp mysql].each do |service|
|
56
|
-
s = Service.create(:name => service, :status => "pending", :host => h)
|
78
|
+
s = Noah::Service.create(:name => service, :status => "pending", :host => h)
|
57
79
|
h.services << s
|
58
80
|
end
|
59
81
|
end
|
@@ -74,32 +96,34 @@ EOY
|
|
74
96
|
}
|
75
97
|
EOJ
|
76
98
|
|
77
|
-
a1 = Application.create(:name => 'myrailsapp1')
|
99
|
+
a1 = Noah::Application.create(:name => 'myrailsapp1')
|
78
100
|
if a1.save
|
79
|
-
c1 = Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
|
101
|
+
c1 = Noah::Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
|
80
102
|
a1.configurations << c1
|
81
103
|
end
|
82
104
|
|
83
|
-
a2 = Application.create(:name => 'myrestapp1')
|
105
|
+
a2 = Noah::Application.create(:name => 'myrestapp1')
|
84
106
|
if a2.save
|
85
|
-
c2 = Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
|
107
|
+
c2 = Noah::Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
|
86
108
|
a2.configurations << c2
|
87
109
|
end
|
88
110
|
puts "Sample data populated!"
|
89
111
|
end
|
90
|
-
|
91
112
|
|
92
|
-
|
93
|
-
|
113
|
+
begin
|
114
|
+
require 'yard'
|
115
|
+
require 'yard/sinatra'
|
116
|
+
desc "Generate documentation"
|
117
|
+
YARD::Rake::YardocTask.new do |t|
|
118
|
+
t.files = ['lib/**/*.rb'] # optional
|
119
|
+
t.options = ['--title', "Noah #{Noah::VERSION} Documentation"]
|
120
|
+
t.options += ['--plugin', "yard-sinatra"]
|
121
|
+
t.options += ['--protected', '--private'] # optional
|
122
|
+
end
|
123
|
+
rescue LoadError
|
124
|
+
"You need YARD installed to generate docs"
|
94
125
|
end
|
95
126
|
|
96
|
-
|
97
|
-
|
98
|
-
task(:clean) { rm_f "coverage.data" }
|
99
|
-
end
|
100
|
-
desc "Run Rcov code coverage analysis"
|
101
|
-
RSpec::Core::RakeTask.new(:coverage) do |t|
|
102
|
-
t.rcov = true
|
103
|
-
t.verbose = true
|
104
|
-
t.rcov_opts = %q[--aggregate coverage.data --sort coverage --text-report --exclude "config,.bundle/*,gems/*,spec/*" -o doc/coverage -Ilib -i "noah.rb"]
|
127
|
+
task :start_demo do
|
128
|
+
puts "Soon, young padawan"
|
105
129
|
end
|
data/TODO.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Brain dump of stuff
|
2
|
+
* Fix JRuby
|
3
|
+
|
4
|
+
This is an ongoing issue for me. I can't rely on stuff that's MRI only.
|
5
|
+
|
6
|
+
* Break agent into separate gem
|
7
|
+
|
8
|
+
Again so that the server gem can be as lean as possible
|
9
|
+
|
10
|
+
* Documentation
|
11
|
+
|
12
|
+
Need to finish documenting everything for YARD to pick up.
|
13
|
+
|
14
|
+
* Stabilize API
|
15
|
+
|
16
|
+
I'm seriously considering moving to a single endpoint with JSON request bodies. Still up in the air. I'm not totally sold on the current layout.
|
17
|
+
|
18
|
+
* Write my own CLI class
|
19
|
+
|
20
|
+
I think I might be bumping into some issues related to Vegas as well.
|
21
|
+
|
22
|
+
* Watchers
|
23
|
+
|
24
|
+
**IN PROGRESS**
|
25
|
+
Need to resolve some issues around pathing for Configuration and Service nodes however watch registration and listing are up.
|
26
|
+
Need to address alternative watcher URIs. Webhook is the only one supported right now.
|
27
|
+
|
28
|
+
* Ephemeral nodes
|
29
|
+
|
30
|
+
**IN PROGRESS**
|
31
|
+
implement lifetime support
|
32
|
+
|
33
|
+
* Examples
|
34
|
+
|
35
|
+
Pretty happy with the examples I have but I need more. Want some in other languages - Python, Java, whatever!
|
36
|
+
|
37
|
+
* Clean up deps
|
38
|
+
|
39
|
+
Feels like I'm relying too much on external libraries.
|
40
|
+
|
41
|
+
* Benchmark
|
42
|
+
|
43
|
+
Need some client libs for this
|
44
|
+
|
45
|
+
# Done TODOS
|
46
|
+
* Github pages
|
47
|
+
- see [[http://lusis.github.com/Noah/]]
|
48
|
+
|
49
|
+
* Examples
|
50
|
+
- Sort of done. Demo app is up! [[http://noah-demo.heroku.com/]]. Also see `examples` directory.
|
51
|
+
|
52
|
+
* Consider ditching Sinatra::Namespace
|
53
|
+
- Done. It was also causing issues with YARD generation. @rkh confirmed known issue via twitter.
|
54
|
+
|
55
|
+
* Namespace models
|
56
|
+
- Done.
|
57
|
+
|
58
|
+
* Watchers
|
59
|
+
- Done. GET PUT DELETE are all available at the '/w/' endpoint now!
|
60
|
+
|
61
|
+
|
62
|
+
## Watcher specific stuff
|
63
|
+
* Implement AMQP
|
64
|
+
* Implement REST
|
65
|
+
* Implement JMX on JRuby
|
data/bin/noah
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
3
|
+
require 'rubygems'
|
3
4
|
require 'noah'
|
4
5
|
require 'vegas'
|
5
6
|
|
6
7
|
Vegas::Runner.new(Noah::App, 'noah') do |runner, opts, app|
|
7
|
-
opts.on("-r", "--redis URL", "redis url to connect to (default: redis://localhost:6379/0)") {|r| ENV["REDIS_URL"] = r }
|
8
|
+
opts.on("-r", "--redis URL", "redis url to connect to (default: redis://localhost:6379/0)") {|r| ENV["REDIS_URL"] = r; Noah::App.set :redis_url, r }
|
8
9
|
end
|
data/bin/noah-watcher.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
3
|
+
HELP = <<-EOH
|
4
|
+
Unfortunately, the agent script has some difficult requirements right now.
|
5
|
+
Please see https://github.com/lusis/Noah/Watcher-Agent for details.
|
6
|
+
EOH
|
7
|
+
begin
|
8
|
+
require 'rubygems'
|
9
|
+
require 'logger'
|
10
|
+
require 'optparse'
|
11
|
+
require 'em-hiredis'
|
12
|
+
require 'eventmachine'
|
13
|
+
require 'em-http-request'
|
14
|
+
require 'noah'
|
15
|
+
require 'json'
|
16
|
+
rescue LoadError
|
17
|
+
puts HELP
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
LOGGER = Logger.new(STDOUT)
|
22
|
+
|
23
|
+
class EventMachine::NoahAgent
|
24
|
+
include EM::Deferrable
|
25
|
+
|
26
|
+
@@watchers = Noah::Watcher.watch_list
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@logger = LOGGER
|
30
|
+
@logger.debug("Initializing with #{@@watchers.size} registered watches")
|
31
|
+
if EventMachine.reactor_running?
|
32
|
+
@worker = EM.spawn {|event, message, watch_list|
|
33
|
+
logger = LOGGER
|
34
|
+
logger.info("Worker initiated")
|
35
|
+
logger.debug("got event on http worker: #{event}")
|
36
|
+
matches = watch_list.find_all{|w| event =~ /^#{Base64.decode64(w)}/}
|
37
|
+
logger.debug("Found #{matches.size} matches for #{event}")
|
38
|
+
EM::Iterator.new(matches).each do |watch, iter|
|
39
|
+
p, ep = Base64.decode64(watch).split("|")
|
40
|
+
logger.info("Sending message to: #{ep} for pattern: #{p}")
|
41
|
+
http = EM::HttpRequest.new(ep, :connection_timeout => 2, :inactivity_timeout => 4).post :body => message
|
42
|
+
http.callback {
|
43
|
+
logger.info("Message posted to #{ep} successfully")
|
44
|
+
}
|
45
|
+
http.errback {
|
46
|
+
logger.error("Something went wrong")
|
47
|
+
}
|
48
|
+
iter.next
|
49
|
+
end
|
50
|
+
}
|
51
|
+
self.succeed("Succeed callback")
|
52
|
+
else
|
53
|
+
logger.fatal("Must be inside a reactor!")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def watchers
|
58
|
+
@@watchers.size
|
59
|
+
end
|
60
|
+
|
61
|
+
def reread_watchers
|
62
|
+
@logger.debug("Found new watches")
|
63
|
+
@logger.debug("Current watch count: #{@@watchers.size}")
|
64
|
+
@@watchers = Noah::Watcher.watch_list
|
65
|
+
@logger.debug("New watch count: #{@@watchers.size}")
|
66
|
+
#@logger.debug(@@watchers)
|
67
|
+
end
|
68
|
+
|
69
|
+
def broker(msg)
|
70
|
+
# This is just for testing for now
|
71
|
+
e,m = msg.split("|")
|
72
|
+
be = Base64.encode64(e).gsub("\n","")
|
73
|
+
@worker.notify e, m, @@watchers.clone
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
EventMachine.run do
|
78
|
+
EM.error_handler do |e|
|
79
|
+
Logger.new(STDOUT).warn(e)
|
80
|
+
end
|
81
|
+
logger = LOGGER
|
82
|
+
trap("INT") { logger.debug("Shutting down. Watches will not be fired");EM.stop }
|
83
|
+
noah = EventMachine::NoahAgent.new
|
84
|
+
noah.errback{|x| logger.error("Errback: #{x}")}
|
85
|
+
noah.callback{|y| logger.info("Callback: #{y}")}
|
86
|
+
# Passing messages...like a boss
|
87
|
+
master_channel = EventMachine::Channel.new
|
88
|
+
|
89
|
+
r = EventMachine::Hiredis::Client.connect
|
90
|
+
r.errback{|x| logger.error("Unable to connect to redis: #{x}")}
|
91
|
+
logger.debug("Starting up")
|
92
|
+
r.psubscribe("//noah/*")
|
93
|
+
r.on(:pmessage) do |pattern, event, message|
|
94
|
+
noah.reread_watchers if event =~ /^\/\/noah\/watcher\/.*/
|
95
|
+
master_channel.push "#{event}|#{message}"
|
96
|
+
logger.debug("Saw[#{event}]")
|
97
|
+
end
|
98
|
+
|
99
|
+
sub = master_channel.subscribe {|msg|
|
100
|
+
# We short circuit if we have no watchers
|
101
|
+
noah.broker(msg) unless noah.watchers == 0
|
102
|
+
}
|
103
|
+
end
|
data/config.ru
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require File.join('.', 'lib','noah')
|
3
|
+
## Uncomment the following to hardcode a redis url
|
4
|
+
ENV['REDIS_URL'] = "redis://localhost:6379/1"
|
5
|
+
noah = Noah::App.new
|
6
|
+
run noah
|
data/config/warble.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Disable automatic framework detection by uncommenting/setting to false
|
2
|
+
# Warbler.framework_detection = false
|
3
|
+
|
4
|
+
# Warbler web application assembly configuration file
|
5
|
+
Warbler::Config.new do |config|
|
6
|
+
#config.features = %w(gemjar)
|
7
|
+
config.dirs = %w(config lib views)
|
8
|
+
config.includes = FileList["config.ru"]
|
9
|
+
config.excludes = FileList["noah.gemspec", "Gemfile", "Gemfile.lock"]
|
10
|
+
config.bundler = false
|
11
|
+
config.gems += ["json", "ohm", "ohm-contrib", "sinatra", "sinatra-namespace", "haml"]
|
12
|
+
config.gem_excludes = [/^(test|spec)\//]
|
13
|
+
config.public_html = FileList["views/**/*"]
|
14
|
+
config.webxml.booter = :rack
|
15
|
+
#config.webxml.rackup.path = 'WEB-INF/config.ru'
|
16
|
+
#config.webxml.rackup = %{require './lib/noah'; run Noah::App}
|
17
|
+
# config.webxml.rackup = require 'cgi' && CGI::escapeHTML(File.read("config.ru"))
|
18
|
+
end
|
data/examples/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Examples
|
2
|
+
The following is a list of notes regarding the examples in this directory.
|
3
|
+
|
4
|
+
## General Requirements
|
5
|
+
|
6
|
+
You'll need a few additional gems
|
7
|
+
|
8
|
+
* [em-hiredis](https://github.com/mloughran/em-hiredis)
|
9
|
+
You'll have to compile/install from source. Sorry. Should pull in the `hiredis` native ext.
|
10
|
+
* [em-http-request](https://github.com/igrigorik/em-http-request)
|
11
|
+
Available via rubygems
|
12
|
+
* [em-websocket](https://github.com/igrigorik/em-websocket)
|
13
|
+
Available via rubygems
|
14
|
+
|
15
|
+
## custom-watcher.rb
|
16
|
+
This is an idea I'm tossing around for allowing easy custom watchers to be written.
|
17
|
+
Essentially the idea is that you tap into the Redis subscription with a defined pattern and a destination.
|
18
|
+
|
19
|
+
### Example
|
20
|
+
|
21
|
+
require './watcher-idea.rb'
|
22
|
+
|
23
|
+
Noah::Watcher.watch do
|
24
|
+
pattern "//noah/configuration/*"
|
25
|
+
destination Proc.new {|x| something_with(x)}
|
26
|
+
run!
|
27
|
+
end
|
28
|
+
|
29
|
+
## logger.rb
|
30
|
+
An example using logger as a watcher. Pretty straighforward.
|
31
|
+
|
32
|
+
|
33
|
+
## httpclient.rb/httpclient-server.rb
|
34
|
+
This is an example of how the Webhook system would work
|
35
|
+
|
36
|
+
### Running
|
37
|
+
|
38
|
+
To get the maximum effect, start with a clean Redis database
|
39
|
+
|
40
|
+
* Start the webhook reciever
|
41
|
+
|
42
|
+
noah/examples$ ruby httpclient-server.rb
|
43
|
+
== Sinatra/1.1.2 has taken the stage on 4567 for development with backup from Thin
|
44
|
+
>> Thin web server (v1.2.7 codename No Hup)
|
45
|
+
>> Maximum connections set to 1024
|
46
|
+
>> Listening on 0.0.0.0:4567, CTRL+C to stop
|
47
|
+
|
48
|
+
* Start the webhook publisher
|
49
|
+
|
50
|
+
noah/examples$ ruby httpclient.rb
|
51
|
+
|
52
|
+
* Run the rake sample script
|
53
|
+
|
54
|
+
In the publisher window, you should see some messages like so:
|
55
|
+
|
56
|
+
Got message for noah.Host[localhost].create
|
57
|
+
Got message for noah.Host[localhost].save
|
58
|
+
Got message for noah.Host[localhost].save
|
59
|
+
Got message for noah.Host[localhost].update
|
60
|
+
|
61
|
+
In the server window, you should see the following:
|
62
|
+
|
63
|
+
"{\"id\":\"1\",\"name\":\"localhost\",\"status\":\"up\",\"created_at\":\"2011-02-15 05:19:05 UTC\",\"updated_at\":\"2011-02-15 05:19:05 UTC\",\"services\":[]}"
|
64
|
+
127.0.0.1 - - [15/Feb/2011 00:19:05] "POST /webhook HTTP/1.1" 200 135 0.0024
|
65
|
+
"{\"id\":\"1\",\"name\":\"localhost\",\"status\":\"up\",\"created_at\":\"2011-02-15 05:19:05 UTC\",\"updated_at\":\"2011-02-15 05:19:05 UTC\",\"services\":[]}"
|
66
|
+
127.0.0.1 - - [15/Feb/2011 00:19:05] "POST /webhook HTTP/1.1" 200 135 0.0004
|
67
|
+
"{\"id\":\"1\",\"name\":\"localhost\",\"status\":\"up\",\"created_at\":\"2011-02-15 05:19:05 UTC\",\"updated_at\":\"2011-02-15 05:19:05 UTC\",\"services\":[]}"
|
68
|
+
|
69
|
+
|
70
|
+
## websocket.rb
|
71
|
+
This is an example of using Websockets, EventMachine and Redis PubSub to provide a "status" console of sorts.
|
72
|
+
|
73
|
+
### Running
|
74
|
+
|
75
|
+
To get the maximum effect, start with a clean Redis database.
|
76
|
+
|
77
|
+
* Start the server:
|
78
|
+
|
79
|
+
~/development/noah/examples$ ./websocket.rb
|
80
|
+
>> Thin web server (v1.2.7 codename No Hup)
|
81
|
+
>> Maximum connections set to 1024
|
82
|
+
>> Listening on 0.0.0.0:3000, CTRL+C to stop
|
83
|
+
|
84
|
+
You should be able to load up the "normal" Noah sample page on [http://localhost:3000].
|
85
|
+
|
86
|
+
* Load the "websocket" file
|
87
|
+
|
88
|
+
In another browser window, open the `websocket.html` file.
|
89
|
+
|
90
|
+
* Send a message
|
91
|
+
|
92
|
+
From another terminal window send the following:
|
93
|
+
|
94
|
+
curl -X PUT -d '{"name":"testhost2","status":"down"}' http://localhost:3000/h/testhost2
|
95
|
+
|
96
|
+
You should see the message come across in the browser window like so:
|
97
|
+
|
98
|
+
connected...
|
99
|
+
|
100
|
+
2 connected and waiting....
|
101
|
+
|
102
|
+
(noah.Host[testhost2].create) {"id":"1","name":"testhost2","status":"down","created_at":"2011-02-14 20:58:04 UTC","updated_at":"2011-02-14 20:58:04 UTC","services":[]}
|
103
|
+
|
104
|
+
(noah.Host[testhost2].save) {"id":"1","name":"testhost2","status":"down","created_at":"2011-02-14 20:58:04 UTC","updated_at":"2011-02-14 20:58:04 UTC","services":[]}
|
105
|
+
|
106
|
+
(noah.Host[testhost2].save) {"id":"1","name":"testhost2","status":"down","created_at":"2011-02-14 20:58:04 UTC","updated_at":"2011-02-14 20:58:04 UTC","services":[]}
|
107
|
+
|
108
|
+
(noah.Host[testhost2].update) {"id":"1","name":"testhost2","status":"down","created_at":"2011-02-14 20:58:04 UTC","updated_at":"2011-02-14 20:58:04 UTC","services":[]}
|
109
|
+
|
110
|
+
You can see the Watcher pattern in the parenthesis and then the JSON message body.
|
111
|
+
|
112
|
+
For fun, refresh the page to clear it and then run the sample data population rake task.
|
113
|
+
|
114
|
+
### Known issues
|
115
|
+
When I started working on the Watcher stuff, I realized that I'm sending A LOT of extranous messages. These are mostly the result of the way I'm creating new objects with Ohm (i.e. via `.create`).
|
116
|
+
I'll be cleaning that up and trying to get down to a single message per operation.
|