rack-ping 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rack-ping.gemspec
4
+ gemspec
@@ -0,0 +1,5 @@
1
+ guard 'minitest' do
2
+ watch(%r|^spec/(.*)_spec\.rb|)
3
+ watch(%r|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
5
+ end
@@ -0,0 +1,62 @@
1
+ # Rack::Ping
2
+ A Rack middleware that should indicate the health of your service.
3
+
4
+
5
+ ## Usage
6
+ Here is a simple example (see `examples`)
7
+
8
+ map '/ping' do
9
+ use Rack::Ping do |ping|
10
+ ping.check_url "http://localhost:9292/"
11
+ ping.ok_regex /goodbye/
12
+ end
13
+ end
14
+
15
+ run lambda{|env| [200, {'Content-Type' => 'text/html'}, ["hello"]]}
16
+
17
+ ## Options
18
+
19
+ When building/mounting your rack, use the `ping` configuration variable,
20
+ specify:
21
+
22
+ * `version` is an accessor for your application version. `App::VERSION`
23
+ would be a good idea.
24
+ * `check_url` is a url that `ping` will fetch and run `ok_regex` on. If
25
+ the match is ok, we're good. You must specify `check_url` and
26
+ `ok_regex` togather. `timeout_secs` is the amount of seconds we wait
27
+ until spitting out an error.
28
+ * `check` will accept a block to run. This is a good alternative to
29
+ `check_url`: run a couple of sanity checks to indicate you're good.
30
+ * `ok_code`, `error_code`, `ok_text`, `error_text` are configuration for
31
+ you to use, to configure against LB quirks. The default config should
32
+ work against ELBs (Amazon elastic LB).
33
+
34
+ ## Headers
35
+
36
+ `ping` will output intelligent headers. First `x-ping-error` will try to
37
+ explain why ping failed.
38
+
39
+ Next, `x-app-version` will expose the current deployed version of your
40
+ app. This is good in order to validate nothing crawled up to production,
41
+ as well as validation for post-production deployment.
42
+
43
+ `ping` will bust any browser/client cache for you.
44
+
45
+
46
+ ## Contributing
47
+
48
+ Guard is set up for your ease of development. Here's how to go from 0 to
49
+ ready.
50
+
51
+ $ git clone https://github.com/jondot/rack-ping
52
+ $ cd rack-ping
53
+ $ bundle install
54
+ $ guard
55
+
56
+ Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
57
+
58
+
59
+ ## Copyright
60
+
61
+ Copyright (c) 2011 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See MIT-LICENSE for further details.
62
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,10 @@
1
+ require 'rack/ping'
2
+
3
+ map '/ping' do
4
+ use Rack::Ping do |ping|
5
+ ping.check_url "http://localhost:9292/"
6
+ ping.ok_regex /goodbye/
7
+ end
8
+ end
9
+
10
+ run lambda{|env| [200, {'Content-Type' => 'text/html'}, ["hello"]]}
@@ -0,0 +1,80 @@
1
+ require 'open-uri'
2
+
3
+ module Rack
4
+ class Ping
5
+ attr_reader :config
6
+
7
+ def initialize(app)
8
+ @config = {
9
+ :version => '0',
10
+ :check_url => nil,
11
+ :ok_regex => nil,
12
+ :ok_text => 'ok',
13
+ :ok_code => 200,
14
+ :timeout_secs => 5,
15
+ :error_text => 'error',
16
+ :error_code => 500
17
+ }
18
+
19
+ yield self if block_given?
20
+ end
21
+
22
+ %w[version check_url ok_regex ok_text ok_code timeout_secs error_text error_code].each do |meth|
23
+ define_method(meth) { |value| @config[meth.to_sym] = value }
24
+ end
25
+
26
+ def check(&block)
27
+ @check_block = block
28
+ end
29
+
30
+ def call(env)
31
+ if @check_block
32
+ begin
33
+ return @check_block.call() ? ok : error("logic")
34
+ rescue
35
+ return error("logic: #{$!}")
36
+ end
37
+ end
38
+
39
+ if @config[:ok_regex] && @config[:check_url]
40
+ begin
41
+ timeout(@config[:timeout_secs]) do
42
+ text = open(@config[:check_url]).read
43
+ return error("regex") unless text =~ @config[:ok_regex]
44
+ end
45
+ rescue Timeout::Error
46
+ return error("timeout")
47
+ rescue
48
+ return error("url: #{$!}")
49
+ end
50
+ end
51
+
52
+ return ok
53
+ end
54
+
55
+ def error(reason)
56
+ [ @config[:error_code],
57
+ NO_CACHE.merge({
58
+ 'Content-Type' => 'text/html',
59
+ 'x-app-version' => @config[:version],
60
+ 'x-ping-error' => reason
61
+ }),
62
+ [@config[:error_text]] ]
63
+ end
64
+
65
+ def ok
66
+ [ @config[:ok_code],
67
+ NO_CACHE.merge({
68
+ 'Content-Type' => 'text/html',
69
+ 'x-app-version' => @config[:version]
70
+ }),
71
+ [@config[:ok_text]] ]
72
+ end
73
+ private
74
+ NO_CACHE = {
75
+ "Cache-Control" => "no-cache, no-store, max-age=0, must-revalidate",
76
+ "Pragma" => "no-cache",
77
+ "Expires" => "Tue, 8 Sep 1981 08:42:00 UTC"
78
+ }
79
+ end
80
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class Ping
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rack/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rack-ping"
7
+ s.version = Rack::Ping::VERSION
8
+ s.authors = ["Dotan Nahum"]
9
+ s.email = ["jondotan@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Health checking Rack middleware}
12
+ s.description = %q{Health checking Rack middleware}
13
+
14
+ s.rubyforge_project = "rack-ping"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'guard-minitest'
22
+ s.add_development_dependency 'rack-test'
23
+ s.add_development_dependency 'webmock'
24
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+ require 'rack/ping'
3
+
4
+
5
+ def app
6
+ lambda{|env| [200, {'Content-Type' => 'text/html'}, ["hello"]]}
7
+ end
8
+
9
+ def must_bust_cache(h)
10
+ h["Cache-Control"].must_equal "no-cache, no-store, max-age=0, must-revalidate"
11
+ h["Pragma"].must_equal "no-cache"
12
+ h["Expires"].must_equal "Tue, 8 Sep 1981 08:42:00 UTC"
13
+ end
14
+
15
+ describe Rack::Ping do
16
+ it "should bust cache" do
17
+ s, h, b = Rack::Ping.new(app).call({})
18
+ must_bust_cache(h)
19
+ end
20
+
21
+ it "should have sane defaults" do
22
+ # when ok
23
+ s, h, b = Rack::Ping.new(app).call({})
24
+
25
+ s.must_equal 200
26
+ h['x-app-version'].must_equal '0'
27
+ b[0].must_equal 'ok'
28
+ must_bust_cache(h)
29
+
30
+ # when error
31
+ s, h, b = Rack::Ping.new(app) do |ping|
32
+ ping.check { false }
33
+ end.call({})
34
+
35
+ s.must_equal 500
36
+ b[0].must_equal 'error'
37
+ must_bust_cache(h)
38
+ end
39
+
40
+ module MyApp
41
+ VERSION = '1.0.0'
42
+ end
43
+
44
+ it "should pick up application version" do
45
+ s, h, b = Rack::Ping.new(app) do |ping|
46
+ ping.version MyApp::VERSION
47
+ end.call({})
48
+ h['x-app-version'].must_equal '1.0.0'
49
+ end
50
+
51
+
52
+ it "should run check code when available" do
53
+ s, h, b = Rack::Ping.new(app) do |ping|
54
+ ping.check do
55
+ false
56
+ end
57
+ end.call({})
58
+
59
+ s.must_equal 500
60
+ b[0].must_equal 'error'
61
+ h['x-ping-error'].must_equal "logic"
62
+ must_bust_cache(h)
63
+
64
+
65
+ s, h, b = Rack::Ping.new(app) do |ping|
66
+ ping.check do
67
+ raise "error"
68
+ end
69
+ end.call({})
70
+
71
+ s.must_equal 500
72
+ b[0].must_equal 'error'
73
+ h['x-ping-error'].must_equal "logic: error"
74
+ must_bust_cache(h)
75
+ end
76
+
77
+ it "should fetch url content and run regex on it when available" do
78
+ stub_request(:any, "http://google.com").to_return(:body => "google is awesome")
79
+ s, h, b = Rack::Ping.new(app) do |ping|
80
+ ping.check_url "http://google.com"
81
+ ping.ok_regex /awesome/
82
+ ping.ok_text "groovy"
83
+ end.call({})
84
+
85
+ s.must_equal 200
86
+ b[0].must_equal 'groovy'
87
+ must_bust_cache(h)
88
+
89
+
90
+ s, h, b = Rack::Ping.new(app) do |ping|
91
+ ping.check_url "http://google.com"
92
+ ping.ok_regex /bing/
93
+ ping.ok_text "groovy"
94
+ end.call({})
95
+
96
+ s.must_equal 500
97
+ b[0].must_equal 'error'
98
+ must_bust_cache(h)
99
+ end
100
+
101
+ it "should timeout when resource at url is unavailable" do
102
+ stub_request(:any, "http://google.com").to_timeout
103
+ s, h, b = Rack::Ping.new(app) do |ping|
104
+ ping.check_url "http://google.com"
105
+ ping.ok_regex /awesome/
106
+ ping.error_text "shitty"
107
+ end.call({})
108
+
109
+ s.must_equal 500
110
+ b[0].must_equal 'shitty'
111
+ h['x-ping-error'].must_equal "timeout"
112
+ must_bust_cache(h)
113
+ end
114
+
115
+ end
@@ -0,0 +1,8 @@
1
+ require 'minitest/autorun'
2
+ require 'rack/test'
3
+ require 'webmock/minitest'
4
+
5
+ include Rack::Test::Methods
6
+ def r
7
+ last_response
8
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-ping
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dotan Nahum
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-19 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard-minitest
16
+ requirement: &89268900 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *89268900
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack-test
27
+ requirement: &89268680 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *89268680
36
+ - !ruby/object:Gem::Dependency
37
+ name: webmock
38
+ requirement: &89268450 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *89268450
47
+ description: Health checking Rack middleware
48
+ email:
49
+ - jondotan@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - Guardfile
57
+ - README.md
58
+ - Rakefile
59
+ - examples/config.ru
60
+ - lib/rack/ping.rb
61
+ - lib/rack/version.rb
62
+ - rack-ping.gemspec
63
+ - spec/rack/ping_spec.rb
64
+ - spec/spec_helper.rb
65
+ homepage: ''
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project: rack-ping
85
+ rubygems_version: 1.8.10
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Health checking Rack middleware
89
+ test_files: []