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.
Files changed (45) hide show
  1. data/Rakefile +2 -69
  2. data/lib/noah.rb +1 -0
  3. data/lib/noah/agent.rb +1 -0
  4. data/lib/noah/agents/base_agent.rb +4 -2
  5. data/lib/noah/agents/http_agent.rb +1 -1
  6. data/lib/noah/agents/https_agent.rb +6 -0
  7. data/lib/noah/app.rb +8 -6
  8. data/lib/noah/exceptions.rb +0 -0
  9. data/lib/noah/linkable.rb +21 -0
  10. data/lib/noah/models.rb +14 -25
  11. data/lib/noah/models/applications.rb +19 -9
  12. data/lib/noah/models/configurations.rb +32 -13
  13. data/lib/noah/models/ephemerals.rb +7 -6
  14. data/lib/noah/models/hosts.rb +11 -5
  15. data/lib/noah/models/link.rb +70 -29
  16. data/lib/noah/models/services.rb +11 -2
  17. data/lib/noah/models/tags.rb +86 -5
  18. data/lib/noah/models/watchers.rb +0 -1
  19. data/lib/noah/{application_routes.rb → routes/applications.rb} +31 -27
  20. data/lib/noah/routes/configurations.rb +77 -0
  21. data/lib/noah/{ephemeral_routes.rb → routes/ephemerals.rb} +5 -5
  22. data/lib/noah/{host_routes.rb → routes/hosts.rb} +16 -1
  23. data/lib/noah/routes/links.rb +16 -0
  24. data/lib/noah/{service_routes.rb → routes/services.rb} +28 -12
  25. data/lib/noah/routes/tags.rb +15 -0
  26. data/lib/noah/{watcher_routes.rb → routes/watchers.rb} +0 -0
  27. data/lib/noah/taggable.rb +30 -0
  28. data/lib/noah/version.rb +1 -1
  29. data/noah.gemspec +5 -4
  30. data/spec/application_spec.rb +3 -3
  31. data/spec/configuration_spec.rb +19 -12
  32. data/spec/host_spec.rb +5 -5
  33. data/spec/noahapp_application_spec.rb +11 -13
  34. data/spec/noahapp_configuration_spec.rb +63 -40
  35. data/spec/noahapp_ephemeral_spec.rb +15 -15
  36. data/spec/noahapp_host_spec.rb +4 -6
  37. data/spec/noahapp_service_spec.rb +8 -7
  38. data/spec/service_spec.rb +2 -2
  39. data/spec/spec_helper.rb +5 -5
  40. data/spec/support/sample_data.rb +87 -0
  41. data/spec/tag_spec.rb +78 -0
  42. data/views/index.haml +7 -1
  43. metadata +335 -311
  44. data/lib/noah/configuration_routes.rb +0 -81
  45. 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
- Ohm::redis.flushdb
46
- puts "Creating watchers..."
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
@@ -2,6 +2,7 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
2
2
  require 'rubygems'
3
3
  require 'noah'
4
4
  require 'noah/agents/http_agent'
5
+ require 'noah/agents/https_agent'
5
6
  require 'noah/agents/dummy_agent'
6
7
  begin
7
8
  candidates = []
@@ -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
@@ -5,7 +5,7 @@ module Noah::Agents
5
5
 
6
6
  PREFIX = "http://"
7
7
  NAME = self.class.to_s
8
- DEFAULT_CONCURRENCY = 500
8
+ DEFAULT_CONCURRENCY = 50
9
9
 
10
10
  def work!(ep, message)
11
11
  logger.info("Sending message to (#{ep})")
@@ -0,0 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), 'http_agent')
2
+ module Noah::Agents
3
+ class HttpsAgent < HttpAgent
4
+ PREFIX = "https://"
5
+ end
6
+ 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__), 'host_routes.rb')
62
- load File.join(File.dirname(__FILE__), 'service_routes.rb')
63
- load File.join(File.dirname(__FILE__), 'application_routes.rb')
64
- load File.join(File.dirname(__FILE__), 'configuration_routes.rb')
65
- load File.join(File.dirname(__FILE__), 'watcher_routes.rb')
66
- load File.join(File.dirname(__FILE__), 'ephemeral_routes.rb')
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, :tags
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.new :path => p, :source => base_pattern
46
- l.valid? ? l.save : (raise "#{l.errors}")
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, :pattern => 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 => pattern, :endpoint => endpoint
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
- "//noah/#{self.class_to_lower}s/#{n}"
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
- self.class.to_s.gsub(/(.*)::(\w)/,'\2').downcase
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
- collection :configurations, Configuration
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
- arr = []
16
- configurations.sort.each {|c| arr << c.to_hash}
17
- super.merge(:name => name, :created_at => created_at, :updated_at => updated_at, :configurations => arr)
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? ? (app = create(opts)) : (app = find(opts).first)
24
- if app.valid?
25
- app.save
29
+ find(opts).first.nil? ? (obj = new(opts)) : (obj = find(opts).first)
30
+ if obj.valid?
31
+ obj.save
26
32
  end
27
- app
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
- options.empty? ? Application.all.sort : Application.find(options).sort
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
- assert_present :application_id
20
- assert_unique [:name, :application_id]
19
+ assert_unique :name
21
20
  end
22
21
 
23
22
  def to_hash
24
- Application[application_id].nil? ? app_name=nil : app_name=Application[application_id].name
25
- super.merge(:name => name, :format => format, :body => body, :created_at => created_at, :updated_at => updated_at, :application => app_name)
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
- if find(opts).first.nil?
32
- conf = create(opts)
33
- else
34
- conf = find(opts).first
35
- end
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
- options.empty? ? Configuration.all.sort : Configuration.find(options).sort
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? ? (eph = new(:path => path)) : (eph = find(:path => path).first)
32
- eph.data = data
33
- if eph.valid?
34
- eph.save
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
- eph
37
+ obj
37
38
  rescue Exception => e
38
39
  e.message
39
40
  end