auser-poolparty 1.2.8 → 1.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/VERSION.yml +1 -1
  2. data/bin/cloud-list +4 -4
  3. data/bin/cloud-provision +2 -0
  4. data/bin/cloud-ssh +1 -1
  5. data/bin/install-poolparty +1 -1
  6. data/examples/fairchild.rb +26 -17
  7. data/examples/metavirt_cloud.rb +2 -4
  8. data/lib/poolparty.rb +2 -7
  9. data/lib/poolparty/core/array.rb +1 -1
  10. data/lib/poolparty/core/exception.rb +1 -1
  11. data/lib/poolparty/core/hash.rb +12 -5
  12. data/lib/poolparty/core/integer.rb +11 -0
  13. data/lib/poolparty/core/object.rb +14 -0
  14. data/lib/poolparty/core/string.rb +6 -1
  15. data/lib/poolparty/core/time.rb +6 -0
  16. data/lib/poolparty/extra/duration.rb +96 -0
  17. data/lib/poolparty/helpers/binary.rb +1 -1
  18. data/lib/poolparty/modules/cloud_resourcer.rb +1 -1
  19. data/lib/poolparty/modules/definable_resource.rb +5 -7
  20. data/lib/poolparty/modules/output.rb +2 -2
  21. data/lib/poolparty/monitors/base_monitor.rb +17 -0
  22. data/lib/poolparty/net/init.rb +4 -11
  23. data/lib/poolparty/net/remote_instance.rb +5 -0
  24. data/lib/poolparty/net/remoter/connections.rb +14 -11
  25. data/lib/poolparty/net/remoter/interactive.rb +13 -2
  26. data/lib/poolparty/net/remoter_base.rb +9 -4
  27. data/lib/poolparty/net/remoter_bases/ec2/ec2.rb +50 -35
  28. data/lib/poolparty/net/remoter_bases/ec2/ec2_remote_instance.rb +46 -5
  29. data/lib/poolparty/net/remoter_bases/ec2/ec2_response_object.rb +57 -1
  30. data/lib/poolparty/plugins/apache2/apache.rb +13 -160
  31. data/lib/poolparty/plugins/apache2/passenger_site.rb +86 -0
  32. data/lib/poolparty/plugins/apache2/php5.rb +40 -0
  33. data/lib/poolparty/plugins/apache2/virtual_host.rb +53 -0
  34. data/lib/poolparty/plugins/authorized_key.rb +2 -2
  35. data/lib/poolparty/plugins/bind.rb +5 -6
  36. data/lib/poolparty/plugins/{chef.rb → chef/chef.rb} +22 -18
  37. data/lib/poolparty/plugins/{chef_deploy.rb → chef/chef_deploy.rb} +20 -19
  38. data/lib/poolparty/plugins/deploy_directory.rb +2 -3
  39. data/lib/poolparty/plugins/gem_package.rb +6 -12
  40. data/lib/poolparty/plugins/git.rb +22 -7
  41. data/lib/poolparty/{base_packages → plugins}/haproxy.rb +2 -2
  42. data/lib/poolparty/{base_packages → plugins}/heartbeat.rb +7 -7
  43. data/lib/poolparty/plugins/line_in_file.rb +4 -2
  44. data/lib/poolparty/plugins/plugin_template.rb +13 -0
  45. data/lib/poolparty/{base_packages/poolparty.rb → plugins/poolparty_base_packages.rb} +2 -2
  46. data/lib/poolparty/plugins/rails_deploy.rb +2 -3
  47. data/lib/poolparty/{base_packages → plugins}/ruby.rb +3 -3
  48. data/lib/poolparty/{base_packages → plugins}/runit.rb +3 -3
  49. data/lib/poolparty/plugins/svn.rb +8 -6
  50. data/lib/poolparty/poolparty/cloud.rb +5 -8
  51. data/lib/poolparty/poolparty/default.rb +1 -1
  52. data/lib/poolparty/poolparty/plugin.rb +36 -15
  53. data/lib/poolparty/poolparty/pool.rb +6 -2
  54. data/lib/poolparty/poolparty/poolparty_base_class.rb +5 -11
  55. data/lib/poolparty/poolparty/resource.rb +2 -1
  56. data/lib/poolparty/poolparty/service.rb +6 -8
  57. data/lib/poolparty/provision/dr_configure.rb +3 -3
  58. data/lib/poolparty/verification/verifier_base.rb +10 -0
  59. data/spec/bin/server-list-active_spec.rb +1 -3
  60. data/spec/poolparty/core/string_spec.rb +1 -1
  61. data/spec/poolparty/dependency_resolver/chef_resolver_spec.rb +0 -2
  62. data/spec/poolparty/dependency_resolver/dependency_resolver_cloud_extensions_spec.rb +16 -13
  63. data/spec/poolparty/extra/deployments_spec.rb +68 -68
  64. data/spec/poolparty/net/remoter_bases/ec2_spec.rb +1 -0
  65. data/spec/poolparty/plugins/deploydirectory_spec.rb +64 -51
  66. data/spec/poolparty/poolparty/cloud_spec.rb +21 -19
  67. data/spec/poolparty/poolparty/configurers/files/ruby_basic.rb +1 -1
  68. data/spec/poolparty/poolparty/configurers/files/ruby_plugins.rb +1 -1
  69. data/spec/poolparty/{base_packages → poolparty}/haproxy_spec.rb +1 -1
  70. data/spec/poolparty/{base_packages → poolparty}/heartbeat_spec.rb +1 -1
  71. data/spec/poolparty/poolparty/plugin_model_spec.rb +6 -13
  72. data/spec/poolparty/poolparty/plugin_spec.rb +7 -7
  73. data/spec/poolparty/poolparty/resource_spec.rb +15 -5
  74. data/spec/poolparty/poolparty/test_plugins/webserver.rb +27 -23
  75. data/test/fixtures/metavirt_cloud.json +1 -0
  76. data/test/poolparty/dependency_resolver/puppet_resolver_test.rb +0 -5
  77. data/test/poolparty/modules/cloud_dsl_test.rb +1 -1
  78. data/test/poolparty/monitors/test_base_monitor.rb +17 -0
  79. data/test/poolparty/monitors/test_monitor_rack.rb +39 -0
  80. data/test/poolparty/net/remoter_base_test.rb +18 -0
  81. data/test/poolparty/plugins/chef_deploy_test.rb +1 -1
  82. data/test/poolparty/plugins/rails_deploy_test.rb +3 -3
  83. data/test/poolparty/poolparty/cloud_test.rb +27 -2
  84. data/test/poolparty/poolparty/isolated_cloud_test.rb +25 -0
  85. data/test/poolparty/poolparty/plugin_test.rb +9 -8
  86. data/test/poolparty/poolparty/schema_test.rb +13 -0
  87. data/test/poolparty/verification/verify_test.rb +4 -0
  88. data/test/test_helper.rb +10 -3
  89. data/test/test_methods.rb +11 -0
  90. data/vendor/gems/dslify/test/dslify_test.rb +28 -0
  91. metadata +29 -15
  92. data/lib/poolparty/extra/deployments.rb +0 -31
  93. data/lib/poolparty/poolparty/plugin_model.rb +0 -46
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 2
3
- :patch: 8
3
+ :patch: 9
4
4
  :major: 1
