last-resort 0.0.8 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/.rspec +3 -0
- data/README.md +23 -20
- data/Rakefile +5 -0
- data/bin/last-resort +39 -2
- data/last-resort.gemspec +9 -5
- data/lib/last-resort.rb +10 -17
- data/lib/last-resort/application.rb +120 -0
- data/lib/last-resort/commands.rb +159 -0
- data/lib/last-resort/config.rb +131 -0
- data/lib/last-resort/contextio.rb +1 -0
- data/lib/last-resort/scheduler.rb +29 -18
- data/lib/last-resort/twilio.rb +49 -47
- data/lib/last-resort/version.rb +2 -4
- data/lib/last-resort/webhooks.rb +6 -5
- data/spec/controller_spec.rb +106 -0
- data/spec/scheduler_spec.rb +77 -0
- data/spec/spec_helper.rb +11 -2
- data/support/Gemfile +3 -0
- data/support/config.ru +11 -0
- data/support/dot_env +7 -0
- data/support/dot_gitignore +1 -0
- metadata +88 -30
- data/config/config.rb +0 -35
- data/lib/last-resort/config-lang.rb +0 -74
- data/lib/last-resort/controller.rb +0 -78
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LastResort::Scheduler do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@config = LastResort::Config.new true
|
7
|
+
@config.local_utc_offset_in_seconds = 5 * 60 * 60
|
8
|
+
@scheduler = LastResort::Scheduler.new @config
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "when expanding schedule times" do
|
12
|
+
DAY_NAMES = [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday]
|
13
|
+
|
14
|
+
it "should not expand ranges or fixnums" do
|
15
|
+
range = 1..10
|
16
|
+
@scheduler.expand_if_possible(range).should == [range]
|
17
|
+
|
18
|
+
hour = 1
|
19
|
+
@scheduler.expand_if_possible(hour).should == [hour]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should expand weekend/weekdays to day names" do
|
23
|
+
@scheduler.expand_if_possible(:weekends).all? { |day|
|
24
|
+
DAY_NAMES.include? day
|
25
|
+
}.should == true
|
26
|
+
|
27
|
+
@scheduler.expand_if_possible(:weekdays).all? { |day|
|
28
|
+
DAY_NAMES.include? day
|
29
|
+
}.should == true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should expand hour keywords to fixnum ranges" do
|
33
|
+
@scheduler.expand_if_possible(:all_hours).all? { |time|
|
34
|
+
time.is_a? Range
|
35
|
+
}.should == true
|
36
|
+
|
37
|
+
@scheduler.expand_if_possible(:off_hours).all? { |time|
|
38
|
+
time.is_a? Range
|
39
|
+
}.should == true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should raise an error on an unrecognized symbol" do
|
43
|
+
->{ @scheduler.expand_if_possible :no_way! }.should raise_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "when matching schedules" do
|
48
|
+
before :each do
|
49
|
+
@schedule = {
|
50
|
+
:hours => [0..23],
|
51
|
+
:days => [:everyday]
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
it "zone adjusted time should be in UTC" do
|
56
|
+
@scheduler.zone_adjusted_time.utc?.should == true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should match without a time argument" do
|
60
|
+
@scheduler.match?(@schedule).should == true
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should match when the schedule contains a time that falls into the described times/days" do
|
64
|
+
@scheduler.match?(@schedule, Time.now).should == true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not match when the time matches and the day doesn't" do
|
68
|
+
@schedule[:days] = [:monday]
|
69
|
+
@scheduler.match?(@schedule, Time.new(1983, 4, 21)).should == false
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not match when the day matches and the time doesn't" do
|
73
|
+
@schedule[:hours] = [23]
|
74
|
+
@scheduler.match?(@schedule, Time.new(1983, 4, 21)).should == false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'last-resort'
|
2
3
|
require 'rspec'
|
3
|
-
require '
|
4
|
+
require 'rack'
|
5
|
+
require 'rack/test'
|
6
|
+
require 'webmock/rspec'
|
7
|
+
require 'twilio-ruby'
|
8
|
+
require 'nokogiri'
|
9
|
+
|
10
|
+
RSpec.configure do |conf|
|
11
|
+
conf.include Rack::Test::Methods
|
12
|
+
end
|
data/support/Gemfile
ADDED
data/support/config.ru
ADDED
data/support/dot_env
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.env
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: last-resort
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-05-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: sinatra
|
18
|
-
requirement: &
|
18
|
+
requirement: &70248095967180 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
@@ -23,10 +23,10 @@ dependencies:
|
|
23
23
|
version: '1.3'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70248095967180
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: twilio-ruby
|
29
|
-
requirement: &
|
29
|
+
requirement: &70248095965080 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ~>
|
@@ -34,43 +34,54 @@ dependencies:
|
|
34
34
|
version: '3.6'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70248095965080
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
40
|
-
requirement: &
|
39
|
+
name: oauth
|
40
|
+
requirement: &70248095962980 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '0.
|
45
|
+
version: '0.4'
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70248095962980
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
51
|
-
requirement: &
|
50
|
+
name: gli
|
51
|
+
requirement: &70248095960280 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ~>
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
56
|
+
version: '1.6'
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70248095960280
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
62
|
-
requirement: &
|
61
|
+
name: colored
|
62
|
+
requirement: &70248095983900 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *70248095983900
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: launchy
|
73
|
+
requirement: &70248095980580 !ruby/object:Gem::Requirement
|
63
74
|
none: false
|
64
75
|
requirements:
|
65
76
|
- - ~>
|
66
77
|
- !ruby/object:Gem::Version
|
67
|
-
version: '1
|
78
|
+
version: '2.1'
|
68
79
|
type: :runtime
|
69
80
|
prerelease: false
|
70
|
-
version_requirements: *
|
81
|
+
version_requirements: *70248095980580
|
71
82
|
- !ruby/object:Gem::Dependency
|
72
83
|
name: rspec
|
73
|
-
requirement: &
|
84
|
+
requirement: &70248095979100 !ruby/object:Gem::Requirement
|
74
85
|
none: false
|
75
86
|
requirements:
|
76
87
|
- - ~>
|
@@ -78,10 +89,10 @@ dependencies:
|
|
78
89
|
version: 2.9.0
|
79
90
|
type: :development
|
80
91
|
prerelease: false
|
81
|
-
version_requirements: *
|
92
|
+
version_requirements: *70248095979100
|
82
93
|
- !ruby/object:Gem::Dependency
|
83
94
|
name: webmock
|
84
|
-
requirement: &
|
95
|
+
requirement: &70248096002660 !ruby/object:Gem::Requirement
|
85
96
|
none: false
|
86
97
|
requirements:
|
87
98
|
- - ~>
|
@@ -89,10 +100,43 @@ dependencies:
|
|
89
100
|
version: 1.8.5
|
90
101
|
type: :development
|
91
102
|
prerelease: false
|
92
|
-
version_requirements: *
|
103
|
+
version_requirements: *70248096002660
|
93
104
|
- !ruby/object:Gem::Dependency
|
94
105
|
name: awesome_print
|
95
|
-
requirement: &
|
106
|
+
requirement: &70248096001360 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: *70248096001360
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: rack
|
117
|
+
requirement: &70248096000160 !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: *70248096000160
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rack-test
|
128
|
+
requirement: &70248095999180 !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: *70248095999180
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: nokogiri
|
139
|
+
requirement: &70248095997580 !ruby/object:Gem::Requirement
|
96
140
|
none: false
|
97
141
|
requirements:
|
98
142
|
- - ! '>='
|
@@ -100,8 +144,12 @@ dependencies:
|
|
100
144
|
version: '0'
|
101
145
|
type: :development
|
102
146
|
prerelease: false
|
103
|
-
version_requirements: *
|
104
|
-
description:
|
147
|
+
version_requirements: *70248095997580
|
148
|
+
description: Last Resort is a Ruby gem for monitoring email sent by automated services
|
149
|
+
(monit, logging packages, external ping services, etc.) and calling your phone to
|
150
|
+
tell you about the important ones. Using free and trial tiers available from context.io,
|
151
|
+
twilio and heroku, Last Resort can be deployed in a reliable environment and perform
|
152
|
+
up to 1500 emergency calls for free.
|
105
153
|
email:
|
106
154
|
- ianha0@gmail.com
|
107
155
|
- vimota@gmail.com
|
@@ -112,24 +160,32 @@ extensions: []
|
|
112
160
|
extra_rdoc_files: []
|
113
161
|
files:
|
114
162
|
- .gitignore
|
163
|
+
- .rspec
|
115
164
|
- Gemfile
|
116
165
|
- Gemfile.lock
|
117
166
|
- LICENSE
|
118
167
|
- README.md
|
119
168
|
- Rakefile
|
120
169
|
- bin/last-resort
|
121
|
-
- config/config.rb
|
122
170
|
- last-resort.gemspec
|
123
171
|
- lib/last-resort.rb
|
124
|
-
- lib/last-resort/
|
172
|
+
- lib/last-resort/application.rb
|
173
|
+
- lib/last-resort/commands.rb
|
174
|
+
- lib/last-resort/config.rb
|
125
175
|
- lib/last-resort/contextio.rb
|
126
|
-
- lib/last-resort/controller.rb
|
127
176
|
- lib/last-resort/scheduler.rb
|
128
177
|
- lib/last-resort/twilio.rb
|
129
178
|
- lib/last-resort/version.rb
|
130
179
|
- lib/last-resort/webhooks.rb
|
180
|
+
- spec/controller_spec.rb
|
181
|
+
- spec/scheduler_spec.rb
|
131
182
|
- spec/spec_helper.rb
|
132
|
-
|
183
|
+
- support/Gemfile
|
184
|
+
- support/config.ru
|
185
|
+
- support/dot_env
|
186
|
+
- support/dot_gitignore
|
187
|
+
- support/schedule.rb
|
188
|
+
homepage: https://github.com/ianha/LastResort
|
133
189
|
licenses: []
|
134
190
|
post_install_message:
|
135
191
|
rdoc_options: []
|
@@ -152,7 +208,9 @@ rubyforge_project:
|
|
152
208
|
rubygems_version: 1.8.10
|
153
209
|
signing_key:
|
154
210
|
specification_version: 3
|
155
|
-
summary:
|
211
|
+
summary: Calls your phone when critical emails arrive
|
156
212
|
test_files:
|
213
|
+
- spec/controller_spec.rb
|
214
|
+
- spec/scheduler_spec.rb
|
157
215
|
- spec/spec_helper.rb
|
158
216
|
has_rdoc:
|
data/config/config.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
configure :host => "",
|
2
|
-
:twilio_sid => "",
|
3
|
-
:twilio_auth_token => "",
|
4
|
-
:contextio_account => "",
|
5
|
-
:contextio_key => "",
|
6
|
-
:contextio_secret => ""
|
7
|
-
|
8
|
-
|
9
|
-
# DEFINE YOUR CONTACTS
|
10
|
-
|
11
|
-
contact :ian, ""
|
12
|
-
contact :scott, ""
|
13
|
-
contact :victor, ""
|
14
|
-
|
15
|
-
|
16
|
-
# DEFINE WHAT EMAILS YOU WANT TO WATCH FOR
|
17
|
-
|
18
|
-
match :subject => /server down/ # rackspace ping
|
19
|
-
match :subject => /resource limit reached/ # monit
|
20
|
-
|
21
|
-
|
22
|
-
# DEFINE WHO TO CALL AND WHEN
|
23
|
-
|
24
|
-
between 19..22, :on => [:wednesday, :thursday] do
|
25
|
-
call :victor
|
26
|
-
end
|
27
|
-
|
28
|
-
between :off_hours, :on => :weekdays do
|
29
|
-
call :scott
|
30
|
-
end
|
31
|
-
|
32
|
-
between :all_hours, :on => :weekends do
|
33
|
-
call [:ian, :scott, :victor]
|
34
|
-
end
|
35
|
-
|
@@ -1,74 +0,0 @@
|
|
1
|
-
module LastResort
|
2
|
-
class Config
|
3
|
-
|
4
|
-
CONFIG_PATH = "#{Dir.pwd}/schedule.rb"
|
5
|
-
|
6
|
-
attr_accessor :host,
|
7
|
-
:contacts,
|
8
|
-
:matchers,
|
9
|
-
:schedules,
|
10
|
-
:twilio_sid, :twilio_auth_token,
|
11
|
-
:contextio_account, :contextio_key, :contextio_secret
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@contacts = {}
|
15
|
-
@matchers = []
|
16
|
-
@schedules = []
|
17
|
-
run_config_in_context
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def run_config_in_context
|
23
|
-
source = open(CONFIG_PATH).read
|
24
|
-
self.instance_eval source
|
25
|
-
end
|
26
|
-
|
27
|
-
def configure params
|
28
|
-
@host = params[:host]
|
29
|
-
@twilio_sid = params[:twilio_sid]
|
30
|
-
@twilio_auth_token = params[:twilio_auth_token]
|
31
|
-
@contextio_key = params[:contextio_key]
|
32
|
-
@contextio_secret = params[:contextio_secret]
|
33
|
-
@contextio_account = params[:contextio_account]
|
34
|
-
end
|
35
|
-
|
36
|
-
def contact name, phone
|
37
|
-
@contacts[name] = { :name => name, :phone => scrub_phone(phone) }
|
38
|
-
end
|
39
|
-
|
40
|
-
def match matcher
|
41
|
-
@matchers << matcher
|
42
|
-
end
|
43
|
-
|
44
|
-
def between hours, options
|
45
|
-
hours = hours.is_a?(Array) ? hours : [hours]
|
46
|
-
|
47
|
-
days = options[:on] || :everyday
|
48
|
-
days = days.is_a?(Array) ? days : [days]
|
49
|
-
|
50
|
-
@current_schedule = {
|
51
|
-
:hours => hours,
|
52
|
-
:days => days
|
53
|
-
}
|
54
|
-
|
55
|
-
yield
|
56
|
-
|
57
|
-
@schedules << @current_schedule
|
58
|
-
@current_schedule = nil
|
59
|
-
end
|
60
|
-
|
61
|
-
def call contacts
|
62
|
-
contacts = contacts.is_a?(Array) ? contacts : [contacts]
|
63
|
-
@current_schedule[:contacts] = contacts
|
64
|
-
end
|
65
|
-
|
66
|
-
def scrub_phone phone
|
67
|
-
phone.gsub!(/\D/, '')
|
68
|
-
phone = "+1#{phone}" unless phone.start_with? "+1"
|
69
|
-
phone
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
CONFIG = LastResort::Config.new
|