inari 0.1.0 → 0.1.1

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.
data/Rakefile CHANGED
@@ -4,10 +4,11 @@ require 'rake/testtask'
4
4
  require 'rake/rdoctask'
5
5
  require 'rake/gempackagetask'
6
6
  require 'inari/version'
7
+ require 'rake/contrib/rubyforgepublisher'
7
8
 
8
9
  desc 'Run the functional and unit tests.'
9
10
  Rake::TestTask.new(:test) do |t|
10
- t.test_files = FileList['test/*_test.rb']
11
+ t.test_files = FileList['test/*_test.rb'] + FileList['test/*/*_test.rb']
11
12
  t.verbose = true
12
13
  end
13
14
 
@@ -23,11 +24,11 @@ end
23
24
 
24
25
  task :default => :test
25
26
 
26
- Spec = Gem::Specification.new do |s|
27
+ spec = Gem::Specification.new do |s|
27
28
  s.name = 'inari'
28
29
  s.version = Inari::INARI_VERSION
29
30
  s.date = Inari::INARI_RELEASE_DATE
30
- s.summary = 'Inari is a ruby system monitoring program.'
31
+ s.summary = 'Inari is a system monitoring program.'
31
32
  s.email = 'alex@helicoid.net'
32
33
  s.homepage = Inari::UPSTREAM_URL
33
34
  s.rubyforge_project = 'inari'
@@ -38,7 +39,7 @@ Spec = Gem::Specification.new do |s|
38
39
  s.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
39
40
  s.test_files = Dir['test/test_*.rb']
40
41
  s.requirements = ['logger']
41
- s.post_install_message = <<EOF
42
+ """s.post_install_message = <<EOF
42
43
 
43
44
  Welcome to Inari
44
45
  ================
@@ -51,12 +52,25 @@ Take a look at README for help on writing configuration files.
51
52
 
52
53
  http://inari.rubyforge.org
53
54
 
54
- EOF
55
+ EOF"""
55
56
 
56
57
  end
57
58
 
58
59
  task :gem => [:test]
59
- Rake::GemPackageTask.new(Spec) do |p|
60
+ Rake::GemPackageTask.new(spec) do |p|
61
+ p.gem_spec = spec
60
62
  p.need_tar = true
63
+ p.need_zip = true
61
64
  end
62
65
 
66
+ desc 'Publish the release files to RubyForge.'
67
+ task :release => [:package] do
68
+ `rubyforge login`
69
+
70
+ for ext in %w(gem tgz zip)
71
+ pub = Rake::SshFilePublisher.new('alex_young@rubyforge.org',
72
+ '/var/www/gforge-projects/inari',
73
+ "pkg/inari-#{Inari::INARI_VERSION}.#{ext}")
74
+ pub.upload
75
+ end
76
+ end
@@ -5,10 +5,13 @@ require 'socket'
5
5
  require 'net/smtp'
6
6
  require 'timeout'
7
7
  require 'singleton'
8
- require 'logger'
8
+ require 'digest'
9
+ require 'digest/md5'
9
10
  require 'tmpdir'
11
+ require 'logger'
10
12
 
11
13
  # Inari's classes and modules
14
+ require 'inari/misc'
12
15
  require 'inari/daemon'
13
16
  require 'inari/commands'
14
17
  require 'inari/task_manager'
@@ -41,4 +44,4 @@ module Inari
41
44
  logger.info '*** Inari stopped'
42
45
  end
43
46
  end
44
- end
47
+ end
@@ -1,6 +1,3 @@
1
- # The response object
2
- require 'inari/response'
3
-
4
1
  # The command drivers
5
2
  require 'inari/commands/http'
6
3
  require 'inari/commands/snmp'
@@ -10,6 +7,9 @@ require 'inari/commands/tcp_simple'
10
7
  require 'inari/commands/defaults'
11
8
  require 'inari/commands/test'
12
9
 
10
+ # Responses are recorded in this format
11
+ Response = Struct.new(:code, :body, :logged, :size)
12
+
13
13
  module Inari
14
14
  # This is the configuration API. These methods can be used from configuration files.
15
15
  #
@@ -24,11 +24,11 @@ module Inari
24
24
  #
25
25
  class Commands
26
26
  include Singleton
27
-
27
+
28
28
  # The taskmanager created for this command instance.
29
29
  attr_reader :last_response
30
30
  attr_accessor :host, :port, :path, :sleep, :timeout
31
-
31
+
32
32
  include HTTP
33
33
  include SNMP
34
34
  include SMTP
