noah 0.8.5-jruby → 0.8.7-jruby

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ doc
16
16
  examples/log/*
17
17
  examples/tmp/*
18
18
  *.rbc
19
+ *.gem
@@ -0,0 +1,20 @@
1
+ # Noah Changelog
2
+
3
+ ## 0.8.6
4
+ - Issue #7 *Provide url for key-only enumeration*
5
+
6
+ - top-level configurations url now accepts `?short=true` to return shortened display of entries
7
+
8
+ - Issue #10 *noah-watcher daemon doesn't support REDIS_URL env*
9
+
10
+ - **BREAKING CHANGE** noah-watcher.rb renamed to noah-watcher
11
+ - noah-watcher now supports `-r redis://host:port/dbnum` to use alternate redis server
12
+ - noah-watcher now supports `-l logfile` for logging to file
13
+
14
+ ## 0.8.5
15
+ - Issue #9 *Ephemeral Tagging is broken*
16
+
17
+ - All tagging now moved from route files to Sinatra helper
18
+
19
+ # Historical
20
+ This changelog started being maintained at 0.8.5. Previous changes can be viewed in the commit history.
data/README.md CHANGED
@@ -1,13 +1,43 @@
1
1
  # Noah
2
2
  _"look at this effing rainbow I just made for you"_
3
3
 
4
- Noah is an application registry loosely based on [Apache ZooKeeper](http://zookeeper.apache.org)
4
+ Noah is an application registry inspired by [Apache ZooKeeper](http://zookeeper.apache.org)
5
5
 
6
6
  What does that mean? From the ZooKeeper Home Page:
7
7
 
8
8
  > ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications.
9
9
 
10
- Essentially Noah, is a port of those concepts into a stateless RESTful application.
10
+ Essentially Noah is a port of parts of that functionality into a stateless RESTish application.
11
+
12
+ ## Some background
13
+ It's probably worth reading the following blog posts before going any further to clear up any possible misunderstandings.
14
+ Noah is not a direct replacement for ZK. It's a conceptual port. More than anything, it was an itch I needed to scratch:
15
+
16
+ - [On Noah - Part 1](http://blog.lusis.org/blog/2011/05/16/on-noah-part-1/)
17
+ - [On Noah - Part 2](http://blog.lusis.org/blog/2011/05/17/on-noah-part-2/)
18
+ - [On Noah - Part 3](http://blog.lusis.org/blog/2011/05/18/on-noah-part-3/)
19
+ - [On Noah - Part 4](http://blog.lusis.org/blog/2011/05/20/on-noah-part-4/)
20
+
21
+ Also the following post was where I sort of discussed it early on:
22
+
23
+ - [Ad-hoc configuration and Coordination](http://lusislog.blogspot.com/2011/03/ad-hoc-configuration-coordination-and.html)
24
+
25
+ ## Things Noah does not do
26
+
27
+ - Paxos, ZAB or any other sort of consensus protocol
28
+ - Noah itself is not distributed (yet).
29
+ - ACLs (yet)
30
+ - Leader election of any kind
31
+
32
+ ## Things Noah can do
33
+ _note that these terms are fairly overloaded depending on who you talk to_
34
+
35
+ - Service registry
36
+ - Node registry
37
+ - Configuration Registry
38
+ - Group Services
39
+ - Watches (albeit differently)
40
+
11
41
 
12
42
  ## Quick Start
13
43
  The quickstart guide has been moved to the wiki:
@@ -68,4 +98,4 @@ Here are a list of some key [wiki](https://github.com/lusis/Noah/wiki) pages:
68
98
  * [Watchers and Callbacks](https://github.com/lusis/Noah/wiki/Watchers-and-Callbacks)
69
99
  The general idea behind how Noah would implement watches
70
100
  * [Watcher/Callback Examples](https://github.com/lusis/Noah/blob/master/examples/README.md)
71
- Some example callbacks.
101
+ Some example callbacks.
data/bin/noah CHANGED
@@ -6,4 +6,5 @@ require 'vegas'
6
6
 
7
7
  Vegas::Runner.new(Noah::App, 'noah') do |runner, opts, app|
8
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 }
9
+ opts.on("--esize SIZE", Integer, "Max allowed ephemeral size in bytes") {|esize| Noah::App.set :ephemeral_size, esize }
9
10
  end
@@ -8,10 +8,9 @@ Apparently we could not connect to the redis instance.
8
8
  By default the watcher will attempt to connect to "redis://localhost:6379/0"
9
9
  If your redis instance is listening elsewhere, please start like so:
10
10
 
11
- REDIS_URL="redis://hostname:port/dbnum" noah-watcher.rb
12
-
13
- This will be rectified in a future release. Sorry about that.
11
+ noah-watcher.rb -r redis://hostname:port/dbnum
14
12
  ----------------------------------------------------------------------------
13
+
15
14
  EOC
16
15
 
17
16
  HELP = <<-EOH
@@ -27,6 +26,8 @@ require 'json'
27
26
 
28
27
  opts = Slop.parse do
29
28
  banner "Usage: noah-watcher.rb [options]"
29
+ on :r, :redis_url, 'Redis URL to use. This MUST match what the Noah server is using for now', :default => 'redis://localhost:6379/0', :argument => true
30
+ on :o, :output, 'Log destination - full file path. Default is STDOUT', :default => STDOUT, :argument => true
30
31
  on '--depinstall', "Installs additional dependencies" do
31
32
  puts "Installing dependencies"
32
33
  puts "em-hiredis..."
@@ -54,6 +55,8 @@ rescue LoadError => e
54
55
  exit
55
56
  end
56
57
 
58
+ ENV['REDIS_URL'] = opts[:redis_url]
59
+
57
60
  begin
58
61
  require 'noah'
59
62
  require 'noah/agent'
@@ -62,7 +65,7 @@ rescue Errno::ECONNREFUSED
62
65
  exit
63
66
  end
64
67
 
65
- Noah::Log.logger = Logger.new(STDOUT)
68
+ Noah::Log.logger = Logger.new(opts[:output])
66
69
  LOGGER = Noah::Log.logger
67
70
  LOGGER.progname = __FILE__
68
71
 
@@ -78,10 +81,10 @@ EventMachine.run do
78
81
  r = EventMachine::Hiredis.connect(ENV["REDIS_URL"])
79
82
  r.errback{|x| LOGGER.error("Unable to connect to redis: #{x}")}
80
83
  LOGGER.info("Attaching to Redis Pubsub")
81
- r.psubscribe("*")
82
- r.on(:pmessage) do |pattern, event, message|
84
+ proc = Proc.new{ |event, message|
83
85
  noah.reread_watchers if event =~ /^\/\/noah\/watchers\/.*/
