noah 0.4 → 0.6.pre

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