@@ -17,21 +17,21 @@ EOS
17
17
 
18
18
  short_desc "show a list of the current instances on the clouds"
19
19
 
20
- run do |command|
20
+ run do |command|
21
21
  @loaded_clouds.each do |cld|
22
22
  if command[:instance_id]
23
23
  require 'pp'
24
- pp result = cld.describe_instance(:instance_id=>command[:instance_id])
24
+ pp result = cld.nodes(:instance_id=>command[:instance_id])
25
25
  else
26
26
  puts "Listing cloud #{cld.name}"
27
27
  puts "Active instances"
28
28
  puts cld.nodes(:status => "running").map{|a| "#{a[:instance_id] || a[:id]}\t#{a[:ip] ||a[:public_ip] }" }.join("\n")
29
-
29
+
30
30
  if cld.nodes(:status => "pending").size > 0
31
31
  puts "Pending instances"
32
32
  puts cld.nodes(:status => "pending").map{|a| "#{a[:instance_id] || a[:id]}\t#{a[:ip] ||a[:public_ip] }" }.join("\n")
33
33
  end
34
34
  end
35
- end
35
+ end
36
36
  end
37
37
  end
@@ -26,11 +26,13 @@ EOS
26
26
  address = cld.nodes[ command[:inst_num] ]
27
27
  ::PoolParty::Provision::BootStrapper.new( address[:ip], :cloud => cld )