84
86
  noah.broker("#{event}|#{message}") unless noah.watchers == 0
85
- end
87
+ }
88
+ r.pubsub.psubscribe("*", proc)
86
89
 
87
90
  end
@@ -5,7 +5,7 @@ require 'em-http-request'
5
5
 
6
6
  class HttpPostWatch < Noah::CustomWatcher
7
7
  redis_host "redis://127.0.0.1:6379/0"
8
- pattern "//noah/configuration/redis_server"
8
+ pattern "//noah/configurations/redis_server"
9
9
  destination Proc.new {|x| ::EM::HttpRequest.new('http://localhost:4567/webhook', :connection_timeout => 2, :inactivity_timeout => 4).post :body => x}
10
10
  run!
11
11
  end
@@ -9,7 +9,7 @@ set :noah_client_name, 'my_sinatra_app'
9
9
 
10
10
  def get_config_from_noah(setting)
11
11
  begin
12
- c = open("#{settings.noah_server}/c/#{settings.noah_client_name}/#{setting}").read
12
+ c = open("#{settings.noah_server}/applications/#{settings.noah_client_name}/configurations/#{setting}").read
13
13
  set setting.to_sym, c
14
14
  end
15
15
  end
@@ -17,7 +17,7 @@ end
17
17
  get_config_from_noah('redis_server')
18
18
 
19
19
  def get_redis_version
20
- Ohm.connect :url => settings.redis_server
20
+ Ohm.connect :url => settings.redis_server['body']
21
21
  Ohm.redis.info["redis_version"]
22
22
  end
23
23
 
@@ -25,9 +25,10 @@ get "/" do
25
25
  "Redis version: #{get_redis_version}"
26
26
  end
27
27
 
28
- put "/webhook" do
28
+ post "/webhook" do
29
29
  data = JSON.parse(request.body.read)
30
- settings.redis_server = data["body"]
30
+ settings.redis_server = data
31
+ puts data["body"]
31
32
  resp = {:message => "reconfigured", :setting => data["name"], :body => data["body"]}.to_json
32
33
  "#{resp}"
33
34
  end
@@ -16,6 +16,8 @@ module Noah
16
16
  set :show_exceptions, false
17
17
  set :run, false
18
18
  set :redis_url, ENV['REDIS_URL'] || 'redis://localhost:6379/0'
19
+ set :ephemeral_size, ENV['NOAH_ESIZE'] || 512
20
+ disable :protection
19
21
  end
20
22
 
21
23
  configure(:development) do
@@ -43,12 +45,21 @@ module Noah
43
45
  end
44
46
 
45
47
  # Displays an overview page of all registered objects
46
- get '/' do
48
+ get '/', :provides => :html do
47
49
  content_type "text/html"
48
-
49
50
  haml :index, :format => :html5, :locals => {:redis_version => Ohm.redis.info["redis_version"].to_s, :noah_version => Noah::VERSION}
50
51
  end
51
52
 
53
+ get '/', :provides => :json do
54
+ content_type "application/json"
55
+ erb :'index.json', :locals => {:redis_version => Ohm.redis.info["redis_version"].to_s, :noah_version => Noah::VERSION}
56
+ end
57
+
58
+ get '/version', :provides => :json do
59
+ content_type "application/json"
60
+ {:redis_version => Ohm.redis.info["redis_version"].to_s, :noah_version => Noah::VERSION}.to_json
61
+ end
62
+
52
63
  not_found do
53
64
  content_type "application/json"
54
65
  erb :'404'
@@ -88,8 +88,11 @@ module Noah
88
88
  self.name.nil? ? name=@deleted_name : name=self.name
89
89
  # Pulling out dbnum for now. Need to rethink it
90
90
  #pub_category = "#{db}:noah.#{self.class.to_s}[#{name}].#{meth}"
91
+ # TODO
92
+ # Add a url in the message body containing the URL to the item
93
+ url = "/#{self.class_to_lower}s/#{name}"
91
94
  pub_category = "#{self.patternize_me}"
92
- Ohm.redis.publish(pub_category, self.to_hash.merge({"action" => meth, "pubcategory" => pub_category}).to_json)
95
+ Ohm.redis.publish(pub_category, self.to_hash.merge({"action" => meth, "pubcategory" => pub_category, "path" => url}).to_json)
93
96
 
94
97
  # The following provides a post post-action hook. It allows a class to provide it's own handling after the fact
95
98
  # good example is in [Noah::Ephemeral] where it's used to check for/clean up expired ephemeral nodes entries
