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.
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