noah 0.6.pre → 0.8

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/lib/noah/app.rb CHANGED
@@ -45,7 +45,7 @@ module Noah
45
45
  get '/' do
46
46
  content_type "text/html"
47
47
 
48
- haml :index, :format => :html5, :locals => {:redis_url => settings.redis_url, :noah_version => Noah::VERSION}
48
+ haml :index, :format => :html5, :locals => {:redis_version => Ohm.redis.info["redis_version"].to_s, :noah_version => Noah::VERSION}
49
49
  end
50
50
 
51
51
  not_found do
data/lib/noah/helpers.rb CHANGED
@@ -59,7 +59,54 @@ module Noah
59
59
  else
60
60
  Noah::Services.all(:host_id => id)
61
61
  end
62
- end
62
+ end
63
+
64
+ def find_hosts_by_service(servicename)
65
+ affected_hosts = []
66
+ s = Noah::Service.find(:name => servicename)
67
+ if s.nil?
68
+ affected_hosts
69
+ else
70
+ Noah::Host.all.each {|x| affected_hosts << x if (x.services.to_a & s.to_a).length > 0}
71
+ affected_hosts
72
+ end
73
+ end
74
+
75
+ def delete_service_from_host(servicename, hostname)
76
+ host = Noah::Host.find(:name => hostname).first
77
+ (halt 404) if host.nil?
78
+ service = Noah::Service.find(:name => servicename, :host_id => host.id).first
79
+ (halt 404) if service.nil?
80
+ service.delete
81
+ r = {"action" => "delete", "result" => "success", "id" => service.id, "host" => host.name, "service" => servicename}
82
+ r.to_json
83
+ end
84
+
85
+ def add_config_to_app(appname, config_hash)
86
+ begin
87
+ config = Noah::Configuration.find_or_create(config_hash)
88
+ if config.valid?
89
+ dep_action = config.is_new? ? "create" : "update"
90
+ else
91
+ raise "#{format_errors(config)}"
92
+ end
93
+ app = Noah::Application.find_or_create(:name => appname)
94
+ if app.valid?
95
+ action = app.is_new? ? "create" : "update"
96
+ app.configurations << config
97
+ r = {"result" => "success", "id" => "#{app.id}", "name" => "#{app.name}", "action" => action, "configuration" => {"action" => dep_action, "id" => "#{config.id}", "item" => "#{config.name}"}}
98
+ r.to_json
99
+ else
100
+ raise "#{format_errors(app)}"
101
+ end
102
+ rescue Exception => e
103
+ e.message
104
+ ensure
105
+ # Clean up partial objects
106
+ app.delete if app.valid? == false
107
+ config.delete if config.valid? == false
108
+ end
109
+ end
63
110
 
64
111
  def application(opts = {})
65
112
  Noah::Application.find(opts).first
@@ -20,7 +20,8 @@ module Noah
20
20
  configurations.sort.each do |cfg|
21
21
  cfg_hash["#{cfg.name}"] = {:format => cfg.to_hash[:format], :body => cfg.to_hash[:body]}
22
22
  end
23
- {name => {:id => id, :created_at => created_at, :updated_at => updated_at, :configurations => cfg_hash}}
23
+ res_hash = {:name => name, :created_at => created_at, :updated_at => updated_at, :configurations => cfg_hash}
24
+ super.merge(res_hash)
24
25
  end
25
26
 
26
27
  class << self
@@ -43,8 +44,7 @@ module Noah
43
44
  def self.all(options = {})
44
45
  app_hash = Hash.new
45
46
  options.empty? ? apps=Application.all.sort : apps=Application.find(options).sort