@@ -38,9 +38,9 @@ module Inari
38
38
  include TestCommands
39
39
 
40
40
  def initialize
41
- @host = ''
42
41
  @port = nil
43
42
  @path = ''
43
+ @host = nil
44
44
 
45
45
  @sleep = 60
46
46
  @timeout = 5
@@ -49,7 +49,6 @@ module Inari
49
49
  @downtimers = {}
50
50
  @last_downtime = {}
51
51
  @responses_limit = 10
52
- @last_response = ''
53
52
 
54
53
  @localhost = 'localhost'
55
54
  end
@@ -62,8 +61,10 @@ module Inari
62
61
  def current_host ; @host ; end
63
62
 
64
63
  # The status of the last task against the service.
65
- def status ; @last_response.code; end
66
-
64
+ def status ; last_response.code; end
65
+
66
+ def last_response ; @responses[current_host] and @responses[current_host].last ; end
67
+
67
68
  # Set the port the service you're monitoring runs on.
68
69
  def port(port) ; @port = port ; end
69
70
 
@@ -95,27 +96,27 @@ module Inari
95
96
 
96
97
  # Get the downtime for this task.
97
98
  def down_for
98
- if @downtimers[@host].nil?
99
- return @last_downtime[@host] || 0
99
+ if @downtimers[current_host].nil?
100
+ return @last_downtime[current_host] || 0
100
101
  else
101
- return time.to_i - @downtimers[@host].to_i
102
+ return time.to_i - @downtimers[current_host].to_i
102
103
  end
103
104
  end
104
105
 
105
106
  # Called when a task has reported a service offline.
106
107
  def down
107
- if @downtimers[@host].nil?
108
- @downtimers[@host] = time
109
- @last_downtime[@host] = 0
108
+ if @downtimers[current_host].nil?
109
+ @downtimers[current_host] = time
110
+ @last_downtime[current_host] = 0
110
111
  @on_down.call(self) if @on_down
111
112
  end
112
113
  end
113
114
 
114
115
  # Called when a task has seen the service come back.
115
116
  def up
116
- if @downtimers[@host]
117
- @last_downtime[@host] = time.to_i - @downtimers[@host].to_i
118
- @downtimers[@host] = nil
117
+ if @downtimers[current_host]
118
+ @last_downtime[current_host] = time.to_i - @downtimers[current_host].to_i
119
+ @downtimers[current_host] = nil
119
120
  @on_up.call(self) if @on_up
120
121
  end
121
122
  end
@@ -128,13 +129,11 @@ module Inari
128
129
 
129
130
  # Store the remote responses in queue.
130
131
  def add_response(name, response, down = false)
131
- @last_response = response
132
-
133
132
  down ? self.down : up
134
133
 
135
- @responses[@host] ||= []
136
- @responses[@host].insert 0, {:name => name, :response => response, :time => time, :down => down }
137
- @responses[@host].pop if @responses[@host].size > @responses_limit
134
+ @responses[current_host] ||= []
135
+ @responses[current_host].insert 0, {:name => name, :response => response, :time => time, :down => down }
136
+ @responses[current_host].pop if @responses[current_host].size > @responses_limit
138
137
  end
139
138
 
140
139
  def to_seconds(argument)
@@ -3,40 +3,56 @@ require 'net/http'
3
3
  module HTTP
4
4
  # HTTP commands
5
5
  def page_size(response = nil)
6
- response = @last_response if response.nil?
6
+ response = last_response if response.nil?
7
7
  response.body.size rescue 0
8
8
  end
9
9
 
10
- def page_content; @last_response.body; end
11
-
12
- def get_web_page(page)
13
- Timeout::timeout(@timeout) do
14
- response = Net::HTTP.get_response(@host, page, @port || 80)
15
- add_response(page, response)
16
-
17
- # Return true when a 200 is returned, in case people use get_web_page as a condition
18
- response.code == '200'
19
- end
20
- rescue
21
- add_response(page, Response.new(:code => $!), true)
22
- false
10
+ def page_content(response = nil)
11
+ response = last_response if response.nil?
12
+ response.body rescue nil
23
13
  end
24
14
 
25
- def unexpected_page_change
26
- @first_response = @last_response if @first_response.nil? and @last_response
15
+ # Fetches a web page and notifies when a timeout occurs or the page
16
+ # returns an unexpected status.
17
+ #
18
+ # Supply a block to use something instead of Net::HTTP.get_response
19
+ def get_web_page(page, &block)
20
+ response, down = get_remote_response(page, &block)
21
+
22
+ add_response(page, response, down)
23
+ response.code == '200'
24
+ end
27
25
 
