outpost 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG.rdoc +16 -0
  3. data/Gemfile +9 -3
  4. data/Gemfile.lock +39 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.markdown +40 -8
  7. data/Rakefile +14 -0
  8. data/TODO.md +7 -0
  9. data/lib/outpost.rb +1 -1
  10. data/lib/outpost/application.rb +143 -0
  11. data/lib/outpost/expectations/response_body.rb +23 -9
  12. data/lib/outpost/expectations/response_code.rb +5 -0
  13. data/lib/outpost/expectations/response_time.rb +10 -1
  14. data/lib/outpost/notifiers.rb +2 -0
  15. data/lib/outpost/notifiers/campfire.rb +50 -0
  16. data/lib/outpost/notifiers/email.rb +59 -0
  17. data/lib/outpost/report.rb +7 -1
  18. data/lib/outpost/scout.rb +82 -0
  19. data/lib/outpost/scout_config.rb +10 -4
  20. data/lib/outpost/scouts/http.rb +28 -7
  21. data/lib/outpost/scouts/ping.rb +26 -6
  22. data/lib/outpost/version.rb +4 -1
  23. data/outpost.gemspec +0 -2
  24. data/test/integration/{basic_dsl_test.rb → basic_application_test.rb} +5 -5
  25. data/test/integration/more_complex_test.rb +20 -8
  26. data/test/integration/notifiers_test.rb +51 -0
  27. data/test/outpost/dsl_test.rb +74 -3
  28. data/test/outpost/expectations/response_body_test.rb +13 -15
  29. data/test/outpost/expectations/response_code_test.rb +5 -7
  30. data/test/outpost/expectations/response_time_test.rb +9 -11
  31. data/test/outpost/notifiers/campfire_test.rb +72 -0
  32. data/test/outpost/notifiers/email_test.rb +90 -0
  33. data/test/outpost/scout_test.rb +5 -6
  34. data/test/outpost/scouts/http_test.rb +51 -0
  35. data/test/outpost/scouts/ping_test.rb +41 -0
  36. data/test/support/nothing_raised.rb +10 -0
  37. data/test/support/server.rb +0 -1
  38. data/test/support/stubs.rb +11 -0
  39. data/test/test_helper.rb +8 -6
  40. metadata +32 -22
  41. data/lib/outpost/dsl.rb +0 -54
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .yardoc
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,16 @@
1
+
2
+ == 0.2
3
+ * Features
4
+ * Adding support for Notifications (Email and Campfire)
5
+ * RDoc documentation
6
+ * Refactoring, tests and cleanups
7
+
8
+ * Deprecations
9
+ * Renaming Outpost::DSL to Outpost::Application
10
+
11
+ * Bug Fixes
12
+ * Fixing Rake task to publish the gem (by github.com/ManuelKiessling)
13
+ * HTTP Scout now fails when it is not able to connect to the server
14
+
15
+ == 0.1
16
+ * Initial release
data/Gemfile CHANGED
@@ -1,10 +1,16 @@
1
1
  source :rubygems
2
2
 
3
- gem 'net-ping', :require => false
4
-
5
3
  group :test do
4
+ gem 'mail', :require => false
5
+ gem 'net-ping', :require => false
6
+ gem 'tinder', :require => false
7
+
6
8
  gem 'thin'
7
9
  gem 'rack'
8
10
  gem 'sinatra'
9
- gem 'ruby-debug19'
11
+
12
+ gem 'minitest', '~> 2.0.2', :platforms => :ruby_18
13
+ gem 'ruby-debug', :platforms => :ruby_18
14
+
15
+ gem 'ruby-debug19', :platforms => :ruby_19
10
16
  end
data/Gemfile.lock CHANGED
@@ -1,14 +1,37 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activesupport (3.0.3)
5
+ addressable (2.2.2)
4
6
  archive-tar-minitar (0.5.2)
5
7
  columnize (0.3.2)
6
8
  daemons (1.1.0)
7
9
  eventmachine (0.12.10)
10
+ faraday (0.5.4)
11
+ addressable (~> 2.2.2)
12
+ multipart-post (~> 1.1.0)
13
+ rack (>= 1.1.0, < 2)
14
+ i18n (0.5.0)
15
+ linecache (0.43)
8
16
  linecache19 (0.5.11)
9
17
  ruby_core_source (>= 0.1.4)
