inquisitor 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (C) 2011, brain-geek
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
20
+
21
+ Images by @genn_org
@@ -0,0 +1,54 @@
1
+ Inquisitor
2
+ ===============
3
+
4
+ [![Build Status](https://secure.travis-ci.org/brain-geek/inquisitor.png)](http://travis-ci.org/brain-geek/inquisitor)
5
+ [![Dependencies Status](https://gemnasium.com/brain-geek/inquisitor.png)](https://gemnasium.com/brain-geek/inquisitor)
6
+
7
+ This project is aimed on creation ruby-powered monitoring solution with simple web interface.
8
+
9
+ Usage
10
+ -----
11
+ ###Standalone install:
12
+ #####Running check:
13
+
14
+ monitor -d sqlite3://`pwd`/sqlite_database.db
15
+
16
+ #####Running web server:
17
+
18
+ monitor_web -d sqlite3://`pwd`/sqlite_database.db
19
+
20
+ ###Mounting to rails app:
21
+ #####Add to gemfile:
22
+
23
+ gem 'data_mapper'
24
+ gem 'dm-redis-adapter'
25
+ gem 'inquisitor', :git => 'git://github.com/brain-geek/inquisitor.git'
26
+
27
+ #####Create initializer:
28
+
29
+ require 'inquisitor/web'
30
+ Inquisitor.settings.set :db_path => {:adapter => "redis"}
31
+
32
+ #####Add to routes:
33
+
34
+ mount Inquisitor::Web.new, :at => "/inquisitor"
35
+
36
+ ###Development web server
37
+ shotgun config.dev.ru
38
+
39
+ Features
40
+ -----
41
+ #####Databases supported
42
+ It should work with all databases supported by datamapper. Tested with postgresql, mysql, redis and sqlite. Format for db_path can be found [in datamapper doc](http://datamapper.org/getting-started.html) - "Specify your database connection".
43
+
44
+ #####Cli options:
45
+ You can read availible options from lib/inquisitor/cli.rb . Same options are supported by standalone install
46
+
47
+ #####Supported types of monitoring:
48
+ [outpost gem](https://github.com/vinibaggio/outpost) is used as backend for monitoring. For now, http:// and ping:// checks are supported.
49
+
50
+ Copyright
51
+ ---------
52
+
53
+ Copyright (c) 2011 @brain-geek. See LICENSE for details.
54
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inquisitor', 'cli')
4
+
5
+ Inquisitor.check_all
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inquisitor', 'cli')
3
+
4
+ Inquisitor::Web.bind = '0.0.0.0'
5
+
6
+ Inquisitor::Web.run!
@@ -0,0 +1,35 @@
1
+ require 'outpost'
2
+ require 'outpost/scouts'
3
+ require 'outpost/notifiers/email'
4
+
5
+ require 'data_mapper'
6
+ require File.join(File.dirname(__FILE__), 'inquisitor', 'extensions.rb')
7
+ require File.join(File.dirname(__FILE__), 'inquisitor', 'node.rb')
8
+ require File.join(File.dirname(__FILE__), 'inquisitor', 'contact.rb')
9
+ require File.join(File.dirname(__FILE__), 'inquisitor', 'settings.rb')
10
+ DataMapper.finalize
11
+
12
+ module Inquisitor
13
+ class << self
14
+ def create_outpost(name = '')
15
+ outpost = Outpost::Application.new
16
+ outpost.name = name
17
+
18
+ Inquisitor::Contact.all.each do |contact|
19
+ outpost.add_notifier Outpost::Notifiers::Email, {
20
+ :from => Inquisitor.settings.mail_from,
21
+ :to => contact.email,
22
+ :subject => Inquisitor.settings.mail_subject
23
+ }
24
+ end
25
+
26
+ outpost
27
+ end
28
+
29
+ def settings
30
+ @settings ||= Settings.new
31
+ end
32
+
33
+ delegate :check_all, :to => Node
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ begin
2
+ require 'slop'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'slop'
6
+ end
7
+
8
+ require File.join(File.dirname(__FILE__), '..', 'inquisitor')
9
+ require File.join(File.dirname(__FILE__), 'web')
10
+
11
+ opts = Slop.parse do
12
+ on :d, :db_path, 'DB path', :optional => false
13
+ on :mail_from, 'Send mail from email', :optional => true
14
+ on :mail_subject, 'Mail subject', :optional => true
15
+ on :check_period, :as => :integer, :optional => true
16
+ end
17
+
18
+ opts = opts.to_hash.delete_if{|key, value| value.nil? }
19
+
20
+ raise 'DB connection is not set' unless opts.has_key?(:db_path)
21
+
22
+ Inquisitor.settings.set opts
@@ -0,0 +1,7 @@
1
+ module Inquisitor
2
+ class Contact
3
+ include DataMapper::Resource
4
+ property :id, Serial
5
+ property :email, String, :format => :email_address, :index => :unique, :required => true
6
+ end
7
+ end
@@ -0,0 +1,54 @@
1
+ #Module.delegate by active_support
2
+ class Module
3
+ # File activesupport/lib/active_support/core_ext/module/delegation.rb, line 106
4
+ def delegate(*methods)
5
+ options = methods.pop
6
+ unless options.is_a?(Hash) && to = options[:to]
7
+ raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
8
+ end
9
+
10
+ if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/
11
+ raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
12
+ end
13
+
14
+ prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_" || ''
15
+
16
+ file, line = caller.first.split(':', 2)
17
+ line = line.to_i
18
+
19
+ methods.each do |method|
20
+ on_nil =
21
+ if options[:allow_nil]
22
+ 'return'
23
+ else
24
+ %Q(raise "#{self}##{prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
25
+ end
26
+
27
+ module_eval(" def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block)
28
+ #{to}.__send__(#{method.inspect}, *args, &block) # client.__send__(:name, *args, &block)
29
+ rescue NoMethodError # rescue NoMethodError
30
+ if #{to}.nil? # if client.nil?
31
+ #{on_nil} # return # depends on :allow_nil
32
+ else # else
33
+ raise # raise
34
+ end # end
35
+ end # end
36
+ ", file, line - 1)
37
+ end
38
+ end
39
+ end
40
+
41
+ module ActiveSupport
42
+ module Delegation #:nodoc:
43
+ def self.perform(object, target, method, method_name, allow_nil, to, args, block)
44
+ target.__send__(method, *args, &block)
45
+ rescue NoMethodError
46
+ if target.nil?
47
+ return nil if allow_nil
48
+ raise "#{object.class}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: #{object.inspect}"
49
+ else
50
+ raise
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,61 @@
1
+ require 'uri'
2
+
3
+ module Inquisitor
4
+ class Node
5
+ include DataMapper::Resource
6
+ property :id, Serial
7
+ property :url, String, :index => :unique
8
+ property :name, String, :index => true
9
+
10
+ validates_presence_of :url
11
+ validates_with_method :url, :method => :check_protocol
12
+
13
+ delegate :run, :notify, :to => :outpost
14
+ alias :check :run
15
+
16
+ def check_and_notify
17
+ notify unless run == :up
18
+ end
19
+
20
+ def self.check_all
21
+ all.each &:check_and_notify
22
+ end
23
+
24
+ def last_log
25
+ outpost.messages.join('<br />')
26
+ end
27
+
28
+ def check_protocol
29
+ outpost
30
+ true
31
+ rescue URI::InvalidURIError
32
+ false
33
+ end
34
+
35
+ protected
36
+ def outpost
37
+ @outpost ||= begin
38
+ outpost = Inquisitor.create_outpost(self.name)
39
+ uri = URI.parse(url)
40
+
41
+ case uri.scheme
42
+ when 'http'
43
+ outpost.add_scout Outpost::Scouts::Http => '' do
44
+ options :host => uri.host, :port => uri.port, :path => uri.path.empty? ? '/' : uri.path
45
+ report :up, :response_code => 200...400
46
+ report :down, :response_code => 400..600
47
+ end
48
+ when 'ping'
49
+ outpost.add_scout Outpost::Scouts::Ping => '' do
50
+ options :host => uri.host
51
+ report :up, :response_time => {:less_than => 1000}
52
+ end
53
+ else
54
+ raise URI::InvalidURIError
55
+ end
56
+
57
+ outpost
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ $(window).load(function(){
2
+ // status loading
3
+ $('td.status-load').each(function(index, element){
4
+ $.get($(this).attr('rel'), '', function(req)
5
+ {
6
+ $('.element-' + req['id'] + ' .status-load img').attr('src', $('body').attr('root_path') + req.status + '.png')
7
+ $('.element-' + req['id'] + ' .status-load').attr('detailed', req.log)
8
+ });
9
+ });
10
+
11
+ // submit on enter
12
+ $('form.form-stacked input').keypress(function(e)
13
+ {
14
+ if(e.which == 13)
15
+ {
16
+ $(this).closest('form').submit();
17
+ e.preventDefault();
18
+ return false;
19
+ }
20
+ });
21
+
22
+
23
+ // magic with show-hide
24
+ $('.show_detailed').click(function(){
25
+ $(this).closest('form').find('.hidden').toggle();
26
+ return false;
27
+ });
28
+
29
+
30
+
31
+ });
@@ -0,0 +1,38 @@
1
+ html, body
2
+ {
3
+ background-color: #EEE;
4
+ }
5
+
6
+ .content
7
+ {
8
+ background-color: white;
9
+ padding: 20px;
10
+ margin: 0 -20px;
11
+ }
12
+
13
+ td.status-load
14
+ {
15
+ width: 40px;
16
+ }
17
+
18
+ #nodes table
19
+ {
20
+ margin-bottom: 0px;
21
+ }
22
+
23
+ #nodes fieldset .hidden
24
+ {
25
+ display:none;
26
+ }
27
+
28
+ #nodes fieldset button
29
+ {
30
+ margin-top: 10px;
31
+ }
32
+
33
+ a.show_detailed {
34
+ border-bottom: 1px dotted #00438A;
35
+ margin-bottom: 10px;
36
+ text-decoration: none;
37
+ font-size: 10px;
38
+ }
@@ -0,0 +1,40 @@
1
+ %h2 Check nodes
2
+ #nodes
3
+ %table
4
+ - @nodes.each do |node|
5
+ %tr{ :class => "element-#{node.id}"}
6
+ %td.status-load{:rel => url_for("node/status/#{node.id}")}
7
+ %img{:src => url_for('loading.gif'), :height => 36, :width => 32}
8
+ %td= node.url
9
+ %td{:width => '100%'}= node.name
10
+ %td
11
+ %a.btn.danger{:href => url_for("/node/delete/#{node.id}")} Delete
12
+
13
+ %form.form-stacked.actions{:action => url_for("/node/new"), :method => "post", :id => 'add_node'}
14
+ %fieldset
15
+ .clearfix
16
+ %label{:for => "node[name]"}Url
17
+ %input{:type => "text", :name => "node[url]", :id => "add-url-field"}
18
+ .clearfix
19
+ %a.show_detailed{:href => '#'} Options
20
+ .clearfix.hidden
21
+ %label{:for => "node[name]"}Title
22
+ %input{:type => "text", :name => "node[name]", :id => "add-name-field"}
23
+ .clearfix
24
+ %input.btn.primary{:type => "submit", :value => "Add node"}
25
+
26
+ %h2 Notify me by
27
+ #contacts
28
+ .list
29
+ %table
30
+ - @contacts.each do |contact|
31
+ %tr{ :class => "element-#{contact.id}"}
32
+ %td= contact.email
33
+
34
+ %form.form-stacked.actions{:action => url_for("/contact/new"), :method => "post", :id => 'add_contact'}
35
+ %fieldset
36
+ .clearfix
37
+ %label{:for => "contact[email]"}Email
38
+ %input{:type => "text", :name => "contact[email]", :id => "add-email-field"}
39
+ .clearfix
40
+ %input.btn{:type => "submit", :value => "Add contact"}
@@ -0,0 +1,15 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title Index page
5
+ %meta{:content => "text/html;charset=utf-8", "http-equiv" => "Content-Type"}
6
+ = stylesheet 'http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css', url_for('/style.css')
7
+ %script{:src => 'http://code.jquery.com/jquery-1.7.1.min.js'}
8
+ %script{:src => url_for('/script.js')}
9
+ :javascript
10
+ $(function(){$('body').attr('root_path', '#{url_for("/")}')});
11
+
12
+ %body
13
+ .container
14
+ .content
15
+ = yield
@@ -0,0 +1,24 @@
1
+ module Inquisitor
2
+ class Settings
3
+ attr_accessor :mail_from, :mail_subject, :check_period
4
+
5
+ def initialize
6
+ self.mail_from = 'changeme.in@Inquisitor.settings'
7
+ self.mail_subject = 'Subject for Inquisitor notify letter'
8
+ self.check_period = 30
9
+ end
10
+
11
+ def db_path=(path)
12
+ DataMapper.setup(:default, path)
13
+ DataMapper.auto_upgrade!
14
+ end
15
+
16
+ def set(params)
17
+ params.each do |key, value|
18
+ if respond_to?("#{key}=")
19
+ send("#{key}=", value)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ module Inquisitor
2
+ PATCH = 1
3
+ MINOR = 1
4
+ MAJOR = 0
5
+ VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}".freeze
6
+ end
@@ -0,0 +1,55 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/link_header'
3
+ require 'sinatra/json'
4
+ require 'sinatra/url_for'
5
+ require 'haml'
6
+
7
+ module Inquisitor
8
+ class Web < Sinatra::Base
9
+ helpers Sinatra::LinkHeader
10
+ helpers Sinatra::JSON
11
+ helpers Sinatra::UrlForHelper
12
+
13
+ dir = File.dirname(File.expand_path(__FILE__))
14
+
15
+ set :views, "#{dir}/server/views"
16
+
17
+ if respond_to? :public_folder
18
+ set :public_folder, "#{dir}/server/public"
19
+ else
20
+ set :public, "#{dir}/server/public"
21
+ end
22
+
23
+ set :static, true
24
+ set :run, false
25
+
26
+ get '/' do
27
+ @nodes = Inquisitor::Node.all
28
+ @contacts = Inquisitor::Contact.all
29
+ haml :index, :format => :html5
30
+ end
31
+
32
+ get '/node/status/:id' do
33
+ n = Inquisitor::Node.get(params[:id].to_i)
34
+ json :status => n.check, :log => n.last_log, :id => n.id
35
+ end
36
+
37
+ get '/node/delete/:id' do
38
+ n = Inquisitor::Node.get(params[:id].to_i)
39
+ n.destroy unless n.nil?
40
+ redirect url_for('/')
41
+ end
42
+
43
+ post '/node/new' do
44
+ Inquisitor::Node.create params["node"]
45
+
46
+ redirect url_for('/')
47
+ end
48
+
49
+ post '/contact/new' do
50
+ Inquisitor::Contact.create params["contact"]
51
+
52
+ redirect url_for('/')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ describe Inquisitor::Contact do
4
+ describe "validation" do
5
+ it "saves with valid email" do
6
+ c = Inquisitor::Contact.make_unsaved :email => "valid#{Time.now.to_i}@gmail.com"
7
+ c.save.should be_true
8
+ end
9
+ it "does not save with invalid email" do
10
+ c = Inquisitor::Contact.make_unsaved :email => '#{Time.now.to_i}invalidfghdfhdgdgmail.com'
11
+ c.save.should be_false
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,80 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ describe Inquisitor::Node do
4
+ describe 'http checking' do
5
+ it "should check if it tells that http site is ok" do
6
+ n = Inquisitor::Node.make :url => 'http://ya.ru'
7
+
8
+ n.check.should == :up
9
+ end
10
+
11
+ it "should tell that page with redirect is ok, not down" do
12
+ n = Inquisitor::Node.make :url => 'http://google.com/'
13
+
14
+ n.check.should == :up
15
+ end
16
+
17
+ it "should fail if hostname not found" do
18
+ n = Inquisitor::Node.make :url => 'http://akjfsjjgsdf.google.com'
19
+
20
+ n.check.should == :down
21
+ end
22
+
23
+ it "should fail if page not found" do
24
+ n = Inquisitor::Node.make :url => 'http://www.google.com/404.html'
25
+
26
+ n.check.should == :down
27
+ end
28
+ end
29
+
30
+ describe 'ping checking' do
31
+ it "should pass if host is reachable" do
32
+ n = Inquisitor::Node.make :url => 'ping://127.0.0.1'
33
+ n.check.should == :up
34
+ end
35
+ it "should not pass if host is not reachable" do
36
+ n = Inquisitor::Node.make :url => 'ping://sdfsadfasdfasdf.asdfasdfasdf.asdfasdf'
37
+ n.check.should == :down
38
+ end
39
+ end
40
+
41
+ describe 'validation' do
42
+ it "should fail if unknown protocol of url is passed" do
43
+ n = Inquisitor::Node.make_unsaved :url => 'https://github.com'
44
+ n.save.should be_false
45
+ end
46
+ end
47
+
48
+ describe "work with outpost" do
49
+ it "should return logs from outpost" do
50
+ n = Inquisitor::Node.make
51
+ o = Object.new
52
+ o.should_receive(:messages).and_return([])
53
+ n.should_receive(:outpost).and_return(o)
54
+
55
+ n.last_log
56
+ end
57
+ end
58
+
59
+ it "should run all checks at once" do
60
+ nodes = []
61
+
62
+ 5.times do
63
+ node = Inquisitor::Node.make
64
+ node.should_receive(:run).and_return(:down)
65
+ node.should_receive(:notify)
66
+ nodes.push node
67
+ end
68
+
69
+ 5.times do
70
+ node = Inquisitor::Node.make
71
+ node.should_receive(:run).and_return(:up)
72
+ node.should_not_receive(:notify)
73
+ nodes.push node
74
+ end
75
+
76
+ Inquisitor::Node.should_receive(:all).and_return(nodes)
77
+
78
+ Inquisitor.check_all
79
+ end
80
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_integration_helper.rb')
2
+
3
+ describe 'Outpost factory' do
4
+ before do
5
+ @contact = Inquisitor::Contact.make
6
+ end
7
+
8
+ it "should add email notifiers" do
9
+ outpost = Inquisitor.create_outpost 'title'
10
+
11
+ outpost.name.should == 'title'
12
+
13
+ outpost.notifiers.first[0].should == Outpost::Notifiers::Email
14
+ outpost.notifiers.first[1][:to].should == @contact.email
15
+ end
16
+
17
+ it "should send emails" do
18
+ Mail.defaults do
19
+ delivery_method :test
20
+ end
21
+
22
+ Mail::TestMailer.deliveries.should == []
23
+ Inquisitor::Node.make(:url => 'ping://non-existant.domain').check_and_notify
24
+ Mail::TestMailer.deliveries.count.should == 1
25
+ end
26
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ describe 'App settings' do
4
+ before :each do
5
+ Inquisitor.instance_variable_set '@settings', nil
6
+ end
7
+
8
+ it "should have default values" do
9
+ Inquisitor.settings.mail_from.should == 'changeme.in@Inquisitor.settings'
10
+ Inquisitor.settings.mail_subject.should == 'Subject for Inquisitor notify letter'
11
+
12
+ Inquisitor.settings.check_period.should == 30
13
+ end
14
+
15
+ it "should send email from emails we set and with defined title" do
16
+ Inquisitor::Contact.make
17
+
18
+ subj = 'Notify set in test env'
19
+ mail = 'test-receiver@gmail.com'
20
+
21
+ Inquisitor.settings.mail_from = mail
22
+ Inquisitor.settings.mail_subject = subj
23
+ outpost = Inquisitor.create_outpost
24
+
25
+ outpost.notifiers.first[1][:from].should == mail
26
+ outpost.notifiers.first[1][:subject].should == subj
27
+ end
28
+
29
+ it "should set db settings" do
30
+ DataMapper.should_receive(:setup).with :default, :path
31
+ DataMapper.should_receive(:auto_upgrade!)
32
+
33
+ Inquisitor.settings.db_path = :path
34
+ end
35
+
36
+ it "should do mass asignments" do
37
+ Inquisitor.settings.set :mail_from => 'me@gmail.com', :check_period => 900
38
+ Inquisitor.settings.mail_from.should == 'me@gmail.com'
39
+ Inquisitor.settings.check_period.should == 900
40
+ end
41
+ end
@@ -0,0 +1,118 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_integration_helper.rb')
2
+ require 'json'
3
+
4
+ describe "Basic frontend test" do
5
+ def app
6
+ @app ||= Inquisitor::Web
7
+ end
8
+
9
+ it "should respond to / and list all" do
10
+ nodes = []
11
+ 5.times { nodes.push Inquisitor::Node.make }
12
+ Inquisitor::Node.should_receive(:all).and_return(nodes)
13
+
14
+ contacts = []
15
+ 3.times { contacts.push Inquisitor::Contact.make }
16
+ Inquisitor::Contact.should_receive(:all).and_return(contacts)
17
+
18
+ get '/'
19
+
20
+ last_response.should be_ok
21
+
22
+ nodes.each do |n|
23
+ within "#nodes .element-#{n.id}" do |scope|
24
+ scope.should contain n.name
25
+ scope.should contain n.url
26
+ scope.should have_selector("td[rel='node/status/#{n.id}']")
27
+ end
28
+ end
29
+
30
+ contacts.each do |n|
31
+ within "#contacts .element-#{n.id}" do |scope|
32
+ scope.should contain n.email
33
+ end
34
+ end
35
+ end
36
+
37
+ it "should delete node from interface" do
38
+ 5.times { Inquisitor::Node.make }
39
+ node = Inquisitor::Node.make
40
+ 5.times { Inquisitor::Node.make }
41
+
42
+ get '/'
43
+
44
+ Inquisitor::Node.first(node.attributes).should_not be_nil
45
+
46
+ within "#nodes .element-#{node.id}" do |scope|
47
+ scope.click_link "Delete"
48
+ end
49
+
50
+ Inquisitor::Node.first(node.attributes).should be_nil
51
+ end
52
+
53
+ it "should respond with service status" do
54
+ n = Inquisitor::Node.make
55
+ n.should_receive(:check).and_return(:up)
56
+ n.should_receive(:last_log).and_return('best log in the world')
57
+
58
+ Inquisitor::Node.should_receive(:get).with(n.id).and_return(n)
59
+
60
+ get "/node/status/#{n.id}"
61
+
62
+ resp = JSON.parse(response.body)
63
+ resp['status'].should == 'up'
64
+ resp['log'].should == 'best log in the world'
65
+ end
66
+
67
+ it "should create node" do
68
+ node = Inquisitor::Node.make_unsaved.attributes
69
+ visit '/'
70
+ Inquisitor::Node.first(node).should be_nil
71
+
72
+ fill_in "add-name-field", :with => node[:name]
73
+ fill_in "add-url-field", :with => node[:url]
74
+ click_button "Add node"
75
+
76
+ Inquisitor::Node.first(node).should_not be_nil
77
+ end
78
+
79
+ it "should create new contact" do
80
+ contact = Inquisitor::Contact.make_unsaved.attributes
81
+ visit '/'
82
+ Inquisitor::Contact.first(contact).should be_nil
83
+
84
+ fill_in "add-email-field", :with => contact[:email]
85
+ click_button "Add contact"
86
+
87
+ Inquisitor::Contact.first(contact).should_not be_nil
88
+ end
89
+
90
+ it "should delete node" do
91
+ test_delete(Inquisitor::Node)
92
+ end
93
+
94
+ it "should create node" do
95
+ test_new(Inquisitor::Node)
96
+ end
97
+
98
+ it "should create contact" do
99
+ test_new(Inquisitor::Contact)
100
+ end
101
+
102
+ private
103
+ def test_new(cls)
104
+ attrs = cls.make_unsaved.attributes
105
+ name = cls.to_s.split('::').last.downcase
106
+ cls.first(attrs).should be_nil
107
+ post "/#{name}/new", name => attrs
108
+ cls.first(attrs).should_not be_nil
109
+ end
110
+
111
+ def test_delete(cls)
112
+ attrs = cls.make.attributes
113
+ cls.first(attrs).should_not be_nil
114
+ name = cls.to_s.split('::').last.downcase
115
+ get "/#{name}/delete/#{attrs[:id]}"
116
+ cls.first(attrs).should be_nil
117
+ end
118
+ end
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rack/test'
3
+ require 'rspec'
4
+ require 'webrat'
5
+ require 'ffaker'
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inquisitor.rb')
7
+
8
+ RSpec.configure do |config|
9
+ config.before(:all) { Sham.reset(:before_all) }
10
+ config.before(:each) { Sham.reset(:before_each) }
11
+ end
12
+
13
+ if ENV['DB'] == 'sqlite'
14
+ Inquisitor.settings.db_path = "sqlite3://#{Dir.pwd}/test.db"
15
+ puts "Using sqlite"
16
+ elsif ENV['DB'] == 'redis'
17
+ Inquisitor.settings.db_path ={:adapter => "redis"}
18
+ puts "Using redis"
19
+ elsif ENV['DB'] == 'mysql'
20
+ `mysql -e 'create database test;'`
21
+ Inquisitor.settings.db_path ="mysql://@localhost/test"
22
+ puts "Using mysql"
23
+ elsif ENV['DB'] == 'pg'
24
+ `psql -c 'create database test;' -U postgres`
25
+ Inquisitor.settings.db_path ="postgres://postgres@localhost/test"
26
+ puts "Using pg"
27
+ else
28
+ Inquisitor.settings.db_path = 'sqlite3::memory:'
29
+ puts 'Using sqlite(by default)'
30
+ end
31
+
32
+ require File.join(File.dirname(__FILE__), 'support/blueprints.rb')
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inquisitor', 'web.rb')
3
+
4
+ RSpec.configure do |config|
5
+ config.include Rack::Test::Methods
6
+ config.include Webrat::Methods
7
+ config.include Webrat::Matchers
8
+ config.before{ Inquisitor::Node.all.destroy }
9
+ end
10
+
11
+ Webrat.configure do |config|
12
+ config.mode= :rack
13
+ end
14
+
15
+ Inquisitor::Web.set :environment, :test
@@ -0,0 +1,11 @@
1
+ require 'machinist/data_mapper'
2
+ require 'sham'
3
+
4
+ Inquisitor::Node.blueprint do
5
+ url { 'http://' + Faker::Lorem.words(2).join('-').downcase + '.com' }
6
+ name { Faker::Name.name }
7
+ end
8
+
9
+ Inquisitor::Contact.blueprint do
10
+ email { Faker::Internet.email }
11
+ end
metadata ADDED
@@ -0,0 +1,224 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inquisitor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Rozumiy Alexander
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-01-12 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ requirement: *id001
31
+ prerelease: false
32
+ type: :runtime
33
+ name: data_mapper
34
+ - !ruby/object:Gem::Dependency
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ hash: 3
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ requirement: *id002
45
+ prerelease: false
46
+ type: :runtime
47
+ name: outpost
48
+ - !ruby/object:Gem::Dependency
49
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ requirement: *id003
59
+ prerelease: false
60
+ type: :runtime
61
+ name: net-ping
62
+ - !ruby/object:Gem::Dependency
63
+ version_requirements: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ requirement: *id004
73
+ prerelease: false
74
+ type: :runtime
75
+ name: mail
76
+ - !ruby/object:Gem::Dependency
77
+ version_requirements: &id005 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 3
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirement: *id005
87
+ prerelease: false
88
+ type: :runtime
89
+ name: sinatra
90
+ - !ruby/object:Gem::Dependency
91
+ version_requirements: &id006 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirement: *id006
101
+ prerelease: false
102
+ type: :runtime
103
+ name: sinatra-contrib
104
+ - !ruby/object:Gem::Dependency
105
+ version_requirements: &id007 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ requirement: *id007
115
+ prerelease: false
116
+ type: :runtime
117
+ name: haml
118
+ - !ruby/object:Gem::Dependency
119
+ version_requirements: &id008 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ hash: 3
125
+ segments:
126
+ - 0
127
+ version: "0"
128
+ requirement: *id008
129
+ prerelease: false
130
+ type: :runtime
131
+ name: emk-sinatra-url-for
132
+ - !ruby/object:Gem::Dependency
133
+ version_requirements: &id009 !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirement: *id009
143
+ prerelease: false
144
+ type: :runtime
145
+ name: slop
146
+ description: Monitoring daemon with simple web UI.
147
+ email: brain-geek@yandex.ua
148
+ executables:
149
+ - monitor
150
+ - monitor_web
151
+ extensions: []
152
+
153
+ extra_rdoc_files: []
154
+
155
+ files:
156
+ - lib/inquisitor/extensions.rb
157
+ - lib/inquisitor/cli.rb
158
+ - lib/inquisitor/contact.rb
159
+ - lib/inquisitor/node.rb
160
+ - lib/inquisitor/settings.rb
161
+ - lib/inquisitor/web.rb
162
+ - lib/inquisitor/version.rb
163
+ - lib/inquisitor/server/public/down.png
164
+ - lib/inquisitor/server/public/loading.gif
165
+ - lib/inquisitor/server/public/script.js
166
+ - lib/inquisitor/server/public/style.css
167
+ - lib/inquisitor/server/public/up.png
168
+ - lib/inquisitor/server/views/layout.haml
169
+ - lib/inquisitor/server/views/index.haml
170
+ - lib/inquisitor.rb
171
+ - bin/monitor
172
+ - bin/monitor_web
173
+ - README.md
174
+ - LICENSE
175
+ - spec/inquisitor/node_spec.rb
176
+ - spec/inquisitor/web_spec.rb
177
+ - spec/inquisitor/contact_spec.rb
178
+ - spec/inquisitor/outpost_factory_spec.rb
179
+ - spec/inquisitor/settings_spec.rb
180
+ - spec/support/blueprints.rb
181
+ - spec/spec_helper.rb
182
+ - spec/spec_integration_helper.rb
183
+ homepage: https://github.com/brain-geek/inquisitor
184
+ licenses: []
185
+
186
+ post_install_message:
187
+ rdoc_options: []
188
+
189
+ require_paths:
190
+ - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ hash: 3
197
+ segments:
198
+ - 0
199
+ version: "0"
200
+ required_rubygems_version: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ hash: 3
206
+ segments:
207
+ - 0
208
+ version: "0"
209
+ requirements: []
210
+
211
+ rubyforge_project:
212
+ rubygems_version: 1.8.11
213
+ signing_key:
214
+ specification_version: 3
215
+ summary: Monitoring daemon with simple web UI.
216
+ test_files:
217
+ - spec/inquisitor/node_spec.rb
218
+ - spec/inquisitor/web_spec.rb
219
+ - spec/inquisitor/contact_spec.rb
220
+ - spec/inquisitor/outpost_factory_spec.rb
221
+ - spec/inquisitor/settings_spec.rb
222
+ - spec/support/blueprints.rb
223
+ - spec/spec_helper.rb
224
+ - spec/spec_integration_helper.rb