@@ -31,7 +31,7 @@ module Noah
31
31
  if obj.valid?
32
32
  obj.save
33
33
  end
34
- obj
34
+ obj if obj.valid?
35
35
  rescue Exception => e
36
36
  e.message
37
37
  end
@@ -62,10 +62,25 @@ module Noah
62
62
  end
63
63
 
64
64
  class Configurations
65
- def self.all(options = {})
65
+ def self.all(options = {}, short=false)
66
+ short_keys = [:format, :created_at, :updated_at]
66
67
  config_hash = Hash.new
67
68
  options.empty? ? configs=Configuration.all.sort : configs=Configuration.find(options).sort
68
- configs.each {|x| config_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
69
+ if short == false
70
+ configs.each {|x| config_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
71
+ else
72
+ configs.each do |x|
73
+ items = x.to_hash.select {|k,v| k if short_keys.include?(k)}
74
+ # 1.8 fix for Hash#select
75
+ if items.is_a?(Array)
76
+ items_hash = {}
77
+ items.each {|item| items_hash.merge!(Hash[*item])}
78
+ else
79
+ items_hash = items
80
+ end
81
+ config_hash["#{x.name}"] = items_hash
82
+ end
83
+ end
69
84
  config_hash
70
85
  end
71
86
  end
@@ -47,7 +47,7 @@ class Noah::App
47
47
  end
48
48
  if app.valid?
49
49
  action = app.is_new? ? "create" : "update"
50
- app.save
50
+ #app.save
51
51
  r = {"result" => "success","id" => app.id, "action" => action, "name" => app.name }
52
52
  r.to_json
53
53
  else
@@ -13,16 +13,23 @@ class Noah::App
13
13
  get '/configurations/:configname/?' do |configname|
14
14
  c = Noah::Configuration.find(:name => configname).first
15
15
  (halt 404) if c.nil?
16
+ #content_type c.format.to_sym
16
17
  content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym]
17
- #response.headers['Content-Disposition'] = "attachment; filename=#{configname}"
18
- c.body
18
+ c.body.to_s
19
19
  end
20
+
20
21
  # GET all configurations
21
22
  get '/configurations/?' do
22
- configs = Noah::Configurations.all.to_hash
23
+ params[:short] ||= false
24
+ configs = Noah::Configurations.all({},params[:short])
23
25
  (halt 404) if configs.size == 0
26
+ configs.each do |config, values|
27
+ u = request.url.gsub(/(\/\?short=true|\?short=true)/,'/'+config)
28
+ values.merge!({:location=>u}) if params[:short]
29
+ end
24
30
  configs.to_json
25
31
  end
32
+
26
33
  # Add configuration object to a custom link hierarchy
27
34
  put '/configurations/:configname/link' do |configname|
28
35
  required_params = ["link_name"]
@@ -19,7 +19,7 @@ class Noah::App
19
19
  end
20
20
 
21
21
  put '/ephemerals/*' do
22
- raise("Data too large") if request.body.size > 512
22
+ raise("Data too large") if request.body.size > settings.ephemeral_size
23
23
  d = request.body.read || nil
24
24
  opts = {:path => "/#{params[:splat][0]}", :data => d}
25
25
  e = Noah::Ephemeral.find_or_create(opts)
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.8.5"
2
+ VERSION = "0.8.7"
3
3
  end
@@ -21,36 +21,37 @@ Gem::Specification.new do |s|
21
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
22
  s.require_paths = ["lib"]
23
23
 
24
- s.add_dependency("eventmachine", ["1.0.0.beta.3"])
25
- s.add_dependency("em-http-request", ["1.0.0.beta.4"])
26
- s.add_dependency("redis", ["= 2.2.0"])
27
- s.add_dependency("nest", ["= 1.1.0"])
28
- s.add_dependency("rack", ["= 1.2.2"])
29
- s.add_dependency("tilt", ["= 1.2.2"])
30
- s.add_dependency("sinatra", ["= 1.2.3"])
31
- s.add_dependency("ohm", ["= 0.1.3"])
32
- s.add_dependency("ohm-contrib", ["= 0.1.1"])
33
- s.add_dependency("haml", ["= 3.0.25"])
34
- s.add_dependency("vegas", ["= 0.1.8"])
35
- s.add_dependency("guid", ["= 0.1.1"])
36
- s.add_dependency("slop", ["= 2.1.0"])
24
+ s.add_dependency("eventmachine", "1.0.0.beta.4")
25
+ s.add_dependency("em-http-request", "1.0.0.beta.4")
26
+ s.add_dependency("cookiejar")
27
+ s.add_dependency("redis", "~> 2.2")
28
+ s.add_dependency("nest", "= 1.1.0")
29
+ s.add_dependency("rack", "~> 1.4")
30
+ s.add_dependency("tilt", "~> 1.3")
31
+ s.add_dependency("sinatra", "~> 1.3")
32
+ s.add_dependency("rack-protection", "~> 1.2")
33
+ s.add_dependency("ohm", "= 0.1.3")
34
+ s.add_dependency("ohm-contrib", "= 0.1.1")
35
+ s.add_dependency("haml", "= 3.0.25")
36
+ s.add_dependency("vegas", "= 0.1.8")
37
+ s.add_dependency("guid", "= 0.1.1")
38
+ s.add_dependency("slop", "= 2.1.0")
39
+ s.add_dependency("hiredis", "0.4.5")
40
+ s.add_dependency("cs-em-hiredis", "0.1.2")
37
41
 
38
42
 
39
43
  if RUBY_PLATFORM =~ /java/
40
44
  s.add_dependency("jruby-openssl")
41
45
  s.add_dependency("json")
42
- s.add_development_dependency("warbler", ["= 1.2.1"])
46
+ s.add_development_dependency("warbler", "= 1.2.1")
43
47
  else
44
- s.add_dependency("hiredis", ["= 0.3.1"])
45
48
  s.add_dependency("yajl-ruby")
46
- s.add_dependency("SystemTimer") if RUBY_VERSION =~ /1.8/
47
49
  s.add_dependency("thin")
48
50
  end
49
51
 
50
- s.add_development_dependency("diff-lcs", ["= 1.1.2"])
51
- s.add_development_dependency("sinatra-reloader", ["= 0.5.0"])
52
- s.add_development_dependency("rspec", ["~> 2.5"])
53
- # s.add_development_dependency("rcov", ["= 0.9.9"])
54
- s.add_development_dependency("rack-test", ["= 0.5.7"])
55
- s.add_development_dependency("rake", ["= 0.8.7"])
52
+ s.add_development_dependency("diff-lcs", "= 1.1.2")
53
+ s.add_development_dependency("sinatra-reloader", "= 0.5.0")
54
+ s.add_development_dependency("rspec", "~> 2.5")
55
+ s.add_development_dependency("rack-test", "= 0.6.1")
56
+ s.add_development_dependency("rake", "= 0.8.7")
56
57
  end
@@ -65,8 +65,19 @@ describe "Using the Configuration Model", :reset_redis => true do
65
65
  c = Noah::Configurations.all
66
66
  c.class.to_s.should == 'Hash'
67
67
  c.size.should == 2
68
- c.has_key?(a.name).should == true
69
- c.has_key?(b.name).should == true
68
+ c.has_key?(a.name.to_s).should == true
69
+ c.has_key?(b.name.to_s).should == true
70
+ end
71
+
72
+ it "return all Configurations in short form" do
73
+ a = Noah::Configuration.find_or_create(@appconf_string)
74
+ b = Noah::Configuration.find_or_create(@appconf_json)
75
+ c = Noah::Configurations.all({},true)
76
+ c.class.to_s.should == 'Hash'
77
+ c.size.should == 2
78
+ c.has_key?(a.name.to_s).should == true
79
+ c.has_key?(b.name.to_s).should == true
80
+ c.each {|k,v| v.keys.map {|k| k.to_s}.sort.should == ['created_at','format','updated_at']}
70
81
  end
71
82
  end
72
83
 
@@ -58,16 +58,16 @@ describe "Using the Link Model", :reset_redis => true do
58
58
  h[:name].should == l.name
59
59
  h[:updated_at].should == l.updated_at
60
60
  h[:created_at].should == l.created_at
61
- h[:hosts].has_key?(@host.name).should == true
62
- h[:hosts][@host.name].keys.map {|k| k.to_s}.sort.should == [:id, :status, :tags, :services].map {|k| k.to_s}.sort
63
- h[:services].has_key?(@service.name).should == true
64
- h[:services][@service.name][@host.name].keys.map {|k| k.to_s}.sort.should == [:id, :status, :tags].map {|k| k.to_s}.sort
65
- h[:applications].has_key?(@application.name).should == true
66
- h[:applications][@application.name].keys.map {|k| k.to_s}.sort.should == [:id, :tags, :configurations].map {|k| k.to_s}.sort
67
- h[:configurations].has_key?(@configuration.name).should == true
68
- h[:configurations][@configuration.name].keys.map {|k| k.to_s }.sort.should == [:id, :tags, :format, :body].map {|k| k.to_s}.sort
69
- h[:ephemerals].has_key?(@ephemeral.name).should == true
70
- h[:ephemerals][@ephemeral.name].keys.map {|k| k.to_s}.sort.should == [:id, :tags, :path, :data].map {|k| k.to_s}.sort
61
+ h[:hosts].has_key?(@host.name.to_s).should == true
62
+ h[:hosts]["#{@host.name}"].keys.map {|k| k.to_s}.sort.should == [:id, :status, :tags, :services].map {|k| k.to_s}.sort
63
+ h[:services].has_key?(@service.name.to_s).should == true
64
+ h[:services]["#{@service.name}"]["#{@host.name}"].keys.map {|k| k.to_s}.sort.should == [:id, :status, :tags].map {|k| k.to_s}.sort
65
+ h[:applications].has_key?(@application.name.to_s).should == true
66
+ h[:applications]["#{@application.name}"].keys.map {|k| k.to_s}.sort.should == [:id, :tags, :configurations].map {|k| k.to_s}.sort
67
+ h[:configurations].has_key?(@configuration.name.to_s).should == true
68
+ h[:configurations]["#{@configuration.name}"].keys.map {|k| k.to_s }.sort.should == [:id, :tags, :format, :body].map {|k| k.to_s}.sort
69
+ h[:ephemerals].has_key?(@ephemeral.name.to_s).should == true
70
+ h[:ephemerals]["#{@ephemeral.name}"].keys.map {|k| k.to_s}.sort.should == [:id, :tags, :path, :data].map {|k| k.to_s}.sort
71
71
 
72
72
  end
73
73
  end
@@ -27,7 +27,7 @@ describe "Using the Application API", :reset_redis => false do
27
27
  response["name"].should == @a.name
28
28
  response.has_key?("configurations").should == true
29
29
  c = response["configurations"]
30
- c.has_key?(@c.name).should == true
30
+ c.has_key?(@c.name.to_s).should == true
31
31
  c["#{@c.name}"]["format"].should == "#{@c.format}"
32
32
  c["#{@c.name}"]["body"].should == "#{@c.body}"
33
33
  end
@@ -41,6 +41,35 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
41
41
  end
42
42
  end
43
43
  end
44
+
45
+ it "all configurations in short form with no trailing slash" do
46
+ get '/configurations?short=true'
47
+ last_response.should be_ok
48
+ response = last_response.should return_json
49
+ response.keys.size.should == 3
50
+ %w[redis_url json_config yaml_config].each do |c|
51
+ response.keys.member?(c).should == true
52
+ %w[format location created_at updated_at].each do |ck|
53
+ response[c].keys.member?(ck).should == true
54
+ end
55
+ end
56
+ response.each {|k,v| v['location'].should =~ /^http:\/\/.*\/configurations\/#{k}/}
57
+ end
58
+
59
+ it "all configurations in short form with trailing slash" do
60
+ get '/configurations/?short=true'
61
+ last_response.should be_ok
62
+ response = last_response.should return_json
63
+ response.keys.size.should == 3
64
+ %w[redis_url json_config yaml_config].each do |c|
65
+ response.keys.member?(c).should == true
66
+ %w[format location created_at updated_at].each do |ck|
67
+ response[c].keys.member?(ck).should == true
68
+ end
69
+ end
70
+ response.each {|k,v| v['location'].should =~ /^http:\/\/.*\/configurations\/#{k}/}
71
+ end
72
+
44
73
  it "named configuration should work as JSON" do
45
74
  header "Accept", "application/json"
46
75
  get '/configurations/redis_url'
@@ -22,13 +22,13 @@ describe "Using the Service API", :reset_redis => false, :populate_sample_data =
22
22
  get "/services/#{@sample_service[:name]}"
23
23
  last_response.should be_ok
24
24
  response = last_response.should return_json
25
- response.is_a?(Hash).should == true
26
- response.has_key?(@s.name).should == true
27
- response[@s.name].is_a?(Hash).should == true
28
- response[@s.name].has_key?(@h.name).should == true
29
- response[@s.name][@h.name].is_a?(Hash).should == true
30
- response[@s.name][@h.name]["id"].should == @s.id
31
- response[@s.name][@h.name]["status"].should == @s.status
25
+ response.class.to_s.should == "Hash"
26
+ response.has_key?(@s.name.to_s).should == true
27
+ response["#{@s.name}"].class.to_s.should == "Hash"
28
+ response["#{@s.name}"].has_key?(@h.name.to_s).should == true
29
+ response["#{@s.name}"]["#{@h.name}"].class.to_s.should == "Hash"
30
+ response["#{@s.name}"]["#{@h.name}"]["id"].should == @s.id
31
+ response["#{@s.name}"]["#{@h.name}"]["status"].should == @s.status
32
32
  end
33
33
  it "named service for host should work" do
34
34
  get "/services/#{@sample_service[:name]}/#{@sample_host[:name]}"
@@ -2,16 +2,27 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Noah App Basics", :reset_redis => true do
4
4
 
5
- it "should show the index page" do
5
+ it "should show the index page as html" do
6
+ header "Accept", "text/html"
6
7
  get '/'
7
8
  last_response.should be_ok
8
9
  last_response.body.include?("Noah Start Page").should == true
9
10
  end
10
11
 
12
+ it "should show the index page as json" do
13
+ header "Accept", "application/json"
14
+ get '/'
15
+ last_response.should return_json
16
+ response = JSON.parse(last_response.body)
17
+ response.has_key?("redis_version").should == true
18
+ response.has_key?("noah_version").should == true
19
+ response.has_key?("resources").should == true
20
+ end
21
+
11
22
  it "should test the 404 message" do
12
23
  get '/foo'
13
24
  last_response.status.should == 404
14
- last_response.headers["Content-Type"].should == "application/json"
25
+ last_response.should return_json
15
26
  response = JSON.parse(last_response.body)
16
27
  response["result"].should == "failure"
17
28
  response["error_message"].should == "Resource not found"
@@ -72,7 +72,7 @@ end
72
72
 
73
73
  RSpec::Matchers.define :return_json do
74
74
  match do |last_response|
75
- last_response.headers["Content-Type"].should == "application/json"
75
+ last_response.headers["Content-Type"].should =~ /^application\/json;.*/
76
76
  response = JSON.parse(last_response.body)
77
77
  end
78
78
 
@@ -83,7 +83,7 @@ end
83
83
 
84
84
  RSpec::Matchers.define :be_missing do
85
85
  match do |last_response|
86
- last_response.headers["Content-Type"].should == "application/json"
86
+ last_response.headers["Content-Type"].should =~ /^application\/json;.*/
87
87
  last_response.status.should == 404
88
88
  response = JSON.parse(last_response.body)
89
89
  response["result"].should == "failure"
@@ -93,7 +93,7 @@ end
93
93
 
94
94
  RSpec::Matchers.define :be_invalid do
95
95
  match do |last_response|
96
- last_response.headers["Content-Type"].should == "application/json"
96
+ last_response.headers["Content-Type"].should =~ /^application\/json;.*/
97
97
  response = JSON.parse(last_response.body)
98
98
  response["result"].should == "failure"
99
99
  response["error_message"].should == "Missing Parameters"
@@ -0,0 +1,10 @@
1
+ {
2
+ "redis_version":"<%= locals[:redis_version] %>",
3
+ "noah_version":"<%= locals[:noah_version] %>",
4
+ "resources":{
5
+ "hosts":{"link":"<%= request.url %>hosts"},
6
+ "services":{"link":"<%= request.url %>services"},
7
+ "applications":{"link":"<%= request.url %>applications"},
8
+ "configurations":{"link":"<%= request.url %>configurations"}
9
+ }
10
+ }
metadata CHANGED
@@ -1,263 +1,304 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: noah
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.8.5
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.8.7
6
6
  platform: jruby
7
- authors:
7
+ authors:
8
8
  - John E. Vincent
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-08-05 00:00:00 -04:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
12
+ date: 2012-05-09 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
17
15
  name: eventmachine
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ version_requirements: &2056 !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - =
19
+ - !ruby/object:Gem::Version
20
+ version: 1.0.0.beta.4
20
21
  none: false
21
- requirements:
22
- - - "="
23
- - !ruby/object:Gem::Version
24
- version: 1.0.0.beta.3
22
+ requirement: *2056
23
+ prerelease: false
25
24
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
25
+ - !ruby/object:Gem::Dependency
28
26
  name: em-http-request
27
+ version_requirements: &2074 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - =
30
+ - !ruby/object:Gem::Version
31
+ version: 1.0.0.beta.4
32
+ none: false
33
+ requirement: *2074
29
34
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
35
+ type: :runtime
36
+ - !ruby/object:Gem::Dependency
37
+ name: cookiejar
38
+ version_requirements: &2090 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
31
43
  none: false
32
- requirements:
33
- - - "="
34
- - !ruby/object:Gem::Version
35
- version: 1.0.0.beta.4
44
+ requirement: *2090
45
+ prerelease: false
36
46
  type: :runtime
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
47
+ - !ruby/object:Gem::Dependency
39
48
  name: redis
40
- prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
49
+ version_requirements: &2106 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.2'
42
54
  none: false
43
- requirements:
44
- - - "="
45
- - !ruby/object:Gem::Version
46
- version: 2.2.0
55
+ requirement: *2106
56
+ prerelease: false
47
57
  type: :runtime
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
58
+ - !ruby/object:Gem::Dependency
50
59
  name: nest
51
- prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
53
- none: false
54
- requirements:
55
- - - "="
56
- - !ruby/object:Gem::Version
60
+ version_requirements: &2122 !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - =
63
+ - !ruby/object:Gem::Version
57
64
  version: 1.1.0
65
+ none: false
66
+ requirement: *2122
67
+ prerelease: false
58
68
  type: :runtime
59
- version_requirements: *id004
60
- - !ruby/object:Gem::Dependency
69
+ - !ruby/object:Gem::Dependency
61
70
  name: rack
62
- prerelease: false
63
- requirement: &id005 !ruby/object:Gem::Requirement
71
+ version_requirements: &2138 !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.4'
64
76
  none: false
65
- requirements:
66
- - - "="
67
- - !ruby/object:Gem::Version
68
- version: 1.2.2
77
+ requirement: *2138
78
+ prerelease: false
69
79
  type: :runtime
70
- version_requirements: *id005
71
- - !ruby/object:Gem::Dependency
80
+ - !ruby/object:Gem::Dependency
72
81
  name: tilt
73
- prerelease: false
74
- requirement: &id006 !ruby/object:Gem::Requirement
82
+ version_requirements: &2154 !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: '1.3'
75
87
  none: false
76
- requirements:
77
- - - "="
78
- - !ruby/object:Gem::Version
79
- version: 1.2.2
88
+ requirement: *2154
89
+ prerelease: false
80
90
  type: :runtime
81
- version_requirements: *id006
82
- - !ruby/object:Gem::Dependency
91
+ - !ruby/object:Gem::Dependency
83
92
  name: sinatra
93
+ version_requirements: &2170 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ~>
96
+ - !ruby/object:Gem::Version
97
+ version: '1.3'
98
+ none: false
99
+ requirement: *2170
84
100
  prerelease: false
85
- requirement: &id007 !ruby/object:Gem::Requirement
101
+ type: :runtime
102
+ - !ruby/object:Gem::Dependency
103
+ name: rack-protection
104
+ version_requirements: &2186 !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ~>
107
+ - !ruby/object:Gem::Version
108
+ version: '1.2'
86
109
  none: false
87
- requirements:
88
- - - "="
89
- - !ruby/object:Gem::Version
90
- version: 1.2.3
110
+ requirement: *2186
111
+ prerelease: false
91
112
  type: :runtime
92
- version_requirements: *id007
93
- - !ruby/object:Gem::Dependency
113
+ - !ruby/object:Gem::Dependency
94
114
  name: ohm
95
- prerelease: false
96
- requirement: &id008 !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - "="
100
- - !ruby/object:Gem::Version
115
+ version_requirements: &2202 !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - =
118
+ - !ruby/object:Gem::Version
101
119
  version: 0.1.3
120
+ none: false
121
+ requirement: *2202
122
+ prerelease: false
102
123
  type: :runtime
103
- version_requirements: *id008
104
- - !ruby/object:Gem::Dependency
124
+ - !ruby/object:Gem::Dependency
105
125
  name: ohm-contrib
106
- prerelease: false
107
- requirement: &id009 !ruby/object:Gem::Requirement
108
- none: false
109
- requirements:
110
- - - "="
111
- - !ruby/object:Gem::Version
126
+ version_requirements: &2218 !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - =
129
+ - !ruby/object:Gem::Version
112
130
  version: 0.1.1
131
+ none: false
132
+ requirement: *2218
133
+ prerelease: false
113
134
  type: :runtime
114
- version_requirements: *id009
115
- - !ruby/object:Gem::Dependency
135
+ - !ruby/object:Gem::Dependency
116
136
  name: haml
117
- prerelease: false
118
- requirement: &id010 !ruby/object:Gem::Requirement
119
- none: false
120
- requirements:
121
- - - "="
122
- - !ruby/object:Gem::Version
137
+ version_requirements: &2234 !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - =
140
+ - !ruby/object:Gem::Version
123
141
  version: 3.0.25
142
+ none: false
143
+ requirement: *2234
144
+ prerelease: false
124
145
  type: :runtime
125
- version_requirements: *id010
126
- - !ruby/object:Gem::Dependency
146
+ - !ruby/object:Gem::Dependency
127
147
  name: vegas
128
- prerelease: false
129
- requirement: &id011 !ruby/object:Gem::Requirement
130
- none: false
131
- requirements:
132
- - - "="
133
- - !ruby/object:Gem::Version
148
+ version_requirements: &2250 !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - =
151
+ - !ruby/object:Gem::Version
134
152
  version: 0.1.8
153
+ none: false
154
+ requirement: *2250
155
+ prerelease: false
135
156
  type: :runtime
136
- version_requirements: *id011
137
- - !ruby/object:Gem::Dependency
157
+ - !ruby/object:Gem::Dependency
138
158
  name: guid
139
- prerelease: false
140
- requirement: &id012 !ruby/object:Gem::Requirement
141
- none: false
142
- requirements:
143
- - - "="
144
- - !ruby/object:Gem::Version
159
+ version_requirements: &2266 !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - =
162
+ - !ruby/object:Gem::Version
145
163
  version: 0.1.1
164
+ none: false
165
+ requirement: *2266
166
+ prerelease: false
146
167
  type: :runtime
147
- version_requirements: *id012
148
- - !ruby/object:Gem::Dependency
168
+ - !ruby/object:Gem::Dependency
149
169
  name: slop
150
- prerelease: false
151
- requirement: &id013 !ruby/object:Gem::Requirement
152
- none: false
153
- requirements:
154
- - - "="
155
- - !ruby/object:Gem::Version
170
+ version_requirements: &2282 !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - =
173
+ - !ruby/object:Gem::Version
156
174
  version: 2.1.0
175
+ none: false
176
+ requirement: *2282
177
+ prerelease: false
157
178
  type: :runtime
158
- version_requirements: *id013
159
- - !ruby/object:Gem::Dependency
179
+ - !ruby/object:Gem::Dependency
160
180
  name: hiredis
161
- prerelease: false
162
- requirement: &id014 !ruby/object:Gem::Requirement
181
+ version_requirements: &2298 !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - =
184
+ - !ruby/object:Gem::Version
185
+ version: 0.4.5
163
186
  none: false
164
- requirements:
165
- - - "="
166
- - !ruby/object:Gem::Version
167
- version: 0.3.1
168
- type: :runtime
169
- version_requirements: *id014
170
- - !ruby/object:Gem::Dependency
171
- name: yajl-ruby
187
+ requirement: *2298
172
188
  prerelease: false
173
- requirement: &id015 !ruby/object:Gem::Requirement
174
- none: false
175
- requirements:
176
- - - ">="
177
- - !ruby/object:Gem::Version
178
- version: "0"
179
189
  type: :runtime
180
- version_requirements: *id015
181
- - !ruby/object:Gem::Dependency
182
- name: thin
190
+ - !ruby/object:Gem::Dependency
191
+ name: cs-em-hiredis
192
+ version_requirements: &2314 !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - =
195
+ - !ruby/object:Gem::Version
196
+ version: 0.1.2
197
+ none: false
198
+ requirement: *2314
183
199
  prerelease: false
184
- requirement: &id016 !ruby/object:Gem::Requirement
200
+ type: :runtime
201
+ - !ruby/object:Gem::Dependency
202
+ name: jruby-openssl
203
+ version_requirements: &2330 !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ! '>='
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
185
208
  none: false
186
- requirements:
187
- - - ">="
188
- - !ruby/object:Gem::Version
189
- version: "0"
209
+ requirement: *2330
210
+ prerelease: false
190
211
  type: :runtime
191
- version_requirements: *id016
192
- - !ruby/object:Gem::Dependency
193
- name: diff-lcs
212
+ - !ruby/object:Gem::Dependency
213
+ name: json
214
+ version_requirements: &2346 !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ! '>='
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ none: false
220
+ requirement: *2346
194
221
  prerelease: false
195
- requirement: &id017 !ruby/object:Gem::Requirement
222
+ type: :runtime
223
+ - !ruby/object:Gem::Dependency
224
+ name: warbler
225
+ version_requirements: &2362 !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - =
228
+ - !ruby/object:Gem::Version
229
+ version: 1.2.1
196
230
  none: false
197
- requirements:
198
- - - "="
199
- - !ruby/object:Gem::Version
231
+ requirement: *2362
232
+ prerelease: false
233
+ type: :development
234
+ - !ruby/object:Gem::Dependency
235
+ name: diff-lcs
236
+ version_requirements: &2380 !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - =
239
+ - !ruby/object:Gem::Version
200
240
  version: 1.1.2
241
+ none: false
242
+ requirement: *2380
243
+ prerelease: false
201
244
  type: :development
202
- version_requirements: *id017
203
- - !ruby/object:Gem::Dependency
245
+ - !ruby/object:Gem::Dependency
204
246
  name: sinatra-reloader
205
- prerelease: false
206
- requirement: &id018 !ruby/object:Gem::Requirement
207
- none: false
208
- requirements:
209
- - - "="
210
- - !ruby/object:Gem::Version
247
+ version_requirements: &2396 !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - =
250
+ - !ruby/object:Gem::Version
211
251
  version: 0.5.0
252
+ none: false
253
+ requirement: *2396
254
+ prerelease: false
212
255
  type: :development
213
- version_requirements: *id018
214
- - !ruby/object:Gem::Dependency
256
+ - !ruby/object:Gem::Dependency
215
257
  name: rspec
216
- prerelease: false
217
- requirement: &id019 !ruby/object:Gem::Requirement
218
- none: false
219
- requirements:
258
+ version_requirements: &2412 !ruby/object:Gem::Requirement
259
+ requirements:
220
260
  - - ~>
221
- - !ruby/object:Gem::Version
222
- version: "2.5"
261
+ - !ruby/object:Gem::Version
262
+ version: '2.5'
263
+ none: false
264
+ requirement: *2412
265
+ prerelease: false
223
266
  type: :development
224
- version_requirements: *id019
225
- - !ruby/object:Gem::Dependency
267
+ - !ruby/object:Gem::Dependency
226
268
  name: rack-test
227
- prerelease: false
228
- requirement: &id020 !ruby/object:Gem::Requirement
269
+ version_requirements: &2428 !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - =
272
+ - !ruby/object:Gem::Version
273
+ version: 0.6.1
229
274
  none: false
230
- requirements:
231
- - - "="
232
- - !ruby/object:Gem::Version
233
- version: 0.5.7
275
+ requirement: *2428
276
+ prerelease: false
234
277
  type: :development
235
- version_requirements: *id020
236
- - !ruby/object:Gem::Dependency
278
+ - !ruby/object:Gem::Dependency
237
279
  name: rake
238
- prerelease: false
239
- requirement: &id021 !ruby/object:Gem::Requirement
240
- none: false
241
- requirements:
242
- - - "="
243
- - !ruby/object:Gem::Version
280
+ version_requirements: &2444 !ruby/object:Gem::Requirement
281
+ requirements:
282
+ - - =
283
+ - !ruby/object:Gem::Version
244
284
  version: 0.8.7
285
+ none: false
286
+ requirement: *2444
287
+ prerelease: false
245
288
  type: :development
246
- version_requirements: *id021
247
289
  description: Application registry inspired by Apache Zookeeper
248
- email:
290
+ email:
249
291
  - lusis.org+rubygems.org@gmail.com
250
- executables:
292
+ executables:
251
293
  - noah
252
- - noah-watcher.rb
294
+ - noah-watcher
253
295
  extensions: []
254
-
255
296
  extra_rdoc_files: []
256
-
257
- files:
297
+ files:
258
298
  - .autotest
259
299
  - .gemtest
260
300
  - .gitignore
301
+ - CHANGELOG.md
261
302
  - Gemfile
262
303
  - LICENSE
263
304
  - README.md
@@ -265,7 +306,7 @@ files:
265
306
  - TODO.md
266
307
  - autotest/discover.rb
267
308
  - bin/noah
268
- - bin/noah-watcher.rb
309
+ - bin/noah-watcher
269
310
  - config.ru
270
311
  - config/warble.rb
271
312
  - examples/Kirkfile
@@ -354,33 +395,50 @@ files:
354
395
  - views/404.erb
355
396
  - views/500.erb
356
397
  - views/index.haml
357
- has_rdoc: true
398
+ - views/index.json.erb
358
399
  homepage: https://github.com/lusis/noah
359
400
  licenses: []
360
-
361
401
  post_install_message: This release has backwards incompatible changes to the API. Please watch http://goo.gl/jYqp2 for details
362
402
  rdoc_options: []
363
-
364
- require_paths:
403
+ require_paths:
365
404
  - lib
366
- required_ruby_version: !ruby/object:Gem::Requirement
405
+ required_ruby_version: !ruby/object:Gem::Requirement
406
+ requirements:
407
+ - - ! '>='
408
+ - !ruby/object:Gem::Version
409
+ version: '0'
367
410
  none: false
368
- requirements:
369
- - - ">="
370
- - !ruby/object:Gem::Version
371
- version: "0"
372
- required_rubygems_version: !ruby/object:Gem::Requirement
411
+ required_rubygems_version: !ruby/object:Gem::Requirement
412
+ requirements:
413
+ - - ! '>='
414
+ - !ruby/object:Gem::Version
415
+ version: '0'
373
416
  none: false
374
- requirements:
375
- - - ">="
376
- - !ruby/object:Gem::Version
377
- version: "0"
378
417
  requirements: []
379
-
380
418
  rubyforge_project: noah
381
- rubygems_version: 1.6.2
382
- signing_key:
419
+ rubygems_version: 1.8.15
420
+ signing_key:
383
421
  specification_version: 3
384
422
  summary: Application registry inspired by Apache Zookeeper
385
- test_files: []
386
-
423
+ test_files:
424
+ - spec/application_spec.rb
425
+ - spec/configuration_spec.rb
426
+ - spec/ephemeral_spec.rb
427
+ - spec/host_spec.rb
428
+ - spec/link_spec.rb
429
+ - spec/noahapp_application_spec.rb
430
+ - spec/noahapp_configuration_spec.rb
431
+ - spec/noahapp_ephemeral_spec.rb
432
+ - spec/noahapp_host_spec.rb
433
+ - spec/noahapp_service_spec.rb
434
+ - spec/noahapp_spec.rb
435
+ - spec/noahapp_tag_spec.rb
436
+ - spec/noahapp_watcher_spec.rb
437
+ - spec/service_spec.rb
438
+ - spec/spec_helper.rb
439
+ - spec/support/db/.keep
440
+ - spec/support/sample_data.rb
441
+ - spec/support/test-redis.conf
442
+ - spec/tag_spec.rb
443
+ - spec/watcher_spec.rb
444
+ ...