18
+ mail (2.2.15)
19
+ activesupport (>= 2.3.6)
20
+ i18n (>= 0.4.0)
21
+ mime-types (~> 1.16)
22
+ treetop (~> 1.4.8)
23
+ mime-types (1.16)
24
+ minitest (2.0.2)
25
+ multipart-post (1.1.0)
10
26
  net-ping (1.3.7)
27
+ polyglot (0.3.1)
11
28
  rack (1.2.1)
29
+ roauth (0.0.3)
30
+ ruby-debug (0.10.4)
31
+ columnize (>= 0.1)
32
+ ruby-debug-base (~> 0.10.4.0)
33
+ ruby-debug-base (0.10.4)
34
+ linecache (>= 0.3)
12
35
  ruby-debug-base19 (0.11.24)
13
36
  columnize (>= 0.3.1)
14
37
  linecache19 (>= 0.5.11)
@@ -27,13 +50,29 @@ GEM
27
50
  eventmachine (>= 0.12.6)
28
51
  rack (>= 1.0.0)
29
52
  tilt (1.2.2)
53
+ tinder (1.4.3)
54
+ activesupport
55
+ eventmachine
56
+ faraday (~> 0.5.1)
57
+ mime-types
58
+ multipart-post
59
+ twitter-stream
60
+ treetop (1.4.9)
61
+ polyglot (>= 0.3.1)
62
+ twitter-stream (0.1.10)
63
+ eventmachine (>= 0.12.8)
64
+ roauth (>= 0.0.2)
30
65
 
31
66
  PLATFORMS
32
67
  ruby
33
68
 
34
69
  DEPENDENCIES
70
+ mail
71
+ minitest (~> 2.0.2)
35
72
  net-ping
36
73
  rack
74
+ ruby-debug
37
75
  ruby-debug19
38
76
  sinatra
39
77
  thin
78
+ tinder
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Vinicius Baggio Fuentes http://www.vinibaggio.net
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown CHANGED
@@ -1,8 +1,5 @@
1
1
  # Outpost
2
2
 
3
- Outpost is under development and is a project for the RMU: Ruby Mendicant
4
- University.
5
-
6
3
  ## Features
7
4
 
8
5
  Outpost is a tool to monitor the state of your service (not server). What does it mean?
@@ -21,8 +18,14 @@ It should report a status per declared system.
21
18
  The idea is to make a reliable framework for the Ruby developer to create his own monitoring rules.
22
19
  So, summing it all up, Nagios in Ruby, much cooler!
23
20
 
21
+ ## Information
22
+
23
+ * [Rdoc](http://rdoc.info/github/vinibaggio/outpost/master/frames)
24
+
24
25
  ## Installing
25
26
 
27
+ Outpost is tested with Ruby 1.8.7 and Ruby 1.9.2.
28
+
26
29
  gem install outpost
27
30
 
28
31
  ## Starting
@@ -33,7 +36,7 @@ To create your Outposts, you must require 'outpost'. You also need to include
33
36
  require 'outpost'
34
37
  require 'outpost/scouts'
35
38
 
36
- class Bla < Outpost::DSL
39
+ class Bla < Outpost::Application
37
40
  using Outpost::Scouts::Http => "web page" do
38
41
  options :host => 'localhost', :port => 3000
39
42
  report :up, :response_code => 200
@@ -52,7 +55,7 @@ Consider the following example:
52
55
  require 'outpost'
53
56
  require 'outpost/scouts'
54
57
 
55
- class HttpOutpostExample < Outpost::DSL
58
+ class HttpOutpostExample < Outpost::Application
56
59
  using Outpost::Scouts::Http => "web page" do
57
60
  options :host => 'localhost', :port => 3000
58
61
  report :up, :response_code => 200
@@ -71,7 +74,7 @@ reporting "down" in that case).
71
74
  ## Outpost
72
75
 
73
76
  Outpost is the description of the system and provides a DSL to do it.
