noah 0.0.5 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/.gitignore +9 -0
- data/LICENSE +201 -0
- data/README.md +68 -212
- data/Rakefile +70 -41
- data/TODO.md +59 -0
- data/bin/noah +2 -1
- data/bin/noah-watcher.rb +93 -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 +32 -0
- data/examples/simple-post.rb +17 -0
- data/examples/websocket.html +24 -0
- data/examples/websocket.rb +41 -0
- data/lib/noah.rb +5 -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/ephemeral_routes.rb +19 -0
- data/lib/noah/helpers.rb +12 -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 +33 -0
- data/lib/noah/models/hosts.rb +56 -0
- data/lib/noah/models/services.rb +54 -0
- data/lib/noah/models/watchers.rb +54 -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.rb +75 -0
- data/lib/noah/watcher_routes.rb +12 -0
- data/lib/vendor/em-hiredis/Gemfile +4 -0
- data/lib/vendor/em-hiredis/README.md +61 -0
- data/lib/vendor/em-hiredis/Rakefile +2 -0
- data/lib/vendor/em-hiredis/em-hiredis-0.0.1.gem +0 -0
- data/lib/vendor/em-hiredis/em-hiredis.gemspec +23 -0
- data/lib/vendor/em-hiredis/lib/em-hiredis.rb +22 -0
- data/lib/vendor/em-hiredis/lib/em-hiredis/client.rb +131 -0
- data/lib/vendor/em-hiredis/lib/em-hiredis/connection.rb +61 -0
- data/lib/vendor/em-hiredis/lib/em-hiredis/event_emitter.rb +29 -0
- data/lib/vendor/em-hiredis/lib/em-hiredis/version.rb +5 -0
- data/noah.gemspec +21 -17
- data/spec/application_spec.rb +30 -30
- data/spec/configuration_spec.rb +81 -14
- data/spec/ephemeral_spec.rb +52 -0
- data/spec/host_spec.rb +21 -21
- data/spec/noahapp_application_spec.rb +6 -6
- data/spec/noahapp_configuration_spec.rb +3 -3
- data/spec/noahapp_host_spec.rb +2 -2
- data/spec/noahapp_service_spec.rb +9 -9
- data/spec/noahapp_watcher_spec.rb +34 -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 +124 -148
- data/Gemfile.lock +0 -85
- 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,74 @@
|
|
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 => [:start, :spec, :stop]
|
17
|
+
|
18
|
+
desc "Run tests and manage server start/stop"
|
19
|
+
task :run => [:start, :spec, :stop]
|
20
|
+
|
21
|
+
desc "Start the Redis server"
|
22
|
+
task :start do
|
23
|
+
puts "Starting redis-server"
|
24
|
+
system "redis-server #{REDIS_CNF}"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Stop the Redis server"
|
28
|
+
task :stop do
|
29
|
+
puts "Killing redis"
|
30
|
+
system "killall -TERM redis-server"
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :coverage do
|
34
|
+
desc "Delete aggregate coverage data."
|
35
|
+
task(:clean) { rm_f "coverage.data" }
|
36
|
+
end
|
37
|
+
desc "Run Rcov code coverage analysis"
|
38
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
39
|
+
t.rcov = true
|
40
|
+
t.verbose = true
|
41
|
+
t.rcov_opts = %q[--aggregate coverage.data --sort coverage --text-report --exclude "config,.bundle/*,gems/*,spec/*" -o doc/coverage -Ilib -i "noah.rb"]
|
42
|
+
end
|
15
43
|
|
16
44
|
desc "Populate database with sample dataset"
|
17
45
|
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')
|
46
|
+
require 'noah'
|
25
47
|
|
26
|
-
|
27
48
|
Ohm::connect(:url => args.redis_url)
|
28
49
|
Ohm::redis.flushdb
|
50
|
+
puts "Creating watchers..."
|
51
|
+
Noah::Watcher.create :endpoint => "http://localhost:3000/webhook", :pattern => "//noah/application"
|
52
|
+
Noah::Watcher.create :endpoint => "http://localhost:3001/webhook", :pattern => "//noah/configuration"
|
53
|
+
Noah::Watcher.create :endpoint => "http://localhost:3002/webhook", :pattern => "//noah/host"
|
54
|
+
Noah::Watcher.create :endpoint => "http://localhost:3003/webhook", :pattern => "//noah/service"
|
29
55
|
puts "Creating Host entry for 'localhost'"
|
30
|
-
h = Host.create(:name => 'localhost', :status => "up")
|
56
|
+
h = Noah::Host.create(:name => 'localhost', :status => "up")
|
31
57
|
if h.save
|
32
58
|
%w[redis noah].each do |service|
|
33
59
|
puts "Create Service entry for #{service}"
|
34
|
-
s = Service.create(:name => service, :status => "up", :host => h)
|
60
|
+
s = Noah::Service.create(:name => service, :status => "up", :host => h)
|
35
61
|
h.services << s
|
36
62
|
end
|
37
63
|
end
|
38
64
|
|
39
65
|
puts "Creating Application entry for 'noah'"
|
40
|
-
a = Application.create(:name => 'noah')
|
66
|
+
a = Noah::Application.create(:name => 'noah')
|
41
67
|
if a.save
|
42
68
|
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)
|
69
|
+
cr = Noah::Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0', :application => a)
|
70
|
+
ch = Noah::Configuration.create(:name => 'host', :format => 'string', :body => 'localhost', :application => a)
|
71
|
+
cp = Noah::Configuration.create(:name => 'port', :format => 'string', :body => '9292', :application => a)
|
46
72
|
%w[cr ch cp].each do |c|
|
47
73
|
a.configurations << eval(c)
|
48
74
|
end
|
@@ -50,10 +76,10 @@ task :sample, :redis_url do |t, args|
|
|
50
76
|
|
51
77
|
puts "Creating sample entries - Host and Service"
|
52
78
|
%w[host1.domain.com host2.domain.com host3.domain.com].each do |host|
|
53
|
-
h = Host.create(:name => host, :status => "up")
|
79
|
+
h = Noah::Host.create(:name => host, :status => "up")
|
54
80
|
if h.save
|
55
81
|
%w[http https smtp mysql].each do |service|
|
56
|
-
s = Service.create(:name => service, :status => "pending", :host => h)
|
82
|
+
s = Noah::Service.create(:name => service, :status => "pending", :host => h)
|
57
83
|
h.services << s
|
58
84
|
end
|
59
85
|
end
|
@@ -74,32 +100,35 @@ EOY
|
|
74
100
|
}
|
75
101
|
EOJ
|
76
102
|
|
77
|
-
a1 = Application.create(:name => 'myrailsapp1')
|
103
|
+
a1 = Noah::Application.create(:name => 'myrailsapp1')
|
78
104
|
if a1.save
|
79
|
-
c1 = Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
|
105
|
+
c1 = Noah::Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
|
80
106
|
a1.configurations << c1
|
81
107
|
end
|
82
108
|
|
83
|
-
a2 = Application.create(:name => 'myrestapp1')
|
109
|
+
a2 = Noah::Application.create(:name => 'myrestapp1')
|
84
110
|
if a2.save
|
85
|
-
c2 = Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
|
111
|
+
c2 = Noah::Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
|
86
112
|
a2.configurations << c2
|
87
113
|
end
|
88
114
|
puts "Sample data populated!"
|
89
115
|
end
|
90
|
-
|
91
116
|
|
92
|
-
|
93
|
-
|
117
|
+
begin
|
118
|
+
require 'yard'
|
119
|
+
require 'yard/sinatra'
|
120
|
+
desc "Generate documentation"
|
121
|
+
YARD::Rake::YardocTask.new do |t|
|
122
|
+
t.files = ['lib/**/*.rb'] # optional
|
123
|
+
t.options = ['--title', "Noah #{Noah::VERSION} Documentation"]
|
124
|
+
t.options += ['--plugin', "yard-sinatra"]
|
125
|
+
t.options += ['--protected', '--private'] # optional
|
126
|
+
end
|
127
|
+
rescue LoadError
|
128
|
+
"You need YARD installed to generate docs"
|
94
129
|
end
|
95
130
|
|
96
|
-
|
97
|
-
|
98
|
-
|
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"]
|
131
|
+
desc "Demo environment"
|
132
|
+
task :start_demo do
|
133
|
+
puts "Soon, young padawan"
|
105
134
|
end
|
data/TODO.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Brain dump of stuff
|
2
|
+
* Documentation
|
3
|
+
|
4
|
+
Need to finish documenting everything for YARD to pick up.
|
5
|
+
|
6
|
+
* Stabilize API
|
7
|
+
|
8
|
+
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.
|
9
|
+
|
10
|
+
* Write my own CLI class
|
11
|
+
|
12
|
+
I think I might be bumping into some issues related to Vegas as well.
|
13
|
+
|
14
|
+
* Watchers
|
15
|
+
|
16
|
+
This is going to be a fun task. I'm serious.
|
17
|
+
|
18
|
+
* Ephemeral nodes
|
19
|
+
|
20
|
+
Not sure how I want to implement that. Not too keen on storing them as in-memory hashes. Maybe a LRU in Redis?
|
21
|
+
|
22
|
+
* Examples
|
23
|
+
|
24
|
+
I need to make some example apps to really demonstrate what I'm trying to accomplish.
|
25
|
+
|
26
|
+
* Clean up deps
|
27
|
+
|
28
|
+
Feels like I'm relying too much on external libraries.
|
29
|
+
|
30
|
+
* Benchmark
|
31
|
+
|
32
|
+
Need some client libs for this
|
33
|
+
|
34
|
+
# Done TODOS
|
35
|
+
* Github pages
|
36
|
+
- see [[http://lusis.github.com/Noah/]]
|
37
|
+
|
38
|
+
* Bundle a war
|
39
|
+
- see [[https://github.com/downloads/lusis/Noah/noah.war]]
|
40
|
+
|
41
|
+
* Examples
|
42
|
+
- Sort of done. Demo app is up! [[http://noah-demo.heroku.com/]]. Also see `examples` directory.
|
43
|
+
|
44
|
+
* Consider ditching Sinatra::Namespace
|
45
|
+
- Done. It was also causing issues with YARD generation. @rkh confirmed known issue via twitter.
|
46
|
+
|
47
|
+
* Namespace models
|
48
|
+
- Done.
|
49
|
+
|
50
|
+
* Watchers
|
51
|
+
- Partially done. Framework is in place to create a custom Watcher by hooking directly into Redis. Need to expand that to "official" watchers
|
52
|
+
|
53
|
+
|
54
|
+
## Watcher specific stuff
|
55
|
+
* Implement a watcher endpoint
|
56
|
+
* Implement webhooks
|
57
|
+
* Implement AMQP
|
58
|
+
* Implement REST
|
59
|
+
* 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,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rbtrace'
|
5
|
+
require 'logger'
|
6
|
+
require 'optparse'
|
7
|
+
require 'em-hiredis'
|
8
|
+
require 'eventmachine'
|
9
|
+
require 'em-http-request'
|
10
|
+
require 'thin'
|
11
|
+
require 'noah'
|
12
|
+
require 'json'
|
13
|
+
|
14
|
+
LOGGER = Logger.new(STDOUT)
|
15
|
+
|
16
|
+
class EventMachine::NoahAgent
|
17
|
+
include EM::Deferrable
|
18
|
+
|
19
|
+
@@watchers = Noah::Watcher.watch_list
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@logger = LOGGER
|
23
|
+
@logger.debug("Initializing with #{@@watchers.size} registered watches")
|
24
|
+
if EventMachine.reactor_running?
|
25
|
+
@worker = EM.spawn {|event, message, watch_list|
|
26
|
+
logger = LOGGER
|
27
|
+
logger.debug("Worker initiated")
|
28
|
+
logger.info("got event on http worker: #{event}")
|
29
|
+
logger.info("got message on http worker: #{message}")
|
30
|
+
matches = watch_list.find_all{|w| event =~ /^#{Base64.decode64(w)}/}
|
31
|
+
logger.debug("Found #{matches.size} matches for #{event}")
|
32
|
+
EM::Iterator.new(matches).each do |watch, iter|
|
33
|
+
p, ep = Base64.decode64(watch).split("|")
|
34
|
+
logger.info("Sending message to: #{ep} for pattern: #{p}")
|
35
|
+
http = EM::HttpRequest.new(ep, :connection_timeout => 2, :inactivity_timeout => 4).post :body => message
|
36
|
+
http.callback {
|
37
|
+
LOGGER.debug("Message posted to #{ep} successfully")
|
38
|
+
#iter.next
|
39
|
+
}
|
40
|
+
http.errback {
|
41
|
+
LOGGER.debug("Something went wrong")
|
42
|
+
#iter.net
|
43
|
+
}
|
44
|
+
iter.next
|
45
|
+
end
|
46
|
+
}
|
47
|
+
else
|
48
|
+
logger.fatal("Must be inside a reactor!")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def watchers
|
53
|
+
@@watchers.size
|
54
|
+
end
|
55
|
+
|
56
|
+
def reread_watchers
|
57
|
+
@logger.debug("Found new watches")
|
58
|
+
@logger.debug("Current watch count: #{@@watchers.size}")
|
59
|
+
@@watchers = Noah::Watcher.watch_list
|
60
|
+
@logger.debug("New watch count: #{@@watchers.size}")
|
61
|
+
#@logger.debug(@@watchers)
|
62
|
+
end
|
63
|
+
|
64
|
+
def broker(msg)
|
65
|
+
# This is just for testing for now
|
66
|
+
@logger.warn(msg)
|
67
|
+
e,m = msg.split("|")
|
68
|
+
be = Base64.encode64(e).gsub("\n","")
|
69
|
+
@logger.info("Encoded event: #{be}")
|
70
|
+
@worker.notify e, m, @@watchers.clone
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
EventMachine.run do
|
75
|
+
logger = LOGGER
|
76
|
+
noah = EventMachine::NoahAgent.new
|
77
|
+
# Passing messages...like a boss
|
78
|
+
master_channel = EventMachine::Channel.new
|
79
|
+
|
80
|
+
r = EventMachine::Hiredis::Client.connect
|
81
|
+
logger.debug("Starting up")
|
82
|
+
r.psubscribe("//noah/*")
|
83
|
+
r.on(:pmessage) do |pattern, event, message|
|
84
|
+
noah.reread_watchers if event =~ /^\/\/noah\/watcher\/.*/
|
85
|
+
master_channel.push "#{event}|#{message}"
|
86
|
+
logger.debug("Saw[#{event}]")
|
87
|
+
end
|
88
|
+
|
89
|
+
sub = master_channel.subscribe {|msg|
|
90
|
+
# We short circuit if we have no watchers
|
91
|
+
noah.broker(msg) unless noah.watchers == 0
|
92
|
+
}
|
93
|
+
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.
|