noah 0.4 → 0.6.pre

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/agent.rb +1 -0
  3. data/lib/noah/agents/base_agent.rb +4 -2
  4. data/lib/noah/agents/http_agent.rb +1 -1
  5. data/lib/noah/agents/https_agent.rb +6 -0
  6. data/lib/noah/app.rb +8 -6
  7. data/lib/noah/exceptions.rb +0 -0
  8. data/lib/noah/linkable.rb +21 -0
  9. data/lib/noah/models/applications.rb +19 -9
  10. data/lib/noah/models/configurations.rb +32 -13
  11. data/lib/noah/models/ephemerals.rb +7 -6
  12. data/lib/noah/models/hosts.rb +11 -5
  13. data/lib/noah/models/link.rb +70 -29
  14. data/lib/noah/models/services.rb +11 -2
  15. data/lib/noah/models/tags.rb +86 -5
  16. data/lib/noah/models/watchers.rb +0 -1
  17. data/lib/noah/models.rb +14 -25
  18. data/lib/noah/{application_routes.rb → routes/applications.rb} +31 -27
  19. data/lib/noah/routes/configurations.rb +77 -0
  20. data/lib/noah/{ephemeral_routes.rb → routes/ephemerals.rb} +5 -5
  21. data/lib/noah/{host_routes.rb → routes/hosts.rb} +16 -1
  22. data/lib/noah/routes/links.rb +16 -0
  23. data/lib/noah/{service_routes.rb → routes/services.rb} +28 -12
  24. data/lib/noah/routes/tags.rb +15 -0
  25. data/lib/noah/{watcher_routes.rb → routes/watchers.rb} +0 -0
  26. data/lib/noah/taggable.rb +30 -0
  27. data/lib/noah/version.rb +1 -1
  28. data/lib/noah.rb +1 -0
  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 +23 -16
  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/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
@@ -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
@@ -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
- arr = []
25
- services.sort.each {|s| arr << s.to_hash}
26
- h = {:name => name, :status => status, :created_at => created_at, :updated_at => updated_at, :services => arr}
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
- options.empty? ? Noah::Host.all.sort : Noah::Host.find(options).sort
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
@@ -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
- list :nodes, LinkMember
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
- # Nothing to see yet.
14
- # This will be for creating "overlays" or "link" relationships
15
- # between arbitrary objects or modeling your data the way you want.
16
- #
17
- # Example:
18
- # path = "/myservers"
19
- # path.nodes = ["/applications/myapp","/some/ephemeral/path", "sometag"]
20
- #
21
- # would result in a structure like:
22
- # path/
23
- # applications/
24
- # myapp
25
- # some/ephemeral/path/
26
- # child1
27
- # child2
28
- # child3
29
- # sometag/
30
- # tagged_item1
31
- # tagged_item2
32
- # tagged_item4
33
- # tagged_item5
34
- #
35
- # The idea is to create a blended view across opinionated, tagged and
36
- # ephemeral nodes.
37
- #
38
- # Almost a "choose your own model" thing.
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
@@ -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
- options.empty? ? Service.all.sort : Service.find(options).sort
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
@@ -1,13 +1,94 @@
1
1
  module Noah
2
+
2
3
  class Tag < Model
3
- counter :total
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
- def name
6
- @name = id
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
- def self.[](id)
10
- super(encode(id)) || create(:id => encode(id))
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
 
@@ -1,4 +1,3 @@
1
- require 'digest/sha1'
2
1
  module Noah
3
2
  class Watcher < Model
4
3
  include WatcherValidations