last-resort 0.0.8 → 0.0.10
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.
- 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
|