noah 0.4 → 0.6.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -69
- 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/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/models.rb +14 -25
- 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/lib/noah.rb +1 -0
- 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 +23 -16
- data/lib/noah/configuration_routes.rb +0 -81
- data/lib/noah/models/link_member.rb +0 -18
data/Rakefile
CHANGED
@@ -11,7 +11,6 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
11
11
|
spec.pattern = FileList['spec/**/*_spec.rb']
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
14
|
task :default => :run
|
16
15
|
task :test => :run
|
17
16
|
|
@@ -40,75 +39,9 @@ end
|
|
40
39
|
desc "Populate database with sample dataset"
|
41
40
|
task :sample, :redis_url do |t, args|
|
42
41
|
require 'noah'
|
43
|
-
|
44
42
|
Ohm::connect(:url => args.redis_url)
|
45
|
-
|
46
|
-
|
47
|
-
Noah::Watcher.create :endpoint => "dummy://applications", :pattern => "//noah/applications"
|
48
|
-
Noah::Watcher.create :endpoint => "dummy://configurations", :pattern => "//noah/configurations"
|
49
|
-
Noah::Watcher.create :endpoint => "dummy://hosts", :pattern => "//noah/hosts"
|
50
|
-
Noah::Watcher.create :endpoint => "dummy://services", :pattern => "//noah/services"
|
51
|
-
Noah::Watcher.create :endpoint => "dummy://ephemerals", :pattern => "//noah/ephemerals"
|
52
|
-
puts "Creating Host entry for 'localhost'"
|
53
|
-
h = Noah::Host.create(:name => 'localhost', :status => "up")
|
54
|
-
if h.save
|
55
|
-
%w[redis noah].each do |service|
|
56
|
-
puts "Create Service entry for #{service}"
|
57
|
-
s = Noah::Service.create(:name => service, :status => "up", :host => h)
|
58
|
-
h.services << s
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
puts "Creating Application entry for 'noah'"
|
63
|
-
a = Noah::Application.create(:name => 'noah')
|
64
|
-
if a.save
|
65
|
-
puts "Creating Configuration entry for 'noah'"
|
66
|
-
cr = Noah::Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0', :application => a)
|
67
|
-
ch = Noah::Configuration.create(:name => 'host', :format => 'string', :body => 'localhost', :application => a)
|
68
|
-
cp = Noah::Configuration.create(:name => 'port', :format => 'string', :body => '9292', :application => a)
|
69
|
-
%w[cr ch cp].each do |c|
|
70
|
-
a.configurations << eval(c)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
puts "Creating sample entries - Host and Service"
|
75
|
-
%w[host1.domain.com host2.domain.com host3.domain.com].each do |host|
|
76
|
-
h = Noah::Host.create(:name => host, :status => "up")
|
77
|
-
if h.save
|
78
|
-
%w[http https smtp mysql].each do |service|
|
79
|
-
s = Noah::Service.create(:name => service, :status => "pending", :host => h)
|
80
|
-
h.services << s
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
puts "Creating sample entries - Application and Configuration"
|
86
|
-
my_yaml = <<EOY
|
87
|
-
development:
|
88
|
-
database: development_database
|
89
|
-
adapter: mysql
|
90
|
-
username: dev_user
|
91
|
-
password: dev_password
|
92
|
-
EOY
|
93
|
-
my_json = <<EOJ
|
94
|
-
{
|
95
|
-
"id":"hostname",
|
96
|
-
"data":"localhost"
|
97
|
-
}
|
98
|
-
EOJ
|
99
|
-
|
100
|
-
a1 = Noah::Application.create(:name => 'myrailsapp1')
|
101
|
-
if a1.save
|
102
|
-
c1 = Noah::Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
|
103
|
-
a1.configurations << c1
|
104
|
-
end
|
105
|
-
|
106
|
-
a2 = Noah::Application.create(:name => 'myrestapp1')
|
107
|
-
if a2.save
|
108
|
-
c2 = Noah::Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
|
109
|
-
a2.configurations << c2
|
110
|
-
end
|
111
|
-
puts "Sample data populated!"
|
43
|
+
sample_data = File.expand_path(File.join("..", "spec", "support","sample_data.rb"),__FILE__)
|
44
|
+
instance_eval(File.open(sample_data).read)
|
112
45
|
end
|
113
46
|
|
114
47
|
begin
|
data/lib/noah/agent.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Noah::Agents
|
2
2
|
class Base
|
3
3
|
|
4
|
-
PREFIX = "base"
|
4
|
+
PREFIX = "base://"
|
5
5
|
NAME = "base-agent"
|
6
6
|
DEFAULT_CONCURRENCY = 1
|
7
|
+
NEEDS_TRANSFORM = false
|
7
8
|
|
8
9
|
def self.inherited(base)
|
9
10
|
Noah::Watchers.register_agent(base)
|
@@ -11,12 +12,13 @@ module Noah::Agents
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def notify(event, message, watch_list)
|
14
|
-
logger.info("#{self.class} worker initiated")
|
15
|
+
logger.info("#{self.class.to_s} worker initiated")
|
15
16
|
worklist = []
|
16
17
|
watch_list.select{|w| worklist << w[:endpoint] if (w[:endpoint] =~ /^#{self.class::PREFIX}/ && event =~ /^#{w[:pattern]}/) }
|
17
18
|
if worklist.size >= 1
|
18
19
|
logger.info("Dispatching message to #{worklist.size} #{self.class.to_s} endpoints")
|
19
20
|
EM::Iterator.new(worklist, self.class::DEFAULT_CONCURRENCY).each do |ep, iter|
|
21
|
+
ep, message = transform(ep, message) if self.class::NEEDS_TRANSFORM == true
|
20
22
|
work!(ep, message)
|
21
23
|
iter.next
|
22
24
|
end
|
data/lib/noah/app.rb
CHANGED
@@ -58,12 +58,14 @@ module Noah
|
|
58
58
|
erb :'500'
|
59
59
|
end
|
60
60
|
|
61
|
-
load File.join(File.dirname(__FILE__), '
|
62
|
-
load File.join(File.dirname(__FILE__), '
|
63
|
-
load File.join(File.dirname(__FILE__), '
|
64
|
-
load File.join(File.dirname(__FILE__), '
|
65
|
-
load File.join(File.dirname(__FILE__), '
|
66
|
-
load File.join(File.dirname(__FILE__), '
|
61
|
+
load File.join(File.dirname(__FILE__), 'routes/tags.rb')
|
62
|
+
load File.join(File.dirname(__FILE__), 'routes/hosts.rb')
|
63
|
+
load File.join(File.dirname(__FILE__), 'routes/services.rb')
|
64
|
+
load File.join(File.dirname(__FILE__), 'routes/applications.rb')
|
65
|
+
load File.join(File.dirname(__FILE__), 'routes/configurations.rb')
|
66
|
+
load File.join(File.dirname(__FILE__), 'routes/watchers.rb')
|
67
|
+
load File.join(File.dirname(__FILE__), 'routes/ephemerals.rb')
|
68
|
+
load File.join(File.dirname(__FILE__), 'routes/links.rb')
|
67
69
|
|
68
70
|
end
|
69
71
|
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Noah::Linkable
|
2
|
+
def self.included(model)
|
3
|
+
model.send :set, :links, ::Noah::Link
|
4
|
+
model.send :index, :links
|
5
|
+
end
|
6
|
+
|
7
|
+
def link!(link_name)
|
8
|
+
link = Noah::Link.find_or_create(:path => link_name)
|
9
|
+
link.nodes = self
|
10
|
+
links << link
|
11
|
+
end
|
12
|
+
|
13
|
+
def unlink!(link_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
link_arr = Array.new
|
18
|
+
self.links.sort.each {|l| link_arr << l.path} if self.links.size != 0
|
19
|
+
super.merge(:links => link_arr)
|
20
|
+
end
|
21
|
+
end
|
@@ -1,30 +1,36 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'configurations')
|
2
2
|
module Noah
|
3
3
|
class Application < Model
|
4
|
+
include Taggable
|
5
|
+
include Linkable
|
4
6
|
attribute :name
|
5
|
-
|
7
|
+
set :configurations, Configuration
|
6
8
|
|
7
9
|
index :name
|
10
|
+
index :configurations
|
8
11
|
|
9
12
|
def validate
|
10
13
|
super
|
11
14
|
assert_present :name
|
15
|
+
assert_unique :name
|
12
16
|
end
|
13
17
|
|
14
18
|
def to_hash
|
15
|
-
|
16
|
-
configurations.sort.each
|
17
|
-
|
19
|
+
cfg_hash = Hash.new
|
20
|
+
configurations.sort.each do |cfg|
|
21
|
+
cfg_hash["#{cfg.name}"] = {:format => cfg.to_hash[:format], :body => cfg.to_hash[:body]}
|
22
|
+
end
|
23
|
+
{name => {:id => id, :created_at => created_at, :updated_at => updated_at, :configurations => cfg_hash}}
|
18
24
|
end
|
19
25
|
|
20
26
|
class << self
|
21
27
|
def find_or_create(opts = {})
|
22
28
|
begin
|
23
|
-
find(opts).first.nil? ? (
|
24
|
-
if
|
25
|
-
|
29
|
+
find(opts).first.nil? ? (obj = new(opts)) : (obj = find(opts).first)
|
30
|
+
if obj.valid?
|
31
|
+
obj.save
|
26
32
|
end
|
27
|
-
|
33
|
+
obj
|
28
34
|
rescue Exception => e
|
29
35
|
e.message
|
30
36
|
end
|
@@ -35,7 +41,11 @@ module Noah
|
|
35
41
|
|
36
42
|
class Applications
|
37
43
|
def self.all(options = {})
|
38
|
-
|
44
|
+
app_hash = Hash.new
|
45
|
+
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) }
|
48
|
+
app_hash
|
39
49
|
end
|
40
50
|
end
|
41
51
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'applications')
|
1
2
|
module Noah
|
2
3
|
class Configuration < Model
|
3
|
-
|
4
|
+
include Taggable
|
5
|
+
include Linkable
|
4
6
|
attribute :name
|
5
7
|
attribute :format
|
6
8
|
attribute :body
|
7
|
-
attribute :new_record
|
8
|
-
reference :application, Application
|
9
9
|
|
10
10
|
index :name
|
11
11
|
index :format
|
@@ -16,23 +16,39 @@ module Noah
|
|
16
16
|
assert_present :name
|
17
17
|
assert_present :format
|
18
18
|
assert_present :body
|
19
|
-
|
20
|
-
assert_unique [:name, :application_id]
|
19
|
+
assert_unique :name
|
21
20
|
end
|
22
21
|
|
23
22
|
def to_hash
|
24
|
-
|
25
|
-
|
23
|
+
super.merge(:name => name, :format => format, :body => body, :created_at => created_at, :updated_at => updated_at)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Because we're not doing a 2-way relationship
|
27
|
+
# we need to clean up any applications that use
|
28
|
+
# this configuration ourself
|
29
|
+
def delete
|
30
|
+
@affected_applications = Array.new
|
31
|
+
Noah::Application.all.each do |app|
|
32
|
+
if app.configurations.member?(self)
|
33
|
+
app.configurations.delete(self)
|
34
|
+
@affected_applications << app.name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def affected_applications
|
41
|
+
@affected_applications
|
26
42
|
end
|
27
43
|
|
28
44
|
class << self
|
29
45
|
def find_or_create(opts={})
|
30
46
|
begin
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
47
|
+
find(opts).first.nil? ? (obj = new(opts)) : (obj = find(opts).first)
|
48
|
+
if obj.valid?
|
49
|
+
obj.save
|
50
|
+
end
|
51
|
+
obj
|
36
52
|
rescue Exception => e
|
37
53
|
e.message
|
38
54
|
end
|
@@ -43,7 +59,10 @@ module Noah
|
|
43
59
|
|
44
60
|
class Configurations
|
45
61
|
def self.all(options = {})
|
46
|
-
|
62
|
+
config_hash = Hash.new
|
63
|
+
options.empty? ? configs=Configuration.all.sort : configs=Configuration.find(options).sort
|
64
|
+
configs.each {|x| config_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
|
65
|
+
config_hash
|
47
66
|
end
|
48
67
|
end
|
49
68
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Noah
|
2
2
|
class Ephemeral < Model
|
3
3
|
include EphemeralValidations
|
4
|
-
|
4
|
+
include Taggable
|
5
|
+
include Linkable
|
5
6
|
attribute :path
|
6
7
|
attribute :data
|
7
8
|
attribute :lifetime
|
@@ -28,12 +29,12 @@ module Noah
|
|
28
29
|
def find_or_create(opts = {})
|
29
30
|
begin
|
30
31
|
path, data = opts[:path], opts[:data]
|
31
|
-
find(:path => path).first.nil? ? (
|
32
|
-
|
33
|
-
if
|
34
|
-
|
32
|
+
find(:path => path).first.nil? ? (obj = new(:path => path)) : (obj = find(:path => path).first)
|
33
|
+
obj.data = data
|
34
|
+
if obj.valid?
|
35
|
+
obj.save
|
35
36
|
end
|
36
|
-
|
37
|
+
obj
|
37
38
|
rescue Exception => e
|
38
39
|
e.message
|
39
40
|
end
|
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