26
+ # Raises an alert when a page changes.
27
+ def watch_for_changes_on_page(page, &block)
28
28
  # Fetch a fresh copy of the page and retain the last one
29
- page_size(@first_response) == page_size
29
+ response, down = get_remote_response(page, &block)
30
+
31
+ returning (!set_first_response(response) and changed?(response)) do |state|
32
+ add_response(page, last_response, state)
33
+ end
30
34
  end
31
35
 
32
- #def when_http_status_is(status, invert = false, &block)
33
- # response = Net::HTTP.get_response(@host, @path)
34
- # if status.to_i == response.code.to_i and not invert
35
- # instance_eval(&block) if block
36
- # end
37
- #end
38
- #
39
- #def when_http_status_is_not(status, &block)
40
- # when_http_status_is(status, true, &block)
41
- #end
36
+ def set_first_response(response)
37
+ @first_response ||= {}
38
+ returning @first_response[current_host].nil? do |added|
39
+ @first_response[current_host] = response unless !added
40
+ end
41
+ end
42
+
43
+ def first_response ; @first_response[current_host] ; end
44
+
45
+ private
46
+
47
+ def changed?(response)
48
+ Digest::MD5::hexdigest(page_content(first_response).to_s) != Digest::MD5::hexdigest(page_content(response).to_s)
49
+ end
50
+
51
+ def get_remote_response(page, &block)
52
+ Timeout::timeout(@timeout) do
53
+ [block ? yield : Net::HTTP.get_response(@host, page, @port || 80), false]
54
+ end
55
+ rescue
56
+ [Response.new($!), true]
57
+ end
42
58
  end
@@ -6,11 +6,11 @@ module SMTP
6
6
  response = Response.new
7
7
  begin
8
8
  Net::SMTP.start(@host, port=@port, helo=@localhost, user=nil, secret=nil, authtype=nil)
9
- add_response('helo', Response.new(:code => 'Connection accepted'))
9
+ add_response('helo', Response.new('Connection accepted'))
10
10
  true
11
11
  rescue
12
- add_response('helo', Response.new(:code => $!), true)
12
+ add_response('helo', Response.new($!), true)
13
13
  false
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,11 +8,11 @@ module TCPSimple
8
8
  Timeout::timeout(@timeout) do
9
9
  t = TCPSocket.new(@host, @port)
10
10
  state = true
11
- add_response(name, Response.new(:code => 'Up'))
11
+ add_response(name, Response.new('Up'))
12
12
  end
13
13
  rescue
14
14
  Inari::logger.error "TCP error: #{$!} for host: #{@host}, port: #{@port}"
15
- add_response(name, Response.new(:code => $!), true)
15
+ add_response(name, Response.new($!), true)
16
16
  ensure
17
17
  t.close if defined? t
18
18
  end
@@ -21,4 +21,4 @@ module TCPSimple
21
21
  end
22
22
 
23
23
  def down? ; !up? ; end
24
- end
24
+ end
@@ -1,9 +1,9 @@
1
1
  module TestCommands
2
2
  def run_test(probability)
3
3
  if rand(100) > probability
4
- add_response('Test', Response.new(:code => '200'))
4
+ add_response('Test', Response.new('200'))
5
5
  else
6
- add_response('Test', Response.new(:code => '404'), true)
6
+ add_response('Test', Response.new('404'), true)
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,6 @@
1
+ class Object
2
+ def returning(value)
3
+ yield(value)
4
+ value
5
+ end
6
+ end
@@ -2,8 +2,8 @@
2
2
  module Inari
3
3
  APP_NAME = 'Inari'
4
4
 
5
- INARI_VERSION = '0.1.0'
5
+ INARI_VERSION = '0.1.1'
6
6
  INARI_RELEASE_DATE = '2007/02/06'
7
7
 
8
8
  UPSTREAM_URL = 'http://inari.rubyforge.org'
9
- end
9
+ end
@@ -2,3 +2,7 @@
2
2
 
3
3
  require 'test/unit'
4
4
  require 'inari'