28
28
  ::PoolParty::Provision::DrConfigure.new( address[:ip], :cloud => cld )
29
+ cld.call_after_provision_callbacks
29
30
  else
30
31
  cld.nodes(:status => "running").each do |address|
31
32
  cld.vputs "\nConfiguring: #{address[:ip]}\n--------------------"
32
33
  ::PoolParty::Provision::BootStrapper.new( address[:ip], :cloud => cld )
33
34
  ::PoolParty::Provision::DrConfigure.new( address[:ip], :cloud => cld )
35
+ cld.call_after_provision_callbacks
34
36
  end
35
37
  end
36
38
  end
@@ -21,7 +21,7 @@ EOS
21
21
 
22
22
  if !nodes.empty?
23
23
  n = command[:inst_num] ? command[:inst_num].to_i : 0
24
- @cloud.ssh_into( nodes[n].ip ) if @cloud
24
+ @cloud.ssh_into( nodes[n].ip || nodes[n].public_ip ) if @cloud
25
25
  else
26
26
  puts "No running instances can be found"
27
27
  end
@@ -9,7 +9,7 @@ say("\nWhat remoter base would you like to use?")
9
9
  choose do |menu|
10
10
  menu.prompt = "> "
11
11
 
12
- available_bases.each do |base|
12
+ PoolParty::Remote::RemoterBase.available_bases.each do |base|
13
13
  menu.choice base.to_sym do
14
14
 
15
15
  say "Great, we'll be using #{base}"
@@ -1,27 +1,36 @@
1
+ require 'rubygems'
2
+ $:.unshift "#{File.dirname(__FILE__)}/../lib"
3
+ require "poolparty"
4
+
1
5
  # Basic pool spec
2
6
  # Shows global settings for the clouds
3
- pool :application do
7
+ pool :party do
4
8
  instances 1..3
5
- ami 'ami-7cfd1a15'
9
+ image_id 'ami-7cfd1a15'
10
+ debugging true
6
11
 
7
- cloud :example_one do
8
- keypair 'front'
9
- has_directory "/var/www"
10
-
11
- has_file "/etc/motd",
12
- :content => "Welcome to LARubyConf"
13
- has_file :name => "/var/www/index.html" do
14
- content "<h1>Welcome to your new poolparty instance</h1>"
15
- mode 0644
16
- owner "www-data"
12
+ access_key "XXXXXX"
13
+ secret_access_key "XXXXXXX"
14
+
15
+ cloud :app do
16
+ keypair 'app'
17
+ using :ec2 do
18
+ image_id 'ami-7cfd1a15'
19
+ availability_zone 'us-east-1c'
17
20
  end
18
21
 
19
- has_git_repo "paparazzi" do
20
- source "git://github.com/auser/paparazzi.git"
21
- at "/var/www"
22
- end
22
+ has_file "/etc/motd", :content => "Welcome to LARubyConf"
23
+ # has_directory "/var/www"
24
+ # has_file :name => "/var/www/index.html" do
25
+ # content "<h1>Welcome to your new poolparty instance</h1>"
26
+ # mode 0644
27
+ # owner "www-data"
28
+ # end
23
29
 
24
- apache
30
+ # has_git "paparazzi" do
31
+ # source "git://github.com/auser/paparazzi.git"
32
+ # dir "/var/www"
33
+ # end
25
34
 
26
35
  end
27
36
 
@@ -5,17 +5,15 @@ require "poolparty"
5
5
  pool :multiverse do
6
6
 
7
7
  cloud :vv do
8
- keypair "front"
9
8
  instances 2
10
9
  has_file "/etc/motd", :content => "Welcome to your poolparty instance!"
11
10
  using :metavirt do
12
- server_config({:host=>"172.16.68.1", :port=>3000})
11
+ server_config({:host=>"192.168.248.1", :port=>3000})
13
12
  authorized_keys 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCTppECfx7Tb0zoviRfqFaePyAek6+ZktKkHiTHu/jkhG1s4q1oHEe89no21xLxuReyJrDlNe8rLxxZzoYCaAWRdhcqMR3BNqb2w2jpF4pH+bFj0557KrwWP6HSNpRRkyYhxLqZbuH/2t3TzkPevZbcfSYa09jIzqnmTruh9l1s+n5E3cNr/RDdDn7tv3Ok7mKN7GEjkK7F83Pt9xviHevg22xqzm99nS+hg6Kl/fQUTO6pOmC5x+9V47RJz1+9WdhGJ7M83zijX9rMnAwrR5LFoL6aZyyU0G71SpoIL5e8XD/jt1WNKFJOfG8YMLb3i03UABm/Q5Q30+R7UoRxSWRX'