46
- #apps.each {|x| app_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
47
- apps.each {|x| app_hash.merge!(x.to_hash) }
47
+ apps.each {|x| app_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
48
48
  app_hash
49
49
  end
50
50
  end
@@ -44,9 +44,13 @@ module Noah
44
44
  class << self
45
45
  def find_or_create(opts={})
46
46
  begin
47
- find(opts).first.nil? ? (obj = new(opts)) : (obj = find(opts).first)
48
- if obj.valid?
47
+ find(:name => opts[:name]).first.nil? ? (obj = new(opts)) : (obj = find(:name => opts[:name]).first)
48
+ if obj.valid? && obj.new?
49
49
  obj.save
50
+ else
51
+ obj.format = opts[:format]
52
+ obj.body = opts[:body]
53
+ obj.save if obj.valid?
50
54
  end
51
55
  obj
52
56
  rescue Exception => e
@@ -11,6 +11,7 @@ module Noah
11
11
 
12
12
  index :name
13
13
  index :status
14
+ index :services
14
15
 
15
16
  def validate
16
17
  super
@@ -33,9 +34,9 @@ module Noah
33
34
  class << self
34
35
  def find_or_create(opts = {})
35
36
  begin
36
- # exclude requested status from lookup
37
- h = find(opts.reject{|key,value| key == :status}).first
38
- host = h.nil? ? create(opts) : h
37
+ h = find(:name => opts[:name]).first
38
+ #h = find(opts.reject{|key,value| key == :status}).first
39
+ h.nil? ? host=new(opts) : host=h
39
40
  host.status = opts[:status]
40
41
  if host.valid?
41
42
  host.save
@@ -33,8 +33,8 @@ module Noah
33
33
  opts.reject!{|key, value| key == :host}
34
34
  end
35
35
  # exclude requested status from lookup
36
- s = find(opts.reject{|key,value| key == :status}).first
37
- service = s.nil? ? create(opts) : s
36
+ s = find(:name => opts[:name], :host_id => opts[:host_id]).first
37
+ s.nil? ? service=new(opts) : service=s
38
38
  service.status = opts[:status]
39
39
  if service.valid?
40
40
  service.save
@@ -48,7 +48,7 @@ module Noah
48
48
 
49
49
  private
50
50
  def node_to_class(node)
51
- node.match(/^Noah::(.*):(\d+)$/)
51
+ node.match(/^Noah::(.*):(.*)$/)
52
52
  Noah.const_get($1).send(:[], $2)
53
53
  end
54
54
 
data/lib/noah/models.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'ohm'
2
2
  require 'ohm/contrib'
3
+ require 'guid'
4
+
3
5
  module Noah
4
6
  class Model < Ohm::Model
5
7
 
@@ -96,6 +98,11 @@ module Noah
96
98
  end
97
99
  end
98
100
 
101
+ private
102
+ def initialize_id
103
+ @id ||= Guid.new.to_s
104
+ end
105
+
99
106
  end
100
107
 
101
108
  class RegisteredModels
@@ -1,10 +1,10 @@
1
1
  class Noah::App
2
2
  # Application URIs
3
- get '/applications/:appname/:config/?' do |appname, config|
3
+ get '/applications/:appname/configurations/:config/?' do |appname, config|
4
4
  app = Noah::Application.find(:name => appname).first
5
5
  (halt 404) if app.nil?
6
- c = app.configurations.find(:name => config).first
7
- c.to_json
6
+ request.path_info = "/configurations/#{config}"
7
+ pass
8
8
  end
9
9
 
10
10
  get '/applications/:appname/?' do |appname|
@@ -37,6 +37,14 @@ class Noah::App
37
37
  a.to_json
38
38
  end
39
39
 
40
+ put '/applications/:appname/configurations/:configname/?' do |appname, configname|
41
+ required_params = ["format", "body"]
42
+ raise "Missing Parameters" if request.body.nil?
43
+ data = JSON.parse(request.body.read)
44
+ raise "Missing Parameters" if data.keys.sort != required_params.sort
45
+ add_config_to_app(appname, {:name => configname, :format => data['format'], :body => data['body']})
46
+ end
47
+
40
48
  put '/applications/:appname/?' do |appname|
41
49
  required_params = ["name"]
42
50
  data = JSON.parse(request.body.read)
@@ -64,6 +72,17 @@ class Noah::App
64
72
  end
65
73
 
66
74
  delete '/applications/:appname/configurations/:configname/?' do |appname, configname|
75
+ app = Noah::Application.find(:name => appname).first
76
+ (halt 404) if app.nil?
77
+ config = Noah::Configuration.find(:name => configname).first
78
+ (halt 404) if config.nil?
79
+ if app.configurations.member?(config)
80
+ app.configurations.delete(config)
81
+ r = {"result" => "success", "action" => "delete", "id" => "#{app.id}", "name" => "#{app.name}", "configuration" => "#{config.name}"}
82
+ r.to_json
83
+ else
84
+ halt 404
85
+ end
67
86
  end
68
87
 
69
88
  get '/applications/?' do
@@ -5,19 +5,17 @@ class Noah::App
5
5
  :xml => "text/xml",
6
6
  :string => "text/plain"
7
7
  }
8
- # GET the raw data of a configuration object
9
- get '/configurations/:configname/data/?' do |configname|
8
+ get '/configurations/:configname/?', :provides => :json do |configname|
10
9
  c = Noah::Configuration.find(:name => configname).first
11
10
  (halt 404) if c.nil?
12
- content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym]
13
- response.headers['Content-Disposition'] = "attachment; filename=#{configname}"
14
- c.body
11
+ c.to_json
15
12
  end
16
- # GET the JSON representation of a configuration object
17
13
  get '/configurations/:configname/?' do |configname|
18
14
  c = Noah::Configuration.find(:name => configname).first
19
15
  (halt 404) if c.nil?
20
- c.to_json
16
+ 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
21
19
  end
22
20
  # GET all configurations
23
21
  get '/configurations/?' do
@@ -2,7 +2,7 @@ class Noah::App
2
2
  # Host URIs
3
3
 
4
4
  # GET named {Service} for named {Host}
5
- get '/hosts/:hostname/:servicename/?' do |hostname, servicename|
5
+ get '/hosts/:hostname/services/:servicename/?' do |hostname, servicename|
6
6
  h = host_service(hostname, servicename)
7
7
  if h.nil?
8
8
  halt 404
@@ -35,6 +35,7 @@ class Noah::App
35
35
  put '/hosts/:hostname/tag' do |hostname|
36
36
  required_params = ["tags"]
37
37
  data = JSON.parse(request.body.read)
38
+ raise "Missing parameters" if data.nil?
38
39
  (data.keys.sort == required_params.sort) ? (a=Noah::Host.find(:name=>hostname).first) : (raise "Missing Parameters")
39
40
  a.nil? ? (halt 404) : (a.tag!(data['tags']))
40
41
  a.to_json
@@ -43,6 +44,7 @@ class Noah::App
43
44
  put '/hosts/:hostname/watch' do |hostname|
44
45
  required_params = ["endpoint"]
45
46
  data = JSON.parse(request.body.read)
47
+ raise "Missing parameters" if data.nil?
46
48
  (data.keys.sort == required_params.sort) ? (h = Noah::Host.find(:name => hostname).first) : (raise "Missing Parameters")
47
49
  h.nil? ? (halt 404) : (w = h.watch!(:endpoint => data['endpoint']))
48
50
  w.to_json
@@ -51,15 +53,17 @@ class Noah::App
51
53
  put '/hosts/:hostname/link' do |hostname|
52
54
  required_params = ["link_name"]
53
55
  data = JSON.parse(request.body.read)
56
+ raise "Missing parameters" if data.nil?
54
57
  (data.keys.sort == required_params.sort) ? (a = Noah::Host.find(:name => hostname).first) : (raise "Missing Parameters")
55
58
  a.nil? ? (halt 404) : (a.link! data["link_name"])
56
59
  a.to_json
57
60
  end
58
61
 
59
62
  put '/hosts/:hostname/?' do |hostname|
60
- required_params = ["name", "status"]
63
+ required_params = ["status"]
61
64
  data = JSON.parse(request.body.read)
