noah 0.0.9 → 0.1

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/Rakefile CHANGED
@@ -13,28 +13,24 @@ end
13
13
 
14
14
 
15
15
  task :default => :run
16
- task :test => [:start, :spec, :stop]
16
+ task :test => :run
17
17
 
18
18
  desc "Run tests and manage server start/stop"
19
19
  task :run => [:start, :spec, :stop]
20
20
 
21
- desc "Start the Redis server"
22
21
  task :start do
23
22
  puts "Starting redis-server"
24
23
  system "redis-server #{REDIS_CNF}"
25
24
  end
26
25
 
27
- desc "Stop the Redis server"
28
26
  task :stop do
29
27
  puts "Killing redis"
30
28
  system "killall -TERM redis-server"
31
29
  end
32
30
 
33
31
  namespace :coverage do
34
- desc "Delete aggregate coverage data."
35
32
  task(:clean) { rm_f "coverage.data" }
36
33
  end
37
- desc "Run Rcov code coverage analysis"
38
34
  RSpec::Core::RakeTask.new(:coverage) do |t|
39
35
  t.rcov = true
40
36
  t.verbose = true
@@ -128,7 +124,6 @@ rescue LoadError
128
124
  "You need YARD installed to generate docs"
129
125
  end
130
126
 
131
- desc "Demo environment"
132
127
  task :start_demo do
133
128
  puts "Soon, young padawan"
134
129
  end
data/TODO.md CHANGED
@@ -1,4 +1,12 @@
1
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
+
2
10
  * Documentation
3
11
 
4
12
  Need to finish documenting everything for YARD to pick up.
@@ -13,15 +21,18 @@
13
21
 
14
22
  * Watchers
15
23
 
16
- This is going to be a fun task. I'm serious.
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.
17
27
 
18
28
  * Ephemeral nodes
19
29
 
20
- Not sure how I want to implement that. Not too keen on storing them as in-memory hashes. Maybe a LRU in Redis?
30
+ **IN PROGRESS**
31
+ implement lifetime support
21
32
 
22
33
  * Examples
23
34
 
24
- I need to make some example apps to really demonstrate what I'm trying to accomplish.
35
+ Pretty happy with the examples I have but I need more. Want some in other languages - Python, Java, whatever!
25
36
 
26
37
  * Clean up deps
27
38
 
@@ -35,9 +46,6 @@
35
46
  * Github pages