14
13
  using :vmrun do
15
14
  # vmx_files Dir[::File.expand_path("~/Documents/Virtual Machines.localized/metavirts/*/*.vmx")]
16
15
  vmx_files [
17
- "/Users/mfairchild/Documents/Virtual\ Machines.localized/Ubuntu-jaunty.vmwarevm/Ubuntu-jaunty.vmx",
18
- "/Users/mfairchild/Documents/Virtual\ Machines.localized/metavirts/Ubuntu32bitVM copy.vmwarevm/Ubuntu32bitVM.vmx"
16
+ "/Users/alerner/Documents/vm/Ubuntu32bitVM.vmwarevm/Ubuntu32bitVM.vmx"
19
17
  ]
20
18
  end
21
19
  end
@@ -2,7 +2,7 @@ $LOAD_PATH<< File.dirname(__FILE__)
2
2
  # Load required gems
3
3
  #TODO: remove activesupport
4
4
  @required_software = Array.new
5
- %w(rubygems activesupport ftools logging resolv digest/sha2 json pp).each do |lib|
5
+ %w(rubygems fileutils resolv digest/sha2 json pp).each do |lib|
6
6
  begin
7
7
  require lib
8
8
  rescue Exception => e
@@ -75,7 +75,7 @@ $_poolparty_load_directories = [
75
75
  "dependency_resolver",
76
76
  "aska.rb",
77
77
  "config",
78
- "monitors/monitor_rack",
78
+ "monitors/monitor_rack.rb",
79
79
  "capistrano.rb",
80
80
  'provisioners/provisioner_base.rb',
81
81
  'provisioners/capistrano/capistrano.rb',
@@ -132,14 +132,9 @@ class Object
132
132
  include PoolParty
133
133
  include PoolParty::Pool
134
134
  include PoolParty::Cloud
135
-
136
135
  include PoolParty::DefinableResource
137
136
  end
138
137
 
139
- class Class
140
- include PoolParty::PluginModel
141
- end
142
-
143
138
  ## Load PoolParty Plugins and package
144
139
  module PoolParty
145
140
  %w(plugins base_packages).each do |dir|
@@ -34,7 +34,7 @@ class Array
34
34
  def select_with_hash(conditions={})
35
35
  return self if conditions.empty?
36
36
  select do |node|
37
- conditions.any? do |k,v|
37
+ conditions.any? do |k,v|
38
38
  ( node.has_key?(k) && node[k]==v ) or ( node.respond_to?(k) && node.send(k)==v )
39
39
  end
40
40
  end
@@ -2,7 +2,7 @@
2
2
  Exception overloads
3
3
  =end
4
4
  class Exception
5
- alias nice_message to_str
5
+ alias :nice_message :to_s
6
6
  # Gives us a nice_message for exceptions
7
7
  def nice_message(padding="")
8
8
  "#{padding}#{message}\n#{padding}"# + backtrace.join("\n#{padding}")
@@ -97,17 +97,24 @@ class Hash
97
97
  self
98
98
  end
99
99
 
100
- def symbolize_keys
101
- dup.stringify_keys!
100
+ def symbolize_keys(key_modifier=nil)
101
+ dup.symbolize_keys!(key_modifier)
102
102
  end
103
103
 
104
104
  # Converts all of the keys to strings
105
- def symbolize_keys!
105
+ # can pass in a :key_modifier that will be sent to each key, before being symbolized.
106
+ # This can be usefull if you want to downcase, or snake_case each key.
107
+ # >> {'Placement' => {'AvailabilityZone'=>"us-east-1a"} }.symbolize_keys(:snake_case)
108
+ # => {:placement=>{:availability_zone=>"us-east-1a"}}
109
+ def symbolize_keys!(key_modifier=nil)
106
110
  keys.each{|k|
107
111
  v = delete(k)
112
+ if key_modifier && k.respond_to?(key_modifier)
113
+ k = k.send(key_modifier)
114
+ end
108
115
  self[k.to_sym] = v
109
- v.symbolize_keys! if v.is_a?(Hash)
110
- v.each{|p| p.symbolize_keys! if p.is_a?(Hash)} if v.is_a?(Array)
116
+ v.symbolize_keys!(key_modifier) if v.is_a?(Hash)
117
+ v.each{|p| p.symbolize_keys!(key_modifier) if p.is_a?(Hash)} if v.is_a?(Array)
111
118
  }
112
119
  self
113
120
  end
@@ -0,0 +1,11 @@
1
+ class Integer
2
+ def months
3
+ PoolParty::Duration.new(self * 30.days, [[:months, self]])
4
+ end
5
+ alias :month :months
6
+
7
+ def years
8
+ PoolParty::Duration.new(self * 365.25.days, [[:years, self]])
9
+ end
10
+ alias :year :years
11
+ end
@@ -106,4 +106,18 @@ class Object
106
106
  def unix_hide_string
107
107
  "2>&1 > /dev/null"
108
108
  end
109
+
110
+ # Get object's meta (ghost, eigenclass, singleton) class
111
+ # from activesupport
112
+ def metaclass
113
+ class << self
114
+ self
115
+ end
116
+ end
117
+
118
+ # If class_eval is called on an object, add those methods to its metaclass
119
+ # from activesupport
120
+ def class_eval(*args, &block)
121
+ metaclass.class_eval(*args, &block)
122
+ end
109
123
  end
@@ -60,7 +60,7 @@ class String
60
60
  # Refactor this guy to get the class if the class is defined, and not always create a new one
61
61
  # although, it doesn't really matter as ruby will just reopen the class
62
62
  def class_constant(superclass=nil, opts={}, &block)
63
- symc = ((opts && opts[:preserve]) ? ("#{self.camelcase}Class") : "PoolParty#{self.camelcase}Class").classify
63
+ symc = ((opts && opts[:preserve]) ? ("#{self.camelcase}") : "PoolParty#{self.camelcase}").classify
64
64
 
65
65
  kla=<<-EOE
66
66
  class #{symc} #{"< #{superclass}" if superclass}
@@ -203,5 +203,10 @@ class String
203
203
  result.symbolize_keys!
204
204
  end
205
205
  end
206
+
207
+ # dumb and ugly pluralize
208
+ def pluralize(count=2)
209
+ count > 1 ? self + "s" : self
210
+ end
206
211
 
207
212
  end
@@ -53,4 +53,10 @@ class Numeric
53
53
  in_units = (seconds / 1.send(unit))
54
54
  "#{in_units.to_i} #{in_units != 1 ? unit.to_s.pluralize : unit} ago"
55
55
  end
56
+ end
57
+
58
+ class Time
59
+ def to_time
60
+ self
61
+ end
56
62
  end
@@ -0,0 +1,96 @@
1
+ module PoolParty
2
+ # Provides accurate date and time measurements using Date#advance and
3
+ # Time#advance, respectively. It mainly supports the methods on Numeric,
4
+ # such as in this example:
5
+ #
6
+ # 1.month.ago # equivalent to Time.now.advance(:months => -1)
7
+ class Duration
8
+ attr_accessor :value, :parts
9
+
10
+ def initialize(value, parts) #:nodoc:
11
+ @value, @parts = value, parts
12
+ end
13
+
14
+ # Adds another Duration or a Numeric to this Duration. Numeric values
15
+ # are treated as seconds.
16
+ def +(other)
17
+ if Duration === other
18
+ Duration.new(value + other.value, @parts + other.parts)
19
+ else
20
+ Duration.new(value + other, @parts + [[:seconds, other]])
21
+ end
22
+ end
23
+
24
+ # Subtracts another Duration or a Numeric from this Duration. Numeric
25
+ # values are treated as seconds.
26
+ def -(other)
27
+ self + (-other)
28
+ end
29
+
30
+ def -@ #:nodoc:
31
+ Duration.new(-value, parts.map { |type,number| [type, -number] })
32
+ end
33
+
34
+ def is_a?(klass) #:nodoc:
35
+ klass == Duration || super
36
+ end
37
+
38
+ # Returns true if <tt>other</tt> is also a Duration instance with the
39
+ # same <tt>value</tt>, or if <tt>other == value</tt>.
40
+ def ==(other)
41
+ if Duration === other
42
+ other.value == value
43
+ else
44
+ other == value
45
+ end
46
+ end
47
+
48
+ def self.===(other) #:nodoc:
49
+ other.is_a?(Duration) rescue super
50
+ end
51
+
52
+ # Calculates a new Time or Date that is as far in the future
53
+ # as this Duration represents.
54
+ def since(time = ::Time.current)
55
+ sum(1, time)
56
+ end
57
+ alias :from_now :since
58
+
59
+ # Calculates a new Time or Date that is as far in the past
60
+ # as this Duration represents.
61
+ def ago(time = ::Time.current)
62
+ sum(-1, time)
63
+ end
64
+ alias :until :ago
65
+
66
+ def inspect #:nodoc:
67
+ consolidated = parts.inject(::Hash.new(0)) { |h,part| h[part.first] += part.last; h }
68
+ [:years, :months, :days, :minutes, :seconds].map do |length|
69
+ n = consolidated[length]
70
+ "#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero?
71
+ end.compact.to_sentence
72
+ end
73
+
74
+ protected
75
+
76
+ def sum(sign, time = ::Time.current) #:nodoc:
77
+ parts.inject(time) do |t,(type,number)|
78
+ if t.acts_like?(:time) || t.acts_like?(:date)
79
+ if type == :seconds
80
+ t.since(sign * number)
81
+ else
82
+ t.advance(type => sign * number)
83
+ end
84
+ else
85
+ raise ::ArgumentError, "expected a time or date, got #{time.inspect}"
86
+ end
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def method_missing(method, *args, &block) #:nodoc:
93
+ value.send(method, *args)
94
+ end
95
+ end
96
+ end
@@ -1,4 +1,4 @@
1
- require "ftools"
1
+ require "fileutils"
2
2
  module PoolParty
3
3
 
4
4
  # Load a file that contains a pool into memory
@@ -6,7 +6,7 @@
6
6
 
7
7
  method is stored, for instance. It's also where the key convenience methods are written
8
8
  =end
9
- require "ftools"
9
+ require "fileutils"
10
10
 
11
11
  module PoolParty
12
12
  module CloudResourcer
@@ -19,6 +19,9 @@ module PoolParty
19
19
  name.to_s.new_resource_class &block
20
20
  end
21
21
 
22
+ # DEPRICATED
23
+ # use plugin instead
24
+ #
22
25
  # Allow us to create virtual resources
23
26
  # Generally, in plugins
24
27
  # This sets a virtual resource against the Resource class
@@ -41,13 +44,8 @@ module PoolParty
41
44
  #
42
45
  # An example is included in the poolparty-apache-plugin
43
46
  def virtual_resource(name=:virtual_resource, opts={}, &block)
44
- symc = "#{name}".top_level_class.camelcase
45
- klass = symc.class_constant(PoolParty::Plugin::Plugin, {:preserve => true}, &block)
46
-
47
- PoolParty::Service.add_has_and_does_not_have_methods_for(symc)
48
-
49
- klass.module_eval &block if block
50
- klass
47
+ $stderr.puts "virtual_resource (#{name}) is depricated"
48
+ plugin(name, &block)
51
49
  end
52
50
 
53
51
  end
@@ -6,8 +6,8 @@ module PoolParty
6
6
  args.each do |line|
7
7
  (output ||= []) << line
8
8
  end
9
- end
10
- end
9
+ end
10
+ end
11
11
 
12
12
  end
13
13
  end
@@ -5,12 +5,28 @@
5
5
  monitors
6
6
  =end
7
7
  module Monitors
8
+
9
+ @available_monitors =[]
10
+ def self.available
11
+ @available_monitors
12
+ end
13
+
8
14
  class BaseMonitor
9
15
 
16
+ def self.inherited(subclass)
17
+ unless Monitors.available.include?(subclass)
18
+ Monitors.available << subclass
19
+ end
20
+ end
21
+
10
22
  def initialize(env=nil)
11
23
  @env=env
12
24
  end
13
25
 
26
+ def env(env=@env)
27
+ @env=env
28
+ end
29
+
14
30
  %w(close).each do |event|
15
31
  %w(before after).each do |time|
16
32
  module_eval <<-EOE
@@ -28,5 +44,6 @@ module Monitors
28
44
  def after_close_callbacks
29
45
  @after_close_callbacks ||= []
30
46
  end
47
+
31
48
  end
32
49
  end