62
- (data.keys.sort == required_params.sort && data['name'] == hostname) ? (host = Noah::Host.find_or_create(:name => data['name'], :status => data['status'])) : (raise "Missing Parameters")
65
+ raise "Missing parameters" if data.nil?
66
+ (data.keys.sort == required_params.sort) ? (host = Noah::Host.find_or_create(:name => hostname, :status => data['status'])) : (raise "Missing Parameters")
63
67
  if host.valid?
64
68
  r = {"result" => "success","id" => "#{host.id}","status" => "#{host.status}", "name" => "#{host.name}", "new_record" => host.is_new?}
65
69
  r.to_json
@@ -70,15 +74,16 @@ class Noah::App
70
74
 
71
75
  delete '/hosts/:hostname/?' do |hostname|
72
76
  host = Noah::Host.find(:name => hostname).first
73
- if host
74
- services = []
75
- Noah::Service.find(:host_id => host.id).sort.each {|x| services << x; x.delete} if host.services.size > 0
76
- host.delete
77
- r = {"result" => "success", "id" => "#{host.id}", "name" => "#{hostname}", "service_count" => "#{services.size}"}
78
- r.to_json
79
- else
80
- halt 404
81
- end
77
+ (halt 404) if host.nil?
78
+ services = []
79
+ Noah::Service.find(:host_id => host.id).sort.each {|x| services << x; x.delete} if host.services.size > 0
80
+ host.delete
81
+ r = {"result" => "success", "id" => "#{host.id}", "name" => "#{hostname}", "service_count" => "#{services.size}"}
82
+ r.to_json
83
+ end
84
+
85
+ delete '/hosts/:hostname/services/:servicename/?' do |hostname, servicename|
86
+ delete_service_from_host(servicename, hostname)
82
87
  end
83
88
 
84
89
  end
@@ -54,19 +54,26 @@ class Noah::App
54
54
  w.to_json
55
55
  end
56
56
 
57
- put '/services/:servicename/?' do |servicename|
58
- required_params = ["status", "host", "name"]
57
+ put '/services/:servicename/:hostname?' do |servicename, hostname|
58
+ required_params = ["status", "host_status"]
59
59
  data = JSON.parse(request.body.read)
60
+ raise ("Missing Parameters") if data.nil?
60
61
  if data.keys.sort == required_params.sort
61
- h = Noah::Host.find(:name => data['host']).first || (raise "Invalid Host")
62
- service = Noah::Service.find_or_create(:name => servicename, :status => data['status'], :host => h)
63
- if service.valid?
64
- action = service.is_new? ? "create" : "update"
65
- service.save
66
- r = {"action" => action, "result" => "success", "id" => service.id, "host" => h.name, "name" => service.name}
67
- r.to_json
68
- else
69
- raise "#{format_errors(service)}"
62
+ begin
63
+ host = Noah::Host.find_or_create(:name => hostname, :status => data['host_status'])
64
+ if host.valid?
65
+ service = Noah::Service.find_or_create(:name => servicename, :status => data['status'], :host => host)
66
+ if service.valid?
67
+ service_action = service.is_new? ? "create" : "update"
68
+ host_action = host.is_new? ? "create" : "update"
69
+ r = {"action" => service_action, "result" => "success", "id" => service.id, "name" => service.name, "host" => {"name" => host.name, "action" => host_action, "status" => host.status}}
70
+ r.to_json
71
+ else
72
+ raise "#{format_errors(service)}"
73
+ end
74
+ else
75
+ raise "#{format_errors(host)}"
76
+ end
70
77
  end
71
78
  else
72
79
  raise "Missing Parameters"
@@ -74,14 +81,15 @@ class Noah::App
74
81
  end
75
82
 
76
83
  delete '/services/:servicename/:hostname/?' do |servicename, hostname|
77
- host = Noah::Host.find(:name => hostname).first || (halt 404)
78
- service = Noah::Service.find(:name => servicename, :host_id => host.id).first || (halt 404)
79
- if host && service
80
- service.delete
81
- r = {"action" => "delete", "result" => "success", "id" => service.id, "host" => host.name, "service" => servicename}
82
- r.to_json
83
- else
84
- halt 404
85
- end
86
- end
84
+ delete_service_from_host(servicename, hostname)
85
+ end
86
+
87
+ delete '/services/:servicename/?' do |servicename|
88
+ affected_hosts = find_hosts_by_service(servicename)
89
+ (halt 404) if affected_hosts.size == 0
90
+ service = Noah::Service.find(:name => servicename)
91
+ service.each {|x| x.delete}
92
+ r = {"action" => "delete", "result" => "success", "affected_hosts" => affected_hosts.size, "service" => servicename}
93
+ r.to_json
94
+ end
87
95
  end
data/lib/noah/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.6"
2
+ VERSION = "0.8"
3
3
  end
