noah 0.4-jruby → 0.6.pre-jruby
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/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
|