36
47
  - see [[http://lusis.github.com/Noah/]]
37
48
 
38
- * Bundle a war
39
- - see [[https://github.com/downloads/lusis/Noah/noah.war]]
40
-
41
49
  * Examples
42
50
  - Sort of done. Demo app is up! [[http://noah-demo.heroku.com/]]. Also see `examples` directory.
43
51
 
@@ -48,12 +56,10 @@
48
56
  - Done.
49
57
 
50
58
  * 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
59
+ - Done. GET PUT DELETE are all available at the '/w/' endpoint now!
52
60
 
53
61
 
54
62
  ## Watcher specific stuff
55
- * Implement a watcher endpoint
56
- * Implement webhooks
57
63
  * Implement AMQP
58
64
  * Implement REST
59
65
  * Implement JMX on JRuby
data/bin/noah-watcher.rb CHANGED
@@ -1,15 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
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'
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
13
20
 
14
21
  LOGGER = Logger.new(STDOUT)
15
22
 
@@ -73,6 +80,7 @@ end
73
80
 
74
81
  EventMachine.run do
75
82
  logger = LOGGER
83
+ trap("INT") { logger.debug("Shutting down. Watches will not be fired");EM.stop }
76
84
  noah = EventMachine::NoahAgent.new
77
85
  # Passing messages...like a boss
78
86
  master_channel = EventMachine::Channel.new
data/lib/noah/app.rb CHANGED
@@ -63,7 +63,7 @@ module Noah
63
63
  load File.join(File.dirname(__FILE__), 'application_routes.rb')
64
64
  load File.join(File.dirname(__FILE__), 'configuration_routes.rb')
65
65
  load File.join(File.dirname(__FILE__), 'watcher_routes.rb')
66
- #load File.joint(File.dirname(__FILE__), 'ephemeral_routes.rb')
66
+ load File.join(File.dirname(__FILE__), 'ephemeral_routes.rb')
67
67
 
68
68
  end
69
69
  end
@@ -41,7 +41,7 @@ class Noah::App
41
41
  r = {"result" => "success","id" => app.id, "action" => action, "name" => app.name }
42
42
  r.to_json
43
43
  else
44
- raise "#{app.errors}"
44
+ raise "#{format_errors(app)}"
45
45
  end
46
46
  end
47
47
 
@@ -59,7 +59,7 @@ class Noah::App
59
59
  r = {"result" => "success","id" => "#{config.id}", "action" => action, "dependencies" => dependency_action, "application" => app.name, "item" => config.name}
60
60
  r.to_json
61
61
  else
62
- raise "#{config.errors}"
62
+ raise "#{format_errors(config)}"
63
63
  end
64
64
  end
65
65
 
@@ -1,19 +1,48 @@
1
1
  class Noah::App
2
- # Stubbing Ephemeral endpoints
2
+ get '/e/?' do
3
+ halt 404
4
+ end
5
+
3
6
  get '/e/*' do
4
- # Some logic to handle splats for ephemerals
5
- # Eventually I'll move to root path
7
+ params["splat"].size == 0 ? (halt 404) : (e=Noah::Ephemeral.find(:path => "/#{params["splat"][0]}").first)
8
+ (halt 404) if e.nil?
9
+ content_type "application/octet-stream"
10
+ e.data.nil? ? "" : "#{e.data}"
6
11
  end
7
12
 
8
13
  put '/e/*/watch' do
9
- # Logic for adding watches to ephemerals
14
+ required_params = ["endpoint"]
15
+ data = JSON.parse(request.body.read)
16
+ (data.keys.sort == required_params.sort) ? (e = Noah::Watcher.find(:path => params[:splat][0]).first) : (raise "Missing Parameters")
17
+ e.nil? ? (halt 404) : (w = e.watch!(:endpoint => data["endpoint"]))
18
+ w.to_json
10
19
  end
11
20
 
12
21
  put '/e/*' do
13
- # Some logic for creating ephemerals
22
+ raise("Data too large") if request.body.size > 512
23
+ d = request.body.read || nil
24
+ e = Noah::Ephemeral.find_or_create(:path => "/#{params[:splat][0]}")
25
+ e.data = d
26
+ if e.valid?
27
+ e.save
28
+ action = e.is_new? ? "create" : "update"
29
+ r = {"action" => action, "result" => "success", "id" => e.id, "path" => e.path, "data" => e.data}
30
+ r.to_json
31
+ else
32
+ raise "#{format_errors(e)}"
33
+ end
14
34
  end
15
35
 
16
36
  delete '/e/*' do
17
- # See previous two entries
37
+ p = params[:splat][0]
38
+ e = Noah::Ephemeral.find(:path => "/"+p).first
39
+ if e
40
+ e.delete
41
+ r = {"result" => "success", "id" => "#{e.id}", "action" => "delete", "path" => e.name}
42
+ r.to_json
43
+ else
44
+ halt 404
45
+ end
18
46
  end
47
+
19
48
  end
data/lib/noah/helpers.rb CHANGED
@@ -1,5 +1,30 @@
1
1
  module Noah
2
2
  module SinatraHelpers
3
+
4
+ def format_errors(model)
5
+ error_messages = model.errors.present do |e|
6
+ # Missing attributes
7
+ e.on [:name, :not_present], "Name attribute missing"
8
+ e.on [:status, :not_present], "Status attribute missing"
9
+ e.on [:format, :not_present], "Format attribute missing"
10
+ e.on [:body, :not_present], "Body attribute missing"
11
+ e.on [:application_id, :not_present], "Application attribute missing"
12
+ e.on [:path, :not_present], "Path attribute missing"
13
+ e.on [:pattern, :not_present], "Pattern attribute missing"
14
+ e.on [:endpoint, :not_present], "Endpoint attribute missing"
15
+ # Invalid option
16
+ e.on [:status, :not_member], "Status must be up, down or pending"
17
+ # Duplicate keys
18
+ e.on [[:name, :application_id], :not_unique], "Record already exists"
19
+ e.on [[:name, :host_id], :not_unique], "Record already exists"
20
+ e.on [[:endpoint, :pattern], :not_unique], "Record already exists"
21
+ e.on [:path, :not_unique], "Record already exists"
22
+ # Custom exceptions
23
+ e.on [:pattern, :already_provided], "Pattern is already provided"
24
+ e.on [:pattern, :replaces_existing], "Pattern would overwrite existing"
25
+ end
26
+ error_messages.first
27
+ end
3
28
 
4
29
  def host(opts = {})
5
30
  Noah::Host.find(opts).first
@@ -49,7 +49,7 @@ class Noah::App
49
49
  r = {"result" => "success","id" => "#{host.id}","status" => "#{host.status}", "name" => "#{host.name}", "new_record" => host.is_new?}
50
50
  r.to_json
51
51
  else
52
- raise "#{host.errors}"
52
+ raise "#{format_errors(host)}"
53
53
  end
54
54
  end
55
55
 
@@ -1,9 +1,9 @@
1
- require 'digest/sha1'
2
1
  module Noah
3
2
  class Ephemeral < Model #NYI
4
3
 
5
4
  attribute :path
6
5
  attribute :data
6
+ attribute :lifetime
7
7
 
8
8
  index :path
9
9
 
@@ -17,6 +17,25 @@ module Noah
17
17
  @name = path
18
18
  end
19
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
+ find(opts).first.nil? ? (eph = create(opts)) : (eph = find(opts).first)
29
+ if eph.valid?
30
+ eph.save
31
+ end
32
+ eph
33
+ rescue Exception => e
34
+ e.message
35
+ end
36
+ end
37
+ end
38
+
20
39
  protected
21
40
  def save_hook
22
41
  # called after any create,update,delete
@@ -27,7 +46,7 @@ module Noah
27
46
  def path_protected?(path_part)
28
47
  # Check for protected paths in ephemeral nodes
29
48
  end
30
-
49
+
31
50
  end
32
51
 
33
52
  end
@@ -7,6 +7,7 @@ module Noah
7
7
 
8
8
  attribute :pattern
9
9
  attribute :endpoint
10
+ attribute :name
10
11
 
11
12
  index :pattern
12
13
  index :endpoint
@@ -29,12 +30,19 @@ module Noah
29
30
  super.merge(h)
30
31
  end
31
32
 
32
- def self.watch_list
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
33
40
  arr = []
34
41
  watches = self.all.sort_by(:pattern)
35
42
  watches.each {|w| arr << w.name}
36
43
  arr
37
44
  end
45
+ end
38
46
 
39
47
  private
40
48
  # Not sure about these next two.
@@ -50,7 +50,7 @@ class Noah::App
50
50
  r = {"action" => action, "result" => "success", "id" => service.id, "host" => h.name, "name" => service.name}
51
51
  r.to_json
52
52
  else
53
- raise "#{service.errors}"
53
+ raise "#{format_errors(service)}"
54
54
  end
55
55
  else
56
56
  raise "Missing Parameters"
data/lib/noah/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1"
3
3
  end
@@ -1,12 +1,45 @@
1
1
  class Noah::App
2
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
+
3
8
  get '/w/?' do
4
9
  w = Noah::Watcher.all.sort_by(:pattern)
5
10
  if w.size == 0
6
11
  halt 404
7
12
  else
8
13
  w.to_json
9
- end
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
10
43
  end
11
44
 
12
45
  end
data/noah.gemspec CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |s|
37
37
  s.add_development_dependency("warbler", ["= 1.2.1"])
38
38
  else
39
39
  s.add_dependency("yajl-ruby")
40
+ s.add_dependency("SystemTimer") if RUBY_VERSION =~ /1.8/
40
41
  s.add_dependency("thin")
41
42
  end
42
43
 
@@ -1,18 +1,15 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Using the Configuration Model", :reset_redis => true do
4
- before(:all) do
5
- app = Noah::Application.create(:name => "my_application")
6
- app.save
7
- @appconf_string = {:name => "mystringconf", :format => "string", :body => "some_var", :application_id => app.id}
8
- @appconf_json = {:name => "myjsonconf", :format => "json", :body => @appconf_string.to_json, :application_id => app.id}
9
- @appconf_missing_name = @appconf_string.reject {|x| x == :name}
10
- @appconf_missing_format = @appconf_string.reject {|x| x == :format}
11
- @appconf_missing_body = @appconf_string.reject {|x| x == :body}
12
- @appconf_missing_application = @appconf_string.reject {|x| x == :application_id}
13
- end
14
4
  before(:each) do
15
5
  Ohm.redis.flushdb
6
+ app = Noah::Application.create :name => "my_application"
7
+ @appconf_string = {:name => "mystringconf", :format => "string", :body => "some_var", :application_id => app.id}
8
+ @appconf_json = {:name => "myjsonconf", :format => "json", :body => @appconf_string.to_json, :application_id => app.id}
9
+ @appconf_missing_name = @appconf_string.reject {|k, v| k == :name}
10
+ @appconf_missing_format = @appconf_string.reject {|k, v| k == :format}
11
+ @appconf_missing_body = @appconf_string.reject {|k, v| k == :body}
12
+ @appconf_missing_application = @appconf_string.reject {|k, v| k == :application_id}
16
13
  end
17
14
  after(:each) do
18
15
  Ohm.redis.flushdb
@@ -3,8 +3,8 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "Using the Ephemeral Model", :reset_redis => true do
4
4
  before(:all) do
5
5
  @edata = {:path => "/foo/bar/baz", :data => "some_value"}
6
- @emissing_path = @edata.reject {|x| x == :path}
7
- @emissing_data = @edata.reject {|x| x == :data}
6
+ @emissing_path = @edata.reject {|k, v| k == :path}
7
+ @emissing_data = @edata.reject {|k, v| k == :data}
8
8
  @good_ephemeral = Noah::Ephemeral.new(@edata)
9
9
  @missing_path = Noah::Ephemeral.new(@emissing_path)
10
10
  @missing_data = Noah::Ephemeral.new(@emissing_data)
@@ -28,15 +28,15 @@ describe "Using the Ephemeral Model", :reset_redis => true do
28
28
  b = Noah::Ephemeral[@missing_data.id]
29
29
  b.should == @missing_data
30
30
  end
31
- # it "update an existing Noah::Ephemeral" do
32
- # @good_ephemeral.save
33
- # Noah::Ephemeral.all.size.should == 1
34
- # c = Noah::Ephemeral[@good_ephemeral.id]
35
- # c.data = "updated_data"
36
- # c.save
37
- # sleep(2)
38
- # c.is_new?.should == false
39
- # end
31
+ it "update an existing Noah::Ephemeral" do
32
+ e = Noah::Ephemeral.create :path => "/is/new/test"
33
+ Noah::Ephemeral.all.size.should == 1
34
+ sleep(2)
35
+ c = Noah::Ephemeral[e.id]
36
+ c.data = "updated_data"
37
+ c.save
38
+ c.is_new?.should == false
39
+ end
40
40
  it "delete an existing Noah::Ephemeral" do
41
41
  @good_ephemeral.save
42
42
  @good_ephemeral.delete
@@ -45,8 +45,15 @@ describe "Using the Ephemeral Model", :reset_redis => true do
45
45
  end
46
46
  describe "should not" do
47
47
  it "create a new Noah::Ephemeral with missing path" do
48
- @missing_path.valid?.should == false
49
- @missing_path.errors.should == [[:path, :not_present]]
48
+ e = Noah::Ephemeral.create
49
+ e.valid?.should == false
50
+ e.errors.should == [[:path, :not_present]]
51
+ end
52
+ it "create a duplicate Noah::Ephemeral" do
53
+ e = Noah::Ephemeral.create :path => "/random/path"
54
+ f = Noah::Ephemeral.create :path => "/random/path"
55
+ f.valid?.should == false
56
+ f.errors.should == [[:path, :not_unique]]
50
57
  end
51
58
  end
52
59
  end
@@ -34,8 +34,8 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
34
34
  response = YAML.load(last_response.body)
35
35
  response.is_a?(Hash).should == true
36
36
  response.keys.should == ["development"]
37
- response["development"].keys.should == ["database", "adapter", "username", "password"]
38
- response["development"].values.should == ["development_database", "mysql", "dev_user", "dev_password"]
37
+ response["development"].keys.sort.should == ["adapter", "database", "password", "username"]
38
+ response["development"].values.sort.should == ["dev_password", "dev_user", "development_database", "mysql"]
39
39
  end
40
40
  it "invalid application should not work" do
41
41
  get '/c/badapp'
@@ -0,0 +1,115 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Using the Ephemeral API", :reset_redis => true do
4
+ before(:each) do
5
+ Ohm.redis.flushdb
6
+ Noah::Ephemeral.create(:path => "/foo/bar/baz", :data => "value1")
7
+ Noah::Ephemeral.create(:path => "/baz/bar")
8
+ end
9
+ after(:each) do
10
+ Ohm.redis.flushdb
11
+ end
12
+ describe "calling" do
13
+
14
+ describe "GET" do
15
+ it "all ephemerals should return 404" do
16
+ get '/e'
17
+ last_response.should_not be_ok
18
+ last_response.status.should == 404
19
+ response = last_response.should return_json
20
+ response['error_message'].should == 'Resource not found'
21
+ response['result'].should == 'failure'
22
+ end
23
+
24
+ it "named path with data should work" do
25
+ get '/e/foo/bar/baz'
26
+ last_response.should be_ok
27
+ last_response.body.should == 'value1'
28
+ end
29
+
30
+ it "named path without data should work" do
31
+ get '/e/baz/bar'
32
+ last_response.status.should == 200
33
+ last_response.body.should == ""
34
+ end
35
+
36
+ it "invalid path should not work" do
37
+ get '/e/ssss/dddd'
38
+ last_response.should_not be_ok
39
+ last_response.status.should == 404
40
+ response = last_response.should return_json
41
+ response['error_message'].should == 'Resource not found'
42
+ response['result'].should == 'failure'
43
+ end
44
+ end
45
+
46
+ describe "PUT" do
47
+ it "new ephemeral with data should work" do
48
+ put '/e/whiz/bang/', 'value3'
49
+ last_response.should be_ok
50
+ response = last_response.should return_json
51
+ response['result'].should == 'success'
52
+ response['id'].nil?.should == false
53
+ response['path'].should == '/whiz/bang/'
54
+ response['data'].should == 'value3'
55
+ end
56
+
57
+ it "new ephemeral without data should work" do
58
+ put '/e/bang/whiz'
59
+ last_response.should be_ok
60
+ response = last_response.should return_json
61
+ response['result'].should == 'success'
62
+ response['action'].should == 'create'
63
+ response['id'].nil?.should == false
64
+ response['path'].should == '/bang/whiz'
65
+ response['data'].should == nil
66
+ end
67
+
68
+ it "existing ephemeral with data should work" do
69
+ Noah::Ephemeral.create(:path => '/new/ephemeral', :data => 'old_value')
70
+ get '/e/new/ephemeral'
71
+ last_response.should be_ok
72
+ last_response.body.should == 'old_value'
73
+ put '/e/new/ephemeral', 'new_value'
74
+ last_response.should be_ok
75
+ get '/e/new/ephemeral'
76
+ last_response.should be_ok
77
+ last_response.body.should == 'new_value'
78
+ end
79
+ it "existing ephemeral without data should work" do
80
+ Noah::Ephemeral.create(:path => '/a/random/key')
81
+ get '/e/a/random/key'
82
+ last_response.should be_ok
83
+ last_response.body.should == ""
84
+ put '/e/a/random/key', 'a new value'
85
+ last_response.should be_ok
86
+ get '/e/a/random/key'
87
+ last_response.should be_ok
88
+ last_response.body.should == 'a new value'
89
+ end
90
+ end
91
+
92
+ describe "DELETE" do
93
+ it "existing path should work" do
94
+ e = Noah::Ephemeral.new(:path => '/slart/i/bart/fast', :data => 'someddata')
95
+ e.save
96
+ delete "/e/slart/i/bart/fast"
97
+ last_response.should be_ok
98
+ response = last_response.should return_json
99
+ response['result'].should == 'success'
100
+ response['action'].should == 'delete'
101
+ response['id'].should == e.id
102
+ response['path'].should == e.name
103
+ end
104
+
105
+ it "invalid path should not work" do
106
+ delete '/e/fork/spoon/knife'
107
+ last_response.should_not be_ok
108
+ last_response.status.should == 404
109
+ response = last_response.should return_json
110
+ response['error_message'].should == 'Resource not found'
111
+ response['result'].should == 'failure'
112
+ end
113
+ end
114
+ end
115
+ end
@@ -82,7 +82,7 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
82
82
  response = last_response.should return_json
83
83
 
84
84
  response["result"].should == "failure"
85
- response["error_message"].should == "[[:status, :not_member]]"
85
+ response["error_message"].should == "Status must be up, down or pending"
86
86
  end
87
87
  end
88
88
 
@@ -68,7 +68,7 @@ describe "Using the Service API", :reset_redis => false, :populate_sample_data =
68
68
  put "/s/foobar", {:name => "foobar", :status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
69
69
  last_response.should_not be_ok
70
70
  response = last_response.should return_json
71
- response["error_message"].should == "[[:status, :not_member]]"
71
+ response["error_message"].should == "Status must be up, down or pending"
72
72
  end
73
73
  it "new service with missing name should not work" do
74
74
  put "/s/foobar", {:status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
@@ -28,7 +28,96 @@ describe "Using the Watcher API", :reset_redis => true do
28
28
  response.is_a?(Array).should == true
29
29
  response.size.should == 4
30
30
  end
31
+
32
+ it "named watch should work" do
33
+ w = Noah::Watcher.create(:pattern => '//noah/application/myapp', :endpoint => 'http://localhost/webhook')
34
+ get "/w/#{w.name}"
35
+ last_response.should be_ok
36
+ response = last_response.should return_json
37
+ response['pattern'].should == w.pattern
38
+ response['endpoint'].should == w.endpoint
39
+ end
40
+
41
+ it "invalid watch should not work" do
42
+ get '/w/asdfasdfasdfasdfasdfsdf'
43
+ last_response.should be_missing
44
+ end
31
45
  end
32
46
 
47
+ describe "PUT" do
48
+ it "new watch should work" do
49
+ data = {:pattern => "//noah/application", :endpoint => "http://myendpoint/webhook"}
50
+ put '/w', data.to_json, "CONTENT_TYPE" => "application/json"
51
+ last_response.should be_ok
52
+ response = last_response.should return_json
53
+ response['pattern'].should == data[:pattern]
54
+ response['endpoint'].should == data[:endpoint]
55
+ w = Noah::Watcher.find(data).first
56
+ w.pattern.should == data[:pattern]
57
+ w.endpoint.should == data[:endpoint]
58
+ end
59
+
60
+ it "new watch without pattern should not work" do
61
+ data = {:endpoint => "http://myendpoint/webhook"}
62
+ put '/w', data.to_json, "CONTENT_TYPE" => "application/json"
63
+ last_response.should be_invalid
64
+ end
65
+
66
+ it "new watch without endpoint should not work" do
67
+ data = {:pattern => "//noah/application"}
68
+ put '/w', data.to_json, "CONTENT_TYPE" => "application/json"
69
+ last_response.should be_invalid
70
+ end
71
+
72
+ it "new watch that supercedes existing should not work" do
73
+ Noah::Watcher.create(:endpoint => 'http://myendpoint/webhook', :pattern => '//noah/application/foo')
74
+ data = {:endpoint => "http://myendpoint/webhook", :pattern => '//noah/application'}
75
+ put '/w', data.to_json, "CONTENT_TYPE" => "application/json"
76
+ last_response.should_not be_ok
77
+ response = last_response.should return_json
78
+ response['error_message'].should == 'Pattern would overwrite existing'
79
+ end
80
+
81
+ it "new watch that subsets an existing should not work" do
82
+ Noah::Watcher.create(:endpoint => 'http://myendpoint/webhook', :pattern => '//noah/application')
83
+ data = {:endpoint => "http://myendpoint/webhook", :pattern => '//noah/application/foo'}
84
+ put '/w', data.to_json, "CONTENT_TYPE" => "application/json"
85
+ last_response.should_not be_ok
86
+ response = last_response.should return_json
87
+ response['error_message'].should == 'Pattern is already provided'
88
+ end
89
+ end
90
+
91
+ describe "DELETE" do
92
+ it "delete an existing watch should work" do
93
+ data = {:endpoint => "http://myendpoint/webhookd", :pattern => '//noah/application/d'}
94
+ w = Noah::Watcher.create(data)
95
+ delete '/w', data.to_json, "CONTENT_TYPE" => "application/json"
96
+ last_response.should be_ok
97
+ response = last_response.should return_json
98
+ response['pattern'].should == data[:pattern]
99
+ response['endpoint'].should == data[:endpoint]
100
+ response['name'].should_not == "null"
101
+ Noah::Watcher.find(data).size.should == 0
102
+ end
103
+
104
+ it "delete an invalid watch should not work" do
105
+ data = {:endpoint => 'missing', :pattern => '//noah/application/dag'}
106
+ delete '/w', data.to_json, "CONTENT_TYPE" => "application/json"
107
+ last_response.should be_missing
108
+ end
109
+
110
+ it "delete without pattern should not work" do
111
+ data = {:endpoint => "invalid"}
112
+ delete '/w', data.to_json, "CONTENT_TYPE" => "application/json"
113
+ last_response.should be_invalid
114
+ end
115
+
116
+ it "delete without endpoint should not work" do
117
+ data = {:pattern => "//noah/invalid"}
118
+ delete '/w', data.to_json, "CONTENT_TYPE" => "application/json"
119
+ last_response.should be_invalid
120
+ end
121
+ end
33
122
  end
34
123
  end
data/spec/watcher_spec.rb CHANGED
@@ -32,30 +32,30 @@ describe "Using the Watcher Model", :reset_redis => true do
32
32
  it "create a new Noah::Watcher with missing endpoint" do
33
33
  a = Noah::Watcher.create(:pattern => "/foo/bar")
34
34
  a.valid?.should == false
35
- a.errors.to_s.should == "[[:endpoint, :not_present]]"
35
+ a.errors.should == [[:endpoint, :not_present]]
36
36
  end
37
37
  it "create a new Noah::Watcher with missing pattern" do
38
38
  a = Noah::Watcher.create(:endpoint => "http://localhost/webhook")
39
39
  a.valid?.should == false
40
- a.errors.to_s.should == "[[:pattern, :not_present]]"
40
+ a.errors.should == [[:pattern, :not_present]]
41
41
  end
42
42
  it "create a new Noah::Watcher with subset pattern" do
43
43
  a = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah/")
44
44
  b = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah/foobar")
45
45
  b.valid?.should == false
46
- b.errors.to_s.should == "[[:pattern, :already_provided]]"
46
+ b.errors.should == [[:pattern, :already_provided]]
47
47
  end
48
48
  it "create a new Noah::Watcher with superset pattern" do
49
49
  a = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah/foobar")
50
50
  b = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah")
51
51
  b.valid?.should == false
52
- b.errors.to_s.should == "[[:pattern, :replaces_existing]]"
52
+ b.errors.should == [[:pattern, :replaces_existing]]
53
53
  end
54
54
  it "create a duplicate Noah::Watcher" do
55
55
  a = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah/foobar")
56
56
  b = Noah::Watcher.create(:endpoint => "http://localhost.domain.com/webhook", :pattern => "//noah/foobar")
57
57
  b.valid?.should == false
58
- b.errors.to_s.should == "[[[:endpoint, :pattern], :not_unique]]"
58
+ b.errors.should == [[[:endpoint, :pattern], :not_unique]]
59
59
  end
60
60
  end
61
61
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: noah
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.9
5
+ version: "0.1"
6
6
  platform: ruby
7
7
  authors:
8
8
  - John E. Vincent
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-08 00:00:00 -05:00
13
+ date: 2011-03-11 00:00:00 -05:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -265,7 +265,6 @@ files:
265
265
  - lib/vendor/em-hiredis/Gemfile
266
266
  - lib/vendor/em-hiredis/README.md
267
267
  - lib/vendor/em-hiredis/Rakefile
268
- - lib/vendor/em-hiredis/em-hiredis-0.0.1.gem
269
268
  - lib/vendor/em-hiredis/em-hiredis.gemspec
270
269
  - lib/vendor/em-hiredis/lib/em-hiredis.rb
271
270
  - lib/vendor/em-hiredis/lib/em-hiredis/client.rb
@@ -279,6 +278,7 @@ files:
279
278
  - spec/host_spec.rb
280
279
  - spec/noahapp_application_spec.rb
281
280
  - spec/noahapp_configuration_spec.rb
281
+ - spec/noahapp_ephemeral_spec.rb
282
282
  - spec/noahapp_host_spec.rb
283
283
  - spec/noahapp_service_spec.rb
284
284
  - spec/noahapp_spec.rb
@@ -316,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
316
  requirements: []
317
317
 
318
318
  rubyforge_project: noah
319
- rubygems_version: 1.5.3
319
+ rubygems_version: 1.5.2
320
320
  signing_key:
321
321
  specification_version: 3
322
322
  summary: Application registry based on Apache Zookeeper