data/noah.gemspec CHANGED
@@ -4,7 +4,7 @@ require "noah/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "noah"
7
- s.version = "#{Noah::VERSION}.pre"
7
+ s.version = "#{Noah::VERSION}"
8
8
  s.post_install_message = %q{This release has backwards incompatible changes to the API. Please watch http://goo.gl/jYqp2 for details}
9
9
  s.platform = Gem::Platform::RUBY
10
10
  #s.platform = "jruby"
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.add_dependency("ohm-contrib", ["= 0.1.1"])
33
33
  s.add_dependency("haml", ["= 3.0.25"])
34
34
  s.add_dependency("vegas", ["= 0.1.8"])
35
+ s.add_dependency("guid", ["= 0.1.1"])
35
36
 
36
37
 
37
38
  if RUBY_PLATFORM =~ /java/
data/spec/host_spec.rb CHANGED
@@ -26,10 +26,10 @@ describe "Using the Host Model", :reset_redis => true do
26
26
  host.name.should == hostname
27
27
  host.status.should == hoststatus
28
28
  host.services.size.should == 1
29
- host.services[1].valid?.should == true
30
- host.services[1].name.should == servicename
31
- host.services[1].status.should == servicestatus
32
- host.services[1].host_id.should == host.id
29
+ host.services.first.valid?.should == true
30
+ host.services.first.name.should == servicename
31
+ host.services.first.status.should == servicestatus
32
+ host.services.first.host_id.should == host.id
33
33
  end
34
34
 
35
35
  it "create a Host via find_or_create" do
@@ -2,7 +2,9 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Using the Application API", :reset_redis => false do
4
4
  before(:all) do
5
+ Ohm.redis.flushdb
5
6
  @a = Noah::Application.create(:name => 'rspec_sample_app')
7
+ @b = Noah::Application.create(:name => 'rspec_sample_app_2')
6
8
  @c = Noah::Configuration.create(:name => 'rspec_config', :format => 'string', :body => 'rspec is great')
7
9
  @a.configurations << @c
8
10
  @a.save
@@ -15,30 +17,39 @@ describe "Using the Application API", :reset_redis => false do
15
17
  last_response.should be_ok
16
18
  response = last_response.should return_json
17
19
  response.is_a?(Hash).should == true
20
+ response.size.should == 2
18
21
  end
19
22
  it "named application should work" do
20
23
  get '/applications/rspec_sample_app'
21
24
  last_response.should be_ok
22
25
  response = last_response.should return_json
23
- response.has_key?(@a.name).should == true
24
- response[@a.name].class.to_s.should == 'Hash'
25
- response[@a.name]["id"].should == @a.id.to_s
26
- response[@a.name].has_key?("configurations").should == true
27
- c = response[@a.name]["configurations"]
26
+ response["id"].should == @a.id.to_s
27
+ response["name"].should == @a.name
28
+ response.has_key?("configurations").should == true
29
+ c = response["configurations"]
28
30
  c.has_key?(@c.name).should == true
29
31
  c["#{@c.name}"]["format"].should == "#{@c.format}"
30
32
  c["#{@c.name}"]["body"].should == "#{@c.body}"
31
33
  end
32
- it "named configuration for application should work" do
33
- get "/applications/#{@a.name}/#{@c.name}"
34
+ it "named configuration for application should work as JSON" do
35
+ header "Accept", "application/json"
36
+ get "/applications/#{@a.name}/configurations/#{@c.name}"
34
37
  last_response.should be_ok
35
38
  response = last_response.should return_json
36
-
37
39
  response["id"].should == @c.id
38
40
  response["name"].should == @c.name
39
41
  response["format"].should == @c.format
40
42
  response["body"].should == @c.body
41
43
  end
44
+ it "named configuration for application should work as raw" do
45
+ header "Accept", "application/octet"
46
+ get "/applications/#{@a.name}/configurations/#{@c.name}"
47
+ last_response.should be_ok
48
+ headers = last_response.headers
49
+ body = last_response.body
50
+ headers["Content-Type"].should == 'text/plain;charset=utf-8'
51
+ body.should == @c.body
52
+ end
42
53
  it "invalid application should not work" do
43
54
  get "/applications/should_not_exist"
44
55
  last_response.should be_missing
@@ -64,6 +75,7 @@ describe "Using the Application API", :reset_redis => false do
64
75
  Noah::Application.find(:name => @appdata[:name]).size.should == 1
65
76
  Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == true
66
77
  end
78
+ it "new application with new configuration should work"
67
79
  it "new application with missing name should not work" do
68
80
  put "/applications/should_not_work", '{"foo":"bar"}', "CONTENT_TYPE" => "application/json"
69
81
  last_response.should be_invalid
@@ -80,7 +92,9 @@ describe "Using the Application API", :reset_redis => false do
80
92
  response["action"].should == "update"
81
93
  Noah::Application.find(:name => @appdata[:name]).size.should == 1
82
94
  Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == false
83
- end
95
+ end
96
+ it "existing application with new configuration"
97
+ it "existing application with existing configuration"
84
98
  end
85
99
 
86
100
  describe "DELETE" do
@@ -41,7 +41,8 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
41
41
  end
42
42
  end
43
43
  end
44
- it "named configuration should work" do
44
+ it "named configuration should work as JSON" do
45
+ header "Accept", "application/json"
45
46
  get '/configurations/redis_url'
46
47
  last_response.should be_ok
47
48
  response = last_response.should return_json
@@ -55,7 +56,7 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
55
56
  end
56
57
  it "named configuration should work with mime-type" do
57
58
  require 'yaml'
58
- get '/configurations/yaml_config/data'
59
+ get '/configurations/yaml_config'
59
60
  last_response.should be_ok
60
61
  last_response.headers["Content-Type"].should == "text/x-yaml;charset=utf-8"
61
62
  response = YAML.load(last_response.body)
@@ -114,9 +115,7 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
114
115
  @c = Noah::Configuration.create(cparms)
115
116
  @a.configurations << @c
116
117
  get "/configurations/asdf"
117
- p last_response
118
118
  delete "/configurations/#{@c.name}"
119
- p last_response
120
119
  last_response.should be_ok
121
120
  response = last_response.should return_json
122
121
  response["result"].should == "success"
@@ -27,7 +27,7 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
27
27
  end
28
28
 
29
29
  it "named service for host should work" do
30
- get '/hosts/localhost/noah'
30
+ get '/hosts/localhost/services/noah'
31
31
  last_response.should be_ok
32
32
  response = last_response.should return_json
33
33
 
@@ -39,7 +39,7 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
39
39
 
40
40
  describe "PUT" do
41
41
  it "new host should work" do
42
- host_data = {:name => "host99.domain.com", :status => "down"}.to_json
42
+ host_data = {:status => "down"}.to_json
43
43
  put '/hosts/host99.domain.com', host_data, "CONTENT_TYPE" => "application/json"
44
44
  last_response.should be_ok
45
45
  response = last_response.should return_json
@@ -53,7 +53,7 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
53
53
 
54
54
  it "existing host should work" do
55
55
  sleep 3
56
- host_data = {:name => "host99.domain.com", :status => "pending"}.to_json
56
+ host_data = {:status => "pending"}.to_json
57
57
  put '/hosts/host99.domain.com', host_data, "CONTENT_TYPE" => "application/json"
58
58
  last_response.should be_ok
59
59
  response = last_response.should return_json
@@ -61,20 +61,13 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
61
61
  response["new_record"].should == false
62
62
  end
63
63
 
64
- it "host missing name parameter should not work" do
65
- host_data = {:status => "pending"}.to_json
66
- put '/hosts/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
67
- last_response.should be_invalid
68
- end
69
-
70
64
  it "host missing status parameter should not work" do
71
- host_data = {:name => "host100.domain.com"}.to_json
72
- put '/hosts/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
65
+ put '/hosts/host100.domain.com', "{}", "CONTENT_TYPE" => "application/json"
73
66
  last_response.should be_invalid
74
67
  end
75
68
 
76
69
  it "host with invalid status parameter should not work" do
77
- host_data = {:name => "host100.domain.com", :status => "fscked"}.to_json
70
+ host_data = {:status => "fscked"}.to_json
78
71
  put '/hosts/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
79
72
  last_response.should_not be_ok
80
73
  response = last_response.should return_json
@@ -85,7 +78,8 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
85
78
  end
86
79
 
87
80
  describe "DELETE" do
88
- before(:all) do
81
+ before(:each) do
82
+ Ohm.redis.flushdb
89
83
  @h = Noah::Host.create(:name => 'h', :status => 'up')
90
84
  sparms = {:name => 's', :status => "up"}
91
85
  @h.services << Noah::Service.create(sparms.merge({:host => @h}))
@@ -97,15 +91,25 @@ describe "Using the Host API", :reset_redis => false, :populate_sample_data => t
97
91
  delete "/hosts/#{@h.name}"
98
92
  last_response.should be_ok
99
93
  response = last_response.should return_json
100
-
101
94
  response["result"].should == "success"
102
95
  response["id"].should == @h.id
103
96
  response["name"].should == @h.name
104
97
  response["service_count"].should == svc_size.to_s
105
98
  end
106
99
 
100
+ it "valid service from valid host should work" do
101
+ delete "/hosts/#{@h.name}/services/#{@s.name}"
102
+ last_response.should be_ok
103
+ response = last_response.should return_json
104
+ response["result"].should == "success"
105
+ response["action"].should == "delete"
106
+ response["id"].should == @s.id
107
+ response["host"].should == @h.name
108
+ response["service"].should == @s.name
109
+ end
110
+
107
111
  it "invalid host should not work" do
108
- delete "/hosts/#{@h.name}"
112
+ delete "/hosts/not_a_valid_hsot"
109
113
  last_response.should be_missing
110
114
  end
111
115
  end
@@ -46,76 +46,143 @@ describe "Using the Service API", :reset_redis => false, :populate_sample_data =
46
46
  end
47
47
 
48
48
  describe "PUT" do
49
- before(:all) do
50
- @payload = {:name => 'another_rspec_service', :status => 'up', :host => @h.name}
51
- end
52
- it "new service should work" do
53
- put "/services/#{@payload[:name]}/", @payload.to_json, "CONTENT_TYPE" => "application/json"
49
+ before(:each) do
50
+ Ohm.redis.flushdb
51
+ @host_name = 'rspec_sample_host'
52
+ @service_name = 'rspec_sample_service'
53
+ @payload = {:status => 'up', :host_status => 'up'}
54
+ end
55
+ after(:each) do
56
+ Ohm.redis.flushdb
57
+ end
58
+ it "new service on new host should work" do
59
+ put "/services/#{@service_name}/#{@host_name}", @payload.to_json, "CONTENT_TYPE" => "application/json"
54
60
  last_response.should be_ok
55
61
  response = last_response.should return_json
56
62
  response["result"].should == "success"
57
63
  response["action"].should == "create"
58
64
  response["id"].nil?.should == false
59
- response["name"].should == @payload[:name]
60
- response["host"].should == @payload[:host]
61
- Noah::Service.find(:name => @payload[:name]).size.should == 1
62
- Noah::Service.find(:name => @payload[:name]).first.is_new?.should == true
65
+ response["name"].should == @service_name
66
+ response["host"]["name"].should == @host_name
67
+ response["host"]["status"].should == 'up'
68
+ response["host"]["action"].should == 'create'
69
+ response["host"]["status"].should == 'up'
70
+ Noah::Service.find(:name => @service_name).size.should == 1
71
+ Noah::Service.find(:name => @service_name).first.is_new?.should == true
72
+ Noah::Host.find(:name => @host_name).size.should == 1
73
+ Noah::Host.find(:name => @host_name).first.is_new?.should == true
63
74
  end
64
- it "new service without host should not work" do
65
- put "/services/foobar", {:name => "foobar", :status => "up"}.to_json, "CONTENT_TYPE" => "application/json"
66
- last_response.should be_invalid
75
+ it "new service on existing host should work" do
76
+ hostname = 'non-existant-rspec-host'
77
+ servicename = 'non-existant-rspec-service'
78
+ Noah::Host.create(:name => hostname, :status => 'up')
79
+ sleep(3)
80
+ put "/services/#{servicename}/#{hostname}", @payload.to_json, "CONTENT_TYPE" => "application/json"
81
+ last_response.should be_ok
82
+ response = last_response.should return_json
83
+ response["result"].should == "success"
84
+ response["action"].should == "create"
85
+ response["id"].nil?.should == false
86
+ response["name"].should == servicename
87
+ response["host"]["name"].should == hostname
88
+ response["host"]["status"].should == 'up'
89
+ response["host"]["action"].should == 'update'
90
+ Noah::Service.find(:name => servicename).size.should == 1
91
+ Noah::Service.find(:name => servicename).first.is_new?.should == true
92
+ end
93
+ it "new service with invalid host status should not work" do
94
+ put "/services/foobar/#{@host_name}", {:host_status => "fsck", :status => "up"}.to_json, "CONTENT_TYPE" => "application/json"
95
+ last_response.should_not be_ok
96
+ response = last_response.should return_json
97
+ response["error_message"].should == "Status must be up, down or pending"
67
98
  end
68
- it "new service with invalid status should not work" do
69
- put "/services/foobar", {:name => "foobar", :status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
99
+ it "new service with invalid service status should not work" do
100
+ put "/services/foobar/#{@host_name}", {:host_status => "up", :status => "fsck"}.to_json, "CONTENT_TYPE" => "application/json"
70
101
  last_response.should_not be_ok
71
102
  response = last_response.should return_json
72
103
  response["error_message"].should == "Status must be up, down or pending"
73
104
  end
74
- it "new service with missing name should not work" do
75
- put "/services/foobar", {:status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
105
+ it "new service with missing host_status should not work" do
106
+ put "/services/foobar/#{@host_name}", {:status => "up"}.to_json, "CONTENT_TYPE" => "application/json"
76
107
  last_response.should be_invalid
77
108
  end
78
109
  it "new service with missing status should not work" do
79
- put "/services/foobar", {:name => "foobar", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
110
+ put "/services/foobar/#{@host_name}", {:host_status => 'up'}.to_json, "CONTENT_TYPE" => "application/json"
80
111
  last_response.should be_invalid
81
112
  end
82
113
  it "existing service should work" do
83
- sleep 3
84
- put "/services/#{@payload[:name]}", {:name => @payload[:name], :status => "down", :host => @payload[:host]}.to_json, "CONTENT_TYPE" => "application/json"
114
+ a = Noah::Host.create(:name => @host_name, :status => 'up')
115
+ b = Noah::Service.create(:name => @service_name, :status => 'pending', :host => a)
116
+ sleep(3)
117
+ put "/services/#{@service_name}/#{@host_name}", @payload.to_json, "CONTENT_TYPE" => "application/json"
85
118
  last_response.should be_ok
86
119
  response = last_response.should return_json
87
120
  response["result"].should == "success"
88
121
  response["action"].should == "update"
89
122
  response["id"].nil?.should == false
90
- response["name"].should == @payload[:name]
91
- response["host"].should == @payload[:host]
92
- Noah::Service.find(:name => @payload[:name]).size.should == 1
93
- Noah::Service.find(:name => @payload[:name]).first.is_new?.should == false
123
+ response["name"].should == @service_name
124
+ response["host"]["name"].should == @host_name
125
+ response["host"]["status"].should == 'up'
126
+ response["host"]["action"].should == 'update'
94
127
  end
95
128
  end
96
129
 
97
130
  describe "DELETE" do
98
131
  before(:all) do
132
+ Ohm.redis.flushdb
99
133
  @h = Noah::Host.create(:name => "h1", :status => "up")
100
134
  @h.services << Noah::Service.create(:name => "s1", :status => "up", :host => @h)
101
135
  @h.save
102
136
  @s = @h.services.first
103
137
  end
104
- it "existing host should work" do
138
+ it "service from existing host should work" do
105
139
  delete "/services/#{@s.name}/#{@h.name}"
106
140
  last_response.should be_ok
107
141
  response = last_response.should return_json
108
-
109
142
  response["result"].should == "success"
110
143
  response["action"].should == "delete"
111
144
  response["id"].should == @s.id
112
145
  response["host"].should == @h.name
113
146
  response["service"].should == @s.name
114
- end
115
- it "invalid host should not work" do
147
+ end
148
+ it "all entries for a valid service" do
149
+ all_svc_name = 'my_sample_service'
150
+ foo_svc_name = 'my_sample_service_two'
151
+ bar_svc_name = 'my_sample_service_three'
152
+ %w[foo bar baz].each do |host|
153
+ h = Noah::Host.create(:name => host, :status => "up")
154
+ Noah::Service.create(:name => all_svc_name, :status => 'up', :host => h)
155
+ end
156
+ foo_host = Noah::Host.find(:name => 'foo').first
157
+ bar_host = Noah::Host.find(:name => 'bar').first
158
+ Noah::Service.create(:name => foo_svc_name, :status => 'down', :host => foo_host)
159
+ Noah::Service.create(:name => bar_svc_name, :status => 'pending', :host => bar_host)
160
+
161
+ delete "/services/#{all_svc_name}"
162
+ last_response.should be_ok
163
+ response = last_response.should return_json
164
+ response["result"].should == "success"
165
+ response["action"].should == "delete"
166
+ response["affected_hosts"].should == 3
167
+
168
+ delete "/services/#{foo_svc_name}"
169
+ last_response.should be_ok
170
+ response = last_response.should return_json
171
+ response["affected_hosts"].should == 1
172
+ end
173
+ it "service for invalid host should not work" do
116
174
  delete "/services/#{@s.name}/#{@h.name}"
117
175
  last_response.should be_missing
118
176
  end
177
+ it "invalid service for valid host should not work" do
178
+ Noah::Host.create(:name => 'valid_host', :status => 'up')
179
+ delete "/services/not_really_here/valid_host"
180
+ last_response.should be_missing
181
+ end
182
+ it "all entries for an invalid service should not_work" do
183
+ delete "/services/not_really_here"
184
+ last_response.should be_missing
185
+ end
119
186
  end
120
187
 
121
188
  end
data/spec/service_spec.rb CHANGED
@@ -16,7 +16,7 @@ describe "Noah Service Model", :reset_redis => true do
16
16
  service.name.should == servicename
17
17
  service.status.should == servicestatus
18
18
  service.host_id.should == host.id
19
- host.services[1].name.should == servicename
19
+ host.services[service.id].name.should == servicename
20
20
  end
21
21
 
22
22
  it "create a new Service with find_or_create" do
@@ -78,9 +78,8 @@ l1.nodes = [a1, c2, Noah::Host.find(:name => 'localhost').first, Noah::Service.f
78
78
  a1.tag! ["production", "sample_data"]
79
79
  e2.tag! ["ephemeral", "development"]
80
80
  c1.tag! "development"
81
- Noah::Service[1].tag! "development"
82
- Noah::Service[2].tag! ["development", "out-of-service"]
83
- Noah::Service[2].link! "/my_sample_organization"
81
+ Noah::Service.all.first.tag! ["development", "out-of-service"]
82
+ Noah::Service.all.first.link! "/my_sample_organization"
84
83
 
85
84
 
86
85
  puts "Sample data populated!"
data/views/index.haml CHANGED
@@ -9,7 +9,7 @@
9
9
  %li
10
10
  Noah Version: #{locals[:noah_version]}
11
11
  %li
12
- Redis URL: #{locals[:redis_url]}
12
+ Redis Version: #{locals[:redis_version]}
13
13
  #header
14
14
  %h2 Hosts
15
15
  %ul
metadata CHANGED
@@ -1,8 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noah
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 4
5
- version: 0.6.pre
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 8
9
+ version: "0.8"
6
10
  platform: ruby
7
11
  authors:
8
12
  - John E. Vincent
@@ -10,7 +14,7 @@ autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
16
 
13
- date: 2011-04-18 00:00:00 -04:00
17
+ date: 2011-04-26 00:00:00 -04:00
14
18
  default_executable:
15
19
  dependencies:
16
20
  - !ruby/object:Gem::Dependency
@@ -21,6 +25,13 @@ dependencies:
21
25
  requirements:
22
26
  - - "="
23
27
  - !ruby/object:Gem::Version
28
+ hash: 62196357
29
+ segments:
30
+ - 1
31
+ - 0
32
+ - 0
33
+ - beta
34
+ - 3
24
35
  version: 1.0.0.beta.3
25
36
  type: :runtime
26
37
  version_requirements: *id001
@@ -32,6 +43,13 @@ dependencies:
32
43
  requirements:
33
44
  - - "="
34
45
  - !ruby/object:Gem::Version
46
+ hash: 62196357
47
+ segments:
48
+ - 1
49
+ - 0
50
+ - 0
51
+ - beta
52
+ - 3
35
53
  version: 1.0.0.beta.3
36
54
  type: :runtime
37
55
  version_requirements: *id002
@@ -43,6 +61,11 @@ dependencies:
43
61
  requirements:
44
62
  - - "="
45
63
  - !ruby/object:Gem::Version
64
+ hash: 7
65
+ segments:
66
+ - 2
67
+ - 2
68
+ - 0
46
69
  version: 2.2.0
47
70
  type: :runtime
48
71
  version_requirements: *id003
@@ -54,6 +77,11 @@ dependencies:
54
77
  requirements:
55
78
  - - "="
56
79
  - !ruby/object:Gem::Version
80
+ hash: 19
81
+ segments:
82
+ - 1
83
+ - 1
84
+ - 0
57
85
  version: 1.1.0
58
86
  type: :runtime
59
87
  version_requirements: *id004
@@ -65,6 +93,11 @@ dependencies:
65
93
  requirements:
66
94
  - - "="
67
95
  - !ruby/object:Gem::Version
96
+ hash: 27
97
+ segments:
98
+ - 1
99
+ - 2
100
+ - 2
68
101
  version: 1.2.2
69
102
  type: :runtime
70
103
  version_requirements: *id005
@@ -76,6 +109,11 @@ dependencies:
76
109
  requirements:
77
110
  - - "="
78
111
  - !ruby/object:Gem::Version
112
+ hash: 27
113
+ segments:
114
+ - 1
115
+ - 2
116
+ - 2
79
117
  version: 1.2.2
80
118
  type: :runtime
81
119
  version_requirements: *id006
@@ -87,6 +125,11 @@ dependencies:
87
125
  requirements:
88
126
  - - "="
89
127
  - !ruby/object:Gem::Version
128
+ hash: 25
129
+ segments:
130
+ - 1
131
+ - 2
132
+ - 3
90
133
  version: 1.2.3
91
134
  type: :runtime
92
135
  version_requirements: *id007
@@ -98,6 +141,11 @@ dependencies:
98
141
  requirements:
99
142
  - - "="
100
143
  - !ruby/object:Gem::Version
144
+ hash: 29
145
+ segments:
146
+ - 0
147
+ - 1
148
+ - 3
101
149
  version: 0.1.3
102
150
  type: :runtime
103
151
  version_requirements: *id008
@@ -109,6 +157,11 @@ dependencies:
109
157
  requirements:
110
158
  - - "="
111
159
  - !ruby/object:Gem::Version
160
+ hash: 25
161
+ segments:
162
+ - 0
163
+ - 1
164
+ - 1
112
165
  version: 0.1.1
113
166
  type: :runtime
114
167
  version_requirements: *id009
@@ -120,6 +173,11 @@ dependencies:
120
173
  requirements:
121
174
  - - "="
122
175
  - !ruby/object:Gem::Version
176
+ hash: 53
177
+ segments:
178
+ - 3
179
+ - 0
180
+ - 25
123
181
  version: 3.0.25
124
182
  type: :runtime
125
183
  version_requirements: *id010
@@ -131,97 +189,167 @@ dependencies:
131
189
  requirements:
132
190
  - - "="
133
191
  - !ruby/object:Gem::Version
192
+ hash: 11
193
+ segments:
194
+ - 0
195
+ - 1
196
+ - 8
134
197
  version: 0.1.8
135
198
  type: :runtime
136
199
  version_requirements: *id011
137
200
  - !ruby/object:Gem::Dependency
138
- name: hiredis
201
+ name: guid
139
202
  prerelease: false
140
203
  requirement: &id012 !ruby/object:Gem::Requirement
141
204
  none: false
142
205
  requirements:
143
206
  - - "="
144
207
  - !ruby/object:Gem::Version
145
- version: 0.3.1
208
+ hash: 25
209
+ segments:
210
+ - 0
211
+ - 1
212
+ - 1
213
+ version: 0.1.1
146
214
  type: :runtime
147
215
  version_requirements: *id012
148
216
  - !ruby/object:Gem::Dependency
149
- name: yajl-ruby
217
+ name: hiredis
150
218
  prerelease: false
151
219
  requirement: &id013 !ruby/object:Gem::Requirement
152
220
  none: false
153
221
  requirements:
154
- - - ">="
222
+ - - "="
155
223
  - !ruby/object:Gem::Version
156
- version: "0"
224
+ hash: 17
225
+ segments:
226
+ - 0
227
+ - 3
228
+ - 1
229
+ version: 0.3.1
157
230
  type: :runtime
158
231
  version_requirements: *id013
159
232
  - !ruby/object:Gem::Dependency
160
- name: thin
233
+ name: yajl-ruby
161
234
  prerelease: false
162
235
  requirement: &id014 !ruby/object:Gem::Requirement
163
236
  none: false
164
237
  requirements:
165
238
  - - ">="
166
239
  - !ruby/object:Gem::Version
240
+ hash: 3
241
+ segments:
242
+ - 0
167
243
  version: "0"
168
244
  type: :runtime
169
245
  version_requirements: *id014
170
246
  - !ruby/object:Gem::Dependency
171
- name: diff-lcs
247
+ name: SystemTimer
172
248
  prerelease: false
173
249
  requirement: &id015 !ruby/object:Gem::Requirement
250
+ none: false
251
+ requirements:
252
+ - - ">="
253
+ - !ruby/object:Gem::Version
254
+ hash: 3
255
+ segments:
256
+ - 0
257
+ version: "0"
258
+ type: :runtime
259
+ version_requirements: *id015
260
+ - !ruby/object:Gem::Dependency
261
+ name: thin
262
+ prerelease: false
263
+ requirement: &id016 !ruby/object:Gem::Requirement
264
+ none: false
265
+ requirements:
266
+ - - ">="
267
+ - !ruby/object:Gem::Version
268
+ hash: 3
269
+ segments:
270
+ - 0
271
+ version: "0"
272
+ type: :runtime
273
+ version_requirements: *id016
274
+ - !ruby/object:Gem::Dependency
275
+ name: diff-lcs
276
+ prerelease: false
277
+ requirement: &id017 !ruby/object:Gem::Requirement
174
278
  none: false
175
279
  requirements:
176
280
  - - "="
177
281
  - !ruby/object:Gem::Version
282
+ hash: 23
283
+ segments:
284
+ - 1
285
+ - 1
286
+ - 2
178
287
  version: 1.1.2
179
288
  type: :development
180
- version_requirements: *id015
289
+ version_requirements: *id017
181
290
  - !ruby/object:Gem::Dependency
182
291
  name: sinatra-reloader
183
292
  prerelease: false
184
- requirement: &id016 !ruby/object:Gem::Requirement
293
+ requirement: &id018 !ruby/object:Gem::Requirement
185
294
  none: false
186
295
  requirements:
187
296
  - - "="
188
297
  - !ruby/object:Gem::Version
298
+ hash: 11
299
+ segments:
300
+ - 0
301
+ - 5
302
+ - 0
189
303
  version: 0.5.0
190
304
  type: :development
191
- version_requirements: *id016
305
+ version_requirements: *id018
192
306
  - !ruby/object:Gem::Dependency
193
307
  name: rspec
194
308
  prerelease: false
195
- requirement: &id017 !ruby/object:Gem::Requirement
309
+ requirement: &id019 !ruby/object:Gem::Requirement
196
310
  none: false
197
311
  requirements:
198
312
  - - ~>
199
313
  - !ruby/object:Gem::Version
314
+ hash: 9
315
+ segments:
316
+ - 2
317
+ - 5
200
318
  version: "2.5"
201
319
  type: :development
202
- version_requirements: *id017
320
+ version_requirements: *id019
203
321
  - !ruby/object:Gem::Dependency
204
322
  name: rcov
205
323
  prerelease: false
206
- requirement: &id018 !ruby/object:Gem::Requirement
324
+ requirement: &id020 !ruby/object:Gem::Requirement
207
325
  none: false
208
326
  requirements:
209
327
  - - "="
210
328
  - !ruby/object:Gem::Version
329
+ hash: 41
330
+ segments:
331
+ - 0
332
+ - 9
333
+ - 9
211
334
  version: 0.9.9
212
335
  type: :development
213
- version_requirements: *id018
336
+ version_requirements: *id020
214
337
  - !ruby/object:Gem::Dependency
215
338
  name: rack-test
216
339
  prerelease: false
217
- requirement: &id019 !ruby/object:Gem::Requirement
340
+ requirement: &id021 !ruby/object:Gem::Requirement
218
341
  none: false
219
342
  requirements:
220
343
  - - "="
221
344
  - !ruby/object:Gem::Version
345
+ hash: 5
346
+ segments:
347
+ - 0
348
+ - 5
349
+ - 7
222
350
  version: 0.5.7
223
351
  type: :development
224
- version_requirements: *id019
352
+ version_requirements: *id021
225
353
  description: Application registry based on Apache Zookeeper
226
354
  email:
227
355
  - lusis.org+rubygems.org@gmail.com
@@ -338,13 +466,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
338
466
  requirements:
339
467
  - - ">="
340
468
  - !ruby/object:Gem::Version
469
+ hash: 3
470
+ segments:
471
+ - 0
341
472
  version: "0"
342
473
  required_rubygems_version: !ruby/object:Gem::Requirement
343
474
  none: false
344
475
  requirements:
345
- - - ">"
476
+ - - ">="
346
477
  - !ruby/object:Gem::Version
347
- version: 1.3.1
478
+ hash: 3
479
+ segments:
480
+ - 0
481
+ version: "0"
348
482
  requirements: []
349
483
 
350
484
  rubyforge_project: noah