74
- Check "How it works" section for an example, or check the [integration tests](https://github.com/vinibaggio/outpost/blob/master/test/integration/basic_dsl_test.rb)
77
+ Check "How it works" section for an example, or check the [integration tests](https://github.com/vinibaggio/outpost/blob/master/test/integration/basic_application_test.rb)
75
78
  for more.
76
79
 
77
80
  ## Scout
@@ -150,10 +153,39 @@ So you can easily create your own expectation. Let's recreate the :response\_cod
150
153
  You can also check the supplied expectations in the source of the project to have
151
154
  an idea on how to implement more complex rules.
152
155
 
156
+ ## Notifiers
157
+
158
+ Notifiers query Outposts and act upon its status and reports. In the example
159
+ below, an Email notifier is being used to report failures in the system to the
160
+ system administrator:
161
+
162
+ require 'outpost'
163
+ require 'outpost/scouts'
164
+ require 'outpost/notifiers'
165
+
166
+ class HttpOutpostExample < Outpost::Application
167
+ notify Outpost::Notifiers::Email, {
168
+ :from => 'outpost@example.com',
169
+ :to => 'sleep_deprived_admin@example.com'
170
+ }
171
+
172
+ using Outpost::Scouts::Http => "web page" do
173
+ options :host => 'localhost', :port => 3000
174
+ report :up, :response_code => 200
175
+ report :down, :response_body => {:match => /Ops/}
176
+ end
177
+ end
178
+ outpost = HttpOutpostExample.new
179
+ outpost.run # => :down
180
+
181
+ # Will send an email to the poor sleep-deprived Sys Admin if the system is
182
+ # down.
183
+ outpost.notify if outpost.down?
184
+
153
185
  ## TODO
154
186
 
155
- There's a lot to be done yet. For example, SSH support, :warning status, etc.
187
+ See [TODO](https://github.com/vinibaggio/outpost/blob/master/TODO.md).
156
188
 
157
189
  ## License
158
190
 
159
- MIT.
191
+ MIT License.
data/Rakefile CHANGED
@@ -1,5 +1,9 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+
1
3
  require 'rake/testtask'
2
4
 
5
+ require "outpost/version"
6
+
3
7
  desc 'Default: run tests'
4
8
  task :default => :test
5
9
 
@@ -10,3 +14,13 @@ Rake::TestTask.new(:test) do |t|
10
14
  t.pattern = 'test/**/*_test.rb'
11
15
  t.verbose = true
12
16
  end
17
+
18
+ desc 'Build a gem from gemspec'
19
+ task :build do
20
+ system "gem build outpost.gemspec"
21
+ end
22
+
23
+ desc 'Release new gem version'
24
+ task :release => :build do
25
+ system "gem push outpost-#{Outpost::VERSION}.gem"
26
+ end
data/TODO.md ADDED
@@ -0,0 +1,7 @@
1
+ # TODO
2
+
3
+ * SSH Support
4
+ * Daemon and scheduler
5
+ * New status: :warning
6
+ * Web dashboard
7
+ * Better error reporting
data/lib/outpost.rb CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  # Outpost definition
3
- require 'outpost/dsl'
3
+ require 'outpost/application'
4
4
  require 'outpost/report'
5
5
 
6
6
  # Scout definition
@@ -0,0 +1,143 @@
1
+ module Outpost
2
+ # This class is the basic structure of an Outpost application. It provides
3
+ # the basic DSL for you to configure the monitoring of your services.
4
+ # Example:
5
+ #
6
+ # class ExampleSuccess < Outpost::Application
7
+ # name "Example"
8
+ # using Outpost::Scouts::Http => 'master http server' do
9
+ # options :host => 'localhost', :port => 9595
10
+ # report :up, :response_code => 200
11
+ # end
12
+ # end
13
+ #
14
+ # @abstract
15
+ class Application
16
+ class << self
17
+ # Returns all the registered scouts.
18
+ attr_reader :scouts
19
+
20
+ # Returns all the registered notifiers.
21
+ attr_reader :notifiers
22
+
23
+ # Register a scout in the list of scouts.
24
+ #
25
+ # @param [Hash{Scout => String}, #read] scout_description A hash
26
+ # containing Scout class as key and its description as a value.
27
+ #
28
+ # @yield Block to be evaluated to configure the current {Scout}.
29
+ def using(scout_description, &block)
30
+ @scouts ||= Hash.new { |h, k| h[k] = {} }
31
+
32
+ config = ScoutConfig.new
33
+ config.instance_eval(&block)
34
+
35
+ scout_description.each do |scout, description|
36
+ @scouts[scout][:description] = description
37
+ @scouts[scout][:config] = config
38
+ end
39
+ end
40
+
41
+ # Register a notifier class in the list of notifications.
42
+ #
43
+ # @param [Class, #read] class A class that will be used to issue
44
+ # a notification. The class must accept a configuration hash in the
45
+ # constructor and also implement a #notify method that will receive an
46
+ # outpost instance. See {Outpost::Notifiers::Email} for an example.
47
+ #
48
+ # @param [Hash, #read] options Options that will be used to configure the
49
+ # notification class.
50
+ def notify(notifier, options={})
51
+ @notifiers ||= {}
52
+ @notifiers[notifier] = options
53
+ end
54
+
55
+ # Set the name of the scout. Can be used by notifiers in order to have
56
+ # a better description of the service in question.
57
+ #
58
+ # @param [String, #read] name The name to be given to a Outpost-based
59
+ # class.
60
+ def name(val=nil)
61
+ if val
62
+ @name = val
63
+ else
64
+ @name
65
+ end
66
+ end
67
+ end
68
+
69
+ # Returns the status of the last service check or nil if it didn't happen.
70
+ attr_reader :last_status
71
+
72
+ # Returns a list of {Report} containing the last results of the last check.
73
+ attr_reader :reports
74
+
75
+ # New instance of a Outpost-based class.
76
+ def initialize
77
+ @reports = []
78
+ @last_status = nil
79
+ end
80
+
81
+ # Execute all the scouts associated with an Outpost-based class and returns
82
+ # either :up or :down, depending on the results.
83
+ def run
84
+ @reports = self.class.scouts.map do |scout, options|
85
+ run_scout(scout, options)
86
+ end
87
+
88
+ statuses = @reports.map { |r| r.status }
89
+
90
+ @last_status = Report.summarize(statuses)
91
+ end
92
+
93
+ # Runs all notifications associated with an Outpost-based class.
94
+ def notify
95
+ if reports.any?
96
+ self.class.notifiers.each do |notifier, options|
97
+ # .dup is NOT reliable
98
+ options_copy = Marshal.load(Marshal.dump(options))
99
+ notifier.new(options_copy).notify(self)
100
+ end
101
+ end
102
+ end
103
+
104
+ # Returns true if the last status is :up
105
+ def up?
106
+ @last_status == :up
107
+ end
108
+
109
+ # Returns true if the last status is :down
110
+ def down?
111
+ @last_status == :down
112
+ end
113
+
114
+ # Returns the name of an Outpost-based class or the class name itself if
115
+ # not set.
116
+ #
117
+ # @return [String] The name of the Outpost
118
+ def name
119
+ self.class.name || self.class.to_s
120
+ end
121
+
122
+ # Returns the messages of the latest service check.
123
+ #
124
+ # @return [Array<String>] An array containing all report messages.
125
+ def messages
126
+ reports.map { |r| r.to_s }
127
+ end
128
+
129
+ private
130
+
131
+ # :nodoc:
132
+ def run_scout(scout, options)
133
+ scout_instance = scout.new(options[:description], options[:config])
134
+
135
+ params = {
136
+ :name => scout.name,
137
+ :description => options[:description],
138
+ :status => scout_instance.run
139
+ }
140
+ Report.new(params)
141
+ end
142
+ end
143
+ end
@@ -1,20 +1,34 @@
1
1
  module Outpost
2
2
  module Expectations
3
+ # Module containing response_body matching expectations. Extend your Scout
4
+ # with ResponseBody and it will gain response_body evaluation powers!
5
+ #
6
+ # It respond to the following rules:
7
+ # * match => If the response body matches the associated regular expression
8
+ # * not_match => If the response body does not match the associated regular
9
+ # expression
10
+ # * equals => If the response body matches exactly the associated string
11
+ # * differs => If the response body differs in any way the associated
12
+ # string.
3
13
  module ResponseBody
4
- RESPONSE_BODY_MAPPING = {
5
- :match => "=~",
6
- :not_match => "!~",
7
- :equals => "==",
8
- :differs => "!="
9
- }.freeze
10
-
14
+ # Installs the response body expectation
11
15
  def self.extended(base)
12
16
  base.expect :response_body, base.method(:evaluate_response_body)
13
17
  end
14
18
 
19
+ # Method that will be used as an expectation to evaluate response body
15
20
  def evaluate_response_body(scout, rules)
16
- rules.all? do |rule,comparison|
17
- scout.response_body.send(RESPONSE_BODY_MAPPING[rule], comparison)
21
+ rules.all? do |rule, comparison|
22
+ case rule
23
+ when :match
24
+ scout.response_body =~ comparison
25
+ when :not_match
26
+ scout.response_body !~ comparison
27
+ when :equals
28
+ scout.response_body == comparison
29
+ when :differs
30
+ scout.response_body != comparison
31
+ end
18
32
  end
19
33
  end
20
34
  end