5
+
6
+ module InariTest
7
+ def self.default_host ; 'alexyoung.org' ; end
8
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/abstract_test'
2
+
3
+ class CommandsTest::HTTP < Test::Unit::TestCase
4
+ def setup
5
+ @commands = Inari::Commands.instance
6
+ end
7
+
8
+ def test_get_web_page
9
+ @commands.host = InariTest::default_host
10
+ assert @commands.get_web_page('/')
11
+ end
12
+
13
+ def test_watch_for_changes_on_page
14
+ @commands.host = 'test_watch_for_changes_on_page'
15
+ assert !@commands.watch_for_changes_on_page('/') { Response.new('200', 'Test') }
16
+ assert !@commands.watch_for_changes_on_page('/') { Response.new('200', 'Test') }
17
+ assert !@commands.watch_for_changes_on_page('/') { Response.new('200', 'Test') }
18
+
19
+ # This should be considered different
20
+ assert @commands.watch_for_changes_on_page('/') { Response.new('200', 'Page changed') }
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ require 'test/abstract_test'
2
+
3
+ class CommandsTest::TCPSimple < Test::Unit::TestCase
4
+ def setup
5
+ @commands = Inari::Commands.instance
6
+ end
7
+
8
+ def test_up_down
9
+ @commands.host = InariTest::default_host
10
+ @commands.port = 80
11
+ assert @commands.up?
12
+ end
13
+ end
@@ -5,11 +5,6 @@ class ConfigurationTest < Test::Unit::TestCase
5
5
  @configuration = Inari::Configuration.instance
6
6
  end
7
7
 
8
- # Check if any of the load paths make sense
9
- def test_default_load_path_exists
10
- assert File.directory?(@configuration.default_load_path)
11
- end
12
-
13
8
  def test_loads
14
9
  @configuration.load_paths.push 'test/fixtures/'
15
10
  assert_nil @configuration.load('test_config.rb')
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: inari
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2007-02-06 00:00:00 +00:00
8
- summary: Inari is a ruby system monitoring program.
6
+ version: 0.1.1
7
+ date: 2007-02-06
8
+ summary: Inari is a system monitoring program.
9
9
  require_paths:
10
10
  - lib
11
11
  email: alex@helicoid.net
@@ -23,52 +23,39 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
23
23
  version: 0.0.0
24
24
  version:
25
25
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message: |+
29
-
30
- Welcome to Inari
31
- ================
32
-
33
- Inari is a small and extenable system monitor, intended for us with
34
- web applications. To start using it, tailor /usr/local/etc/inari.conf
35
- to your requirements.
36
-
37
- Take a look at README for help on writing configuration files.
38
-
39
- http://inari.rubyforge.org
40
-
41
26
  authors: []
42
27
 
43
28
  files:
44
29
  - lib/inari.rb
45
- - lib/inari/commands.rb
30
+ - lib/inari/task_process.rb
46
31
  - lib/inari/configuration.rb
32
+ - lib/inari/commands.rb
47
33
  - lib/inari/daemon.rb
48
- - lib/inari/response.rb
49
- - lib/inari/task_manager.rb
50
- - lib/inari/task_process.rb
51
34
  - lib/inari/version.rb
35
+ - lib/inari/task_manager.rb
36
+ - lib/inari/misc.rb
52
37
  - lib/inari/commands/defaults.rb
53
- - lib/inari/commands/http.rb
54
- - lib/inari/commands/reporting.rb
55
- - lib/inari/commands/smtp.rb
56
38
  - lib/inari/commands/snmp.rb
57
- - lib/inari/commands/tcp_simple.rb
39
+ - lib/inari/commands/http.rb
58
40
  - lib/inari/commands/test.rb
41
+ - lib/inari/commands/tcp_simple.rb
42
+ - lib/inari/commands/smtp.rb
43
+ - lib/inari/commands/reporting.rb
59
44
  - bin/inari
60
- - CHANGES
61
- - InstalledFiles
62
45
  - LICENSE
63
46
  - Rakefile
64
- - README
47
+ - CHANGES
65
48
  - THANKS
66
- - test/abstract_test.rb
67
- - test/commands_test.rb
68
- - test/configuration_test.rb
49
+ - README
69
50
  - test/fixtures
70
51
  - test/task_manager_test.rb
52
+ - test/commands_test.rb
53
+ - test/abstract_test.rb
54
+ - test/commands
55
+ - test/configuration_test.rb
71
56
  - test/fixtures/test_config.rb
57
+ - test/commands/http_test.rb
58
+ - test/commands/tcp_simple_test.rb
72
59
  test_files: []
73
60
 
74
61
  rdoc_options: []
@@ -1 +0,0 @@
1
- /usr/local/lib/ruby/site_ruby/1.8/inari.rb
@@ -1,9 +0,0 @@
1
- class Response
2
- attr_accessor :code
3
- attr_accessor :size
4
- attr_accessor :logged
5
-
6
- def initialize(*args)
7
- args.each { |field, value| self.send(field, value) } if args.is_a? Hash
8
- end
9
- end