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/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.rb
CHANGED
@@ -17,6 +17,7 @@ require 'yaml'
|
|
17
17
|
require 'sinatra/base'
|
18
18
|
|
19
19
|
require File.join(File.dirname(__FILE__), 'noah', 'log')
|
20
|
+
require File.join(File.dirname(__FILE__), 'noah', 'exceptions')
|
20
21
|
require File.join(File.dirname(__FILE__), 'noah', 'custom_watcher')
|
21
22
|
require File.join(File.dirname(__FILE__), 'noah','validations')
|
22
23
|
require File.join(File.dirname(__FILE__), 'noah','models')
|
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
|
data/lib/noah/models.rb
CHANGED
@@ -10,8 +10,7 @@ module Noah
|
|
10
10
|
model.send :include, Ohm::Callbacks
|
11
11
|
model.send :include, Ohm::ExtraValidations
|
12
12
|
|
13
|
-
model.send :attribute, :
|
14
|
-
model.send :index, :tag
|
13
|
+
model.send :attribute, :metadata
|
15
14
|
|
16
15
|
# removing this as it's simply redundant
|
17
16
|
# model.after :save, :notify_via_redis_save
|
@@ -33,30 +32,24 @@ module Noah
|
|
33
32
|
self.created_at == self.updated_at
|
34
33
|
end
|
35
34
|
|
36
|
-
def tag(tags = self.tags)
|
37
|
-
tags.to_s.split(/\s*,\s*/).uniq
|
38
|
-
end
|
39
|
-
|
40
35
|
def link!(path)
|
41
36
|
base_pattern = "#{self.patternize_me}"
|
42
37
|
path.nil? ? (raise ArgumentError, "Must provide a path") : p=path
|
43
38
|
|
44
39
|
begin
|
45
|
-
l = Link.
|
46
|
-
l.
|
47
|
-
l.name
|
40
|
+
l = Link.find_or_create :path => p
|
41
|
+
l.nodes = self
|
48
42
|
rescue Exception => e
|
49
43
|
e.message
|
50
44
|
end
|
51
45
|
end
|
52
46
|
|
53
|
-
def watch!(opts={:endpoint => nil
|
47
|
+
def watch!(opts={:endpoint => nil})
|
54
48
|
base_pattern = "#{self.patternize_me}"
|
55
49
|
opts[:endpoint].nil? ? (raise ArgumentError, "Need an endpoint") : endpoint=opts[:endpoint]
|
56
|
-
opts[:pattern].nil? ? pattern=base_pattern : pattern=opts[:pattern]
|
57
50
|
|
58
51
|
begin
|
59
|
-
w = Watcher.new :pattern =>
|
52
|
+
w = Watcher.new :pattern => base_pattern, :endpoint => endpoint
|
60
53
|
w.valid? ? w.save : (raise "#{w.errors}")
|
61
54
|
w.name
|
62
55
|
rescue Exception => e
|
@@ -65,17 +58,18 @@ module Noah
|
|
65
58
|
end
|
66
59
|
|
67
60
|
protected
|
68
|
-
def patternize_me
|
61
|
+
def patternize_me(opts = {:namespace => nil})
|
62
|
+
opts[:namespace].nil? ? namespace="//noah/#{self.class_to_lower}s" : namespace="//noah/#{opts[:namespace]}/#{self.class_to_lower}s"
|
69
63
|
name.match(/^\//) ? n = name.gsub(/^\//, '') : n = name
|
70
|
-
"
|
64
|
+
"#{namespace}/#{n}"
|
71
65
|
end
|
72
66
|
|
73
67
|
def stash_name
|
74
68
|
@deleted_name = self.name
|
75
69
|
end
|
76
70
|
|
77
|
-
def class_to_lower
|
78
|
-
|
71
|
+
def class_to_lower(class_name = self.class.to_s)
|
72
|
+
class_name.gsub(/(.*)::(\w)/,'\2').downcase
|
79
73
|
end
|
80
74
|
|
81
75
|
def dbnum
|
@@ -85,15 +79,6 @@ module Noah
|
|
85
79
|
o[:db].nil? ? "#{o[:url].split('/').last}" : "#{o[:db]}"
|
86
80
|
end
|
87
81
|
|
88
|
-
def before_update
|
89
|
-
return if new?
|
90
|
-
tag(read_remote(:tags)).map(&Tag).each {|t| t.decr :total}
|
91
|
-
end
|
92
|
-
|
93
|
-
def after_save
|
94
|
-
tag.map(&Tag).each {|t| t.incr :total }
|
95
|
-
end
|
96
|
-
|
97
82
|
["create", "update", "delete"].each do |meth|
|
98
83
|
class_eval do
|
99
84
|
define_method("notify_via_redis_#{meth}".to_sym) do
|
@@ -126,7 +111,11 @@ module Noah
|
|
126
111
|
|
127
112
|
end
|
128
113
|
|
114
|
+
require File.join(File.dirname(__FILE__), 'linkable')
|
115
|
+
require File.join(File.dirname(__FILE__), 'models','link')
|
116
|
+
require File.join(File.dirname(__FILE__), 'taggable')
|
129
117
|
require File.join(File.dirname(__FILE__), 'models','tags')
|
118
|
+
require File.join(File.dirname(__FILE__), 'models','link')
|
130
119
|
require File.join(File.dirname(__FILE__), 'models','hosts')
|
131
120
|
require File.join(File.dirname(__FILE__), 'models','services')
|
132
121
|
require File.join(File.dirname(__FILE__), 'models','applications')
|
@@ -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
|