noah 0.4-jruby → 0.6.pre-jruby
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -69
- data/lib/noah.rb +1 -0
- data/lib/noah/agent.rb +1 -0
- data/lib/noah/agents/base_agent.rb +4 -2
- data/lib/noah/agents/http_agent.rb +1 -1
- data/lib/noah/agents/https_agent.rb +6 -0
- data/lib/noah/app.rb +8 -6
- data/lib/noah/exceptions.rb +0 -0
- data/lib/noah/linkable.rb +21 -0
- data/lib/noah/models.rb +14 -25
- data/lib/noah/models/applications.rb +19 -9
- data/lib/noah/models/configurations.rb +32 -13
- data/lib/noah/models/ephemerals.rb +7 -6
- data/lib/noah/models/hosts.rb +11 -5
- data/lib/noah/models/link.rb +70 -29
- data/lib/noah/models/services.rb +11 -2
- data/lib/noah/models/tags.rb +86 -5
- data/lib/noah/models/watchers.rb +0 -1
- data/lib/noah/{application_routes.rb → routes/applications.rb} +31 -27
- data/lib/noah/routes/configurations.rb +77 -0
- data/lib/noah/{ephemeral_routes.rb → routes/ephemerals.rb} +5 -5
- data/lib/noah/{host_routes.rb → routes/hosts.rb} +16 -1
- data/lib/noah/routes/links.rb +16 -0
- data/lib/noah/{service_routes.rb → routes/services.rb} +28 -12
- data/lib/noah/routes/tags.rb +15 -0
- data/lib/noah/{watcher_routes.rb → routes/watchers.rb} +0 -0
- data/lib/noah/taggable.rb +30 -0
- data/lib/noah/version.rb +1 -1
- data/noah.gemspec +5 -4
- data/spec/application_spec.rb +3 -3
- data/spec/configuration_spec.rb +19 -12
- data/spec/host_spec.rb +5 -5
- data/spec/noahapp_application_spec.rb +11 -13
- data/spec/noahapp_configuration_spec.rb +63 -40
- data/spec/noahapp_ephemeral_spec.rb +15 -15
- data/spec/noahapp_host_spec.rb +4 -6
- data/spec/noahapp_service_spec.rb +8 -7
- data/spec/service_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -5
- data/spec/support/sample_data.rb +87 -0
- data/spec/tag_spec.rb +78 -0
- data/views/index.haml +7 -1
- metadata +335 -311
- data/lib/noah/configuration_routes.rb +0 -81
- data/lib/noah/models/link_member.rb +0 -18
data/lib/noah/models/hosts.rb
CHANGED
@@ -3,7 +3,8 @@ module Noah
|
|
3
3
|
class Host < Model
|
4
4
|
# Host model
|
5
5
|
# @return {Host} a {Host} object
|
6
|
-
|
6
|
+
include Taggable
|
7
|
+
include Linkable
|
7
8
|
attribute :name
|
8
9
|
attribute :status
|
9
10
|
collection :services, Service
|
@@ -21,9 +22,11 @@ module Noah
|
|
21
22
|
|
22
23
|
# @return [Hash] A hash representation of a {Host}
|
23
24
|
def to_hash
|
24
|
-
|
25
|
-
services.sort.each
|
26
|
-
|
25
|
+
services_hash = Hash.new
|
26
|
+
services.sort.each do |svc|
|
27
|
+
services_hash["#{svc.name}"] = svc.status
|
28
|
+
end
|
29
|
+
h = {:name => name, :status => status, :created_at => created_at, :updated_at => updated_at, :services => services_hash}
|
27
30
|
super.merge(h)
|
28
31
|
end
|
29
32
|
|
@@ -50,7 +53,10 @@ module Noah
|
|
50
53
|
# @param [Hash] optional filters for results
|
51
54
|
# @return [Array] Array of {Host} objects
|
52
55
|
def self.all(options = {})
|
53
|
-
|
56
|
+
host_hash = Hash.new
|
57
|
+
options.empty? ? hosts=Noah::Host.all.sort : hosts=Noah::Host.find(options).sort
|
58
|
+
hosts.each {|x| host_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name } }
|
59
|
+
host_hash
|
54
60
|
end
|
55
61
|
end
|
56
62
|
end
|
data/lib/noah/models/link.rb
CHANGED
@@ -1,45 +1,86 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'link_member')
|
2
1
|
module Noah
|
3
2
|
class Link < Model
|
4
3
|
attribute :path
|
5
|
-
|
6
|
-
|
4
|
+
attribute :nodes
|
5
|
+
|
7
6
|
index :path
|
7
|
+
index :nodes
|
8
|
+
|
9
|
+
def nodes
|
10
|
+
arr = []
|
11
|
+
self.key[:nodes].smembers.each do |node|
|
12
|
+
arr << node
|
13
|
+
end
|
14
|
+
arr
|
15
|
+
end
|
16
|
+
|
17
|
+
def nodes=(node)
|
18
|
+
case node.class.to_s
|
19
|
+
when "Array"
|
20
|
+
node.each do |n|
|
21
|
+
self.key[:nodes].sadd(n.key)
|
22
|
+
n.links << self
|
23
|
+
end
|
24
|
+
else
|
25
|
+
self.key[:nodes].sadd(node.key)
|
26
|
+
node.links << self
|
27
|
+
end
|
28
|
+
end
|
8
29
|
|
9
30
|
def validate
|
10
31
|
super
|
11
32
|
assert_present :path
|
12
33
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
|
35
|
+
def to_hash
|
36
|
+
# TODO Holy shit, is this messy or what?
|
37
|
+
# Prepopulate instance variables of each object type instead?
|
38
|
+
%w[applications configurations hosts services ephemerals].each {|x| instance_variable_set("@#{x}", Hash.new)}
|
39
|
+
if nodes.size > 0
|
40
|
+
nodes.each do |node|
|
41
|
+
rejected_vals = [:created_at, :updated_at, :links, :name]
|
42
|
+
n = node_to_class(node)
|
43
|
+
cls = class_to_lower(n.class.to_s)
|
44
|
+
hsh = instance_variable_get("@#{cls}s")
|
45
|
+
# all of this bs is because services are unique per [servicename, hostname]
|
46
|
+
# so if I add multiple services just by name to the hash, I'll wipe the previous one
|
47
|
+
# a better option would be for services to be named slug style
|
48
|
+
hsh["#{n.name}"] = Hash.new unless hsh.has_key?(n.name)
|
49
|
+
case cls
|
50
|
+
when "service"
|
51
|
+
sh = Noah::Host[n.host_id].name
|
52
|
+
hsh["#{n.name}"]["#{sh}"] = Hash.new unless hsh["#{n.name}"].has_key?("#{sh}")
|
53
|
+
hsh["#{n.name}"]["#{sh}"].merge!({:id => n.id, :status => n.status, :tags => n.to_hash[:tags]})
|
54
|
+
when "host"
|
55
|
+
hsh["#{n.name}"].merge!({:id => n.id, :status => n.status, :tags => n.to_hash[:tags], :services => n.to_hash[:services]})
|
56
|
+
else
|
57
|
+
hsh["#{n.name}"].merge!(n.to_hash.reject{|key, value| rejected_vals.member?(key)})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
h = {:name => name, :hosts => @hosts, :services => @services, :applications => @applications, :configurations => @configurations, :ephemerals => @ephemerals, :created_at => created_at, :updated_at => updated_at}
|
62
|
+
super.merge(h)
|
63
|
+
end
|
39
64
|
|
40
65
|
def name
|
41
66
|
@name = path
|
42
67
|
end
|
43
68
|
|
69
|
+
class <<self
|
70
|
+
def find_or_create(opts={})
|
71
|
+
begin
|
72
|
+
find(opts).first.nil? ? obj=create(opts) : obj=find(opts).first
|
73
|
+
obj
|
74
|
+
rescue Exception => e
|
75
|
+
e.message
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def node_to_class(node)
|
82
|
+
node.match(/^Noah::(.*):(\d+)$/)
|
83
|
+
Noah.const_get($1).send(:[], $2)
|
84
|
+
end
|
44
85
|
end
|
45
86
|
end
|
data/lib/noah/models/services.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Noah
|
2
2
|
|
3
3
|
class Service < Model
|
4
|
-
|
4
|
+
include Taggable
|
5
|
+
include Linkable
|
5
6
|
attribute :name
|
6
7
|
attribute :status
|
7
8
|
reference :host, Host
|
@@ -48,7 +49,15 @@ module Noah
|
|
48
49
|
|
49
50
|
class Services
|
50
51
|
def self.all(options = {})
|
51
|
-
|
52
|
+
service_hash = Hash.new
|
53
|
+
options.empty? ? services=Service.all.sort : services=Service.find(options).sort
|
54
|
+
services.each do |svc|
|
55
|
+
service_hash["#{svc.name}"] = Hash.new unless service_hash.has_key?(svc.name)
|
56
|
+
host_name = Noah::Host[svc.host_id].name
|
57
|
+
service_hash["#{svc.name}"]["#{host_name}"] = Hash.new
|
58
|
+
service_hash["#{svc.name}"]["#{host_name}"].merge!({:id => svc.id, :status => svc.status, :tags => svc.to_hash[:tags], :links => svc.to_hash[:links], :created_at => svc.created_at, :updated_at => svc.updated_at})
|
59
|
+
end
|
60
|
+
service_hash
|
52
61
|
end
|
53
62
|
end
|
54
63
|
end
|
data/lib/noah/models/tags.rb
CHANGED
@@ -1,13 +1,94 @@
|
|
1
1
|
module Noah
|
2
|
+
|
2
3
|
class Tag < Model
|
3
|
-
|
4
|
+
attribute :name
|
5
|
+
attribute :members
|
6
|
+
index :members
|
7
|
+
index :name
|
8
|
+
|
9
|
+
def validate
|
10
|
+
super
|
11
|
+
assert_present :name
|
12
|
+
assert_unique :name
|
13
|
+
end
|
14
|
+
|
15
|
+
def members=(member)
|
16
|
+
self.key[:members].sadd(member.key)
|
17
|
+
member.tag! self.name unless member.tags.member?(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def members
|
21
|
+
hsh = Hash.new
|
22
|
+
self.key[:members].smembers.each do |member|
|
23
|
+
n = node_to_class(member)
|
24
|
+
cls = class_to_lower(n.class.to_s)
|
25
|
+
hash_key = "#{cls}s".to_sym
|
26
|
+
hsh[hash_key] = Array.new unless hsh.has_key?(hash_key)
|
27
|
+
hsh[hash_key] << n
|
28
|
+
end
|
29
|
+
hsh
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
h = {:name => name, :created_at => created_at, :updated_at => updated_at}
|
34
|
+
h.merge!(members_to_hash)
|
35
|
+
super.merge(h)
|
36
|
+
end
|
37
|
+
|
38
|
+
class <<self
|
39
|
+
def find_or_create(opts={})
|
40
|
+
begin
|
41
|
+
find(opts).first.nil? ? obj=create(opts) : obj=find(opts).first
|
42
|
+
obj
|
43
|
+
rescue Exception => e
|
44
|
+
e.message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def node_to_class(node)
|
51
|
+
node.match(/^Noah::(.*):(\d+)$/)
|
52
|
+
Noah.const_get($1).send(:[], $2)
|
53
|
+
end
|
54
|
+
|
55
|
+
def members_to_hash
|
56
|
+
new_hash = Hash.new
|
57
|
+
members.keys.each {|k| new_hash[k] = Hash.new}
|
58
|
+
members.each do |category, member_array|
|
59
|
+
rejected_vals = [:created_at, :updated_at, :tags, :name, :host]
|
60
|
+
h = new_hash[category]
|
61
|
+
member_array.each {|mem| h["#{mem.name}"] = Hash.new unless h.has_key?(mem.name)}
|
62
|
+
case category
|
63
|
+
when :services
|
64
|
+
member_array.each do |s|
|
65
|
+
sh = Noah::Host[s.host_id].name
|
66
|
+
h["#{s.name}"]["#{sh}"] = Hash.new unless h["#{s.name}"].has_key?(sh)
|
67
|
+
h["#{s.name}"]["#{sh}"].merge!(s.to_hash.reject{|k,v| rejected_vals.member?(k)})
|
68
|
+
end
|
69
|
+
else
|
70
|
+
member_array.each do |m|
|
71
|
+
h["#{m.name}"].merge!(m.to_hash.reject{|k,v| rejected_vals.member?(k)})
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
new_hash
|
76
|
+
end
|
77
|
+
end
|
4
78
|
|
5
|
-
|
6
|
-
|
79
|
+
class Tags
|
80
|
+
def self.all(options = {})
|
81
|
+
tag_hash = Hash.new
|
82
|
+
options.empty? ? tags=Tag.all.sort : tags=Tag.find(options).sort
|
83
|
+
tags.each {|t| tag_hash["#{t.name}"] = t.to_hash.reject {|k,v| k == :name } }
|
84
|
+
tag_hash
|
7
85
|
end
|
8
86
|
|
9
|
-
|
10
|
-
|
87
|
+
class <<self
|
88
|
+
def tagged(tag)
|
89
|
+
t = Tag.find(:name => tag).first
|
90
|
+
t.members
|
91
|
+
end
|
11
92
|
end
|
12
93
|
end
|
13
94
|
|
data/lib/noah/models/watchers.rb
CHANGED
@@ -2,21 +2,23 @@ class Noah::App
|
|
2
2
|
# Application URIs
|
3
3
|
get '/applications/:appname/:config/?' do |appname, config|
|
4
4
|
app = Noah::Application.find(:name => appname).first
|
5
|
-
if app.nil?
|
6
|
-
|
7
|
-
|
8
|
-
c = Noah::Configuration.find(:name => config, :application_id => app.id).first
|
9
|
-
c.to_json
|
10
|
-
end
|
5
|
+
(halt 404) if app.nil?
|
6
|
+
c = app.configurations.find(:name => config).first
|
7
|
+
c.to_json
|
11
8
|
end
|
12
9
|
|
13
10
|
get '/applications/:appname/?' do |appname|
|
14
11
|
app = Noah::Application.find(:name => appname).first
|
15
|
-
if app.nil?
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
(halt 404) if app.nil?
|
13
|
+
app.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
put '/applications/:appname/tag' do |appname|
|
17
|
+
required_params = ["tags"]
|
18
|
+
data = JSON.parse(request.body.read)
|
19
|
+
(data.keys.sort == required_params.sort) ? (a=Noah::Application.find(:name=>appname).first) : (raise "Missing Parameters")
|
20
|
+
a.nil? ? (halt 404) : (a.tag!(data['tags']))
|
21
|
+
a.to_json
|
20
22
|
end
|
21
23
|
|
22
24
|
put '/applications/:appname/watch' do |appname|
|
@@ -27,6 +29,14 @@ class Noah::App
|
|
27
29
|
w.to_json
|
28
30
|
end
|
29
31
|
|
32
|
+
put '/applications/:appname/link' do |appname|
|
33
|
+
required_params = ["link_name"]
|
34
|
+
data = JSON.parse(request.body.read)
|
35
|
+
(data.keys.sort == required_params.sort) ? (a = Noah::Application.find(:name => appname).first) : (raise "Missing Parameters")
|
36
|
+
a.nil? ? (halt 404) : (a.link! data["link_name"])
|
37
|
+
a.to_json
|
38
|
+
end
|
39
|
+
|
30
40
|
put '/applications/:appname/?' do |appname|
|
31
41
|
required_params = ["name"]
|
32
42
|
data = JSON.parse(request.body.read)
|
@@ -47,24 +57,18 @@ class Noah::App
|
|
47
57
|
|
48
58
|
delete '/applications/:appname/?' do |appname|
|
49
59
|
app = Noah::Application.find(:name => appname).first
|
50
|
-
if app.nil?
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
r.to_json
|
58
|
-
end
|
60
|
+
(halt 404) if app.nil?
|
61
|
+
app.delete
|
62
|
+
r = {"result" => "success", "action" => "delete", "id" => "#{app.id}", "name" => "#{appname}"}
|
63
|
+
r.to_json
|
64
|
+
end
|
65
|
+
|
66
|
+
delete '/applications/:appname/configurations/:configname/?' do |appname, configname|
|
59
67
|
end
|
60
68
|
|
61
69
|
get '/applications/?' do
|
62
|
-
apps =
|
63
|
-
|
64
|
-
|
65
|
-
halt 404
|
66
|
-
else
|
67
|
-
apps.to_json
|
68
|
-
end
|
70
|
+
apps = Noah::Applications.all
|
71
|
+
(halt 404) if apps.size == 0
|
72
|
+
apps.to_json
|
69
73
|
end
|
70
74
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Noah::App
|
2
|
+
content_type_mapping = {
|
3
|
+
:yaml => "text/x-yaml",
|
4
|
+
:json => "application/json",
|
5
|
+
:xml => "text/xml",
|
6
|
+
:string => "text/plain"
|
7
|
+
}
|
8
|
+
# GET the raw data of a configuration object
|
9
|
+
get '/configurations/:configname/data/?' do |configname|
|
10
|
+
c = Noah::Configuration.find(:name => configname).first
|
11
|
+
(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
|
15
|
+
end
|
16
|
+
# GET the JSON representation of a configuration object
|
17
|
+
get '/configurations/:configname/?' do |configname|
|
18
|
+
c = Noah::Configuration.find(:name => configname).first
|
19
|
+
(halt 404) if c.nil?
|
20
|
+
c.to_json
|
21
|
+
end
|
22
|
+
# GET all configurations
|
23
|
+
get '/configurations/?' do
|
24
|
+
configs = Noah::Configurations.all.to_hash
|
25
|
+
(halt 404) if configs.size == 0
|
26
|
+
configs.to_json
|
27
|
+
end
|
28
|
+
# Add configuration object to a custom link hierarchy
|
29
|
+
put '/configurations/:configname/link' do |configname|
|
30
|
+
required_params = ["link_name"]
|
31
|
+
data = JSON.parse(request.body.read)
|
32
|
+
(data.keys.sort == required_params.sort) ? (a = Noah::Configuration.find(:name => configname).first) : (raise "Missing Parameters")
|
33
|
+
a.nil? ? (halt 404) : (a.link! data["link_name"])
|
34
|
+
a.to_json
|
35
|
+
end
|
36
|
+
# Add a tag to a configuration object
|
37
|
+
put '/configurations/:configname/tag' do |configname|
|
38
|
+
required_params = ["tags"]
|
39
|
+
data = JSON.parse(request.body.read)
|
40
|
+
(data.keys.sort == required_params.sort) ? (c=Noah::Configuration.find(:name=>configname).first) : (raise "Missing Parameters")
|
41
|
+
c.nil? ? (halt 404) : (c.tag!(data['tags']))
|
42
|
+
c.to_json
|
43
|
+
|
44
|
+
end
|
45
|
+
# Add a watch to a configuration object
|
46
|
+
put '/configurations/:configname/watch' do |configname|
|
47
|
+
required_params = ["endpoint"]
|
48
|
+
data = JSON.parse(request.body.read)
|
49
|
+
(data.keys.sort == required_params.sort) ? (c = Noah::Configuration.find(:name => configname).first) : (raise "Missing Parameters")
|
50
|
+
c.nil? ? (halt 404) : (w = c.watch!(:endpoint => data['endpoint']))
|
51
|
+
w.to_json
|
52
|
+
end
|
53
|
+
# Attach a configuration object to an application object
|
54
|
+
put '/configurations/:configname/?' do |configname|
|
55
|
+
required_params = ["format", "body"]
|
56
|
+
data = JSON.parse(request.body.read)
|
57
|
+
data.keys.sort == required_params.sort ? config=Noah::Configuration.find_or_create(:name => configname) : (raise "Missing Parameters")
|
58
|
+
config.body = data["body"]
|
59
|
+
config.format = data["format"]
|
60
|
+
if config.valid?
|
61
|
+
config.save
|
62
|
+
action = config.is_new? ? "create" : "update"
|
63
|
+
r = {"result" => "success","id" => "#{config.id}", "action" => action, "item" => config.name}
|
64
|
+
r.to_json
|
65
|
+
else
|
66
|
+
raise "#{format_errors(config)}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
delete '/configurations/:configname/?' do |configname|
|
71
|
+
cfg = Noah::Configuration.find(:name => configname).first
|
72
|
+
(halt 404) if cfg.nil?
|
73
|
+
cfg.delete
|
74
|
+
r = {"result" => "success", "id" => cfg.id, "action" => "delete", "affected_applications" => cfg.affected_applications, "item" => cfg.name}
|
75
|
+
r.to_json
|
76
|
+
end
|
77
|
+
end
|