rack-ping 0.0.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.
@@ -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: []