flapjack 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +1 -1
- data/Dockerfile +12 -4
- data/README.md +24 -17
- data/etc/flapjack_config.yaml.example +38 -1
- data/features/cli_purge.feature +43 -0
- data/lib/flapjack/cli/flapper.rb +12 -10
- data/lib/flapjack/cli/purge.rb +77 -0
- data/lib/flapjack/cli/receiver.rb +15 -2
- data/lib/flapjack/cli/server.rb +2 -2
- data/lib/flapjack/data/contact.rb +1 -1
- data/lib/flapjack/data/entity_check.rb +50 -4
- data/lib/flapjack/gateways/jabber.rb +14 -14
- data/lib/flapjack/gateways/jsonapi/medium_methods.rb +2 -1
- data/lib/flapjack/gateways/sms_twilio.rb +115 -0
- data/lib/flapjack/gateways/sms_twilio/alert.text.erb +5 -0
- data/lib/flapjack/gateways/sms_twilio/rollup.text.erb +2 -0
- data/lib/flapjack/gateways/web.rb +20 -1
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +6 -4
- data/lib/flapjack/gateways/web/views/checks.html.erb +3 -0
- data/lib/flapjack/gateways/web/views/entities.html.erb +3 -0
- data/lib/flapjack/gateways/web/views/entity.html.erb +3 -0
- data/lib/flapjack/notifier.rb +4 -2
- data/lib/flapjack/pikelet.rb +5 -3
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/contact_spec.rb +2 -2
- data/spec/lib/flapjack/data/entity_check_spec.rb +5 -1
- data/spec/lib/flapjack/gateways/sms_twilio_spec.rb +88 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4e8b5d1bee24a164e37f5db62f177d02cb470cb
|
4
|
+
data.tar.gz: f7e916ff508251675628c89ff70a31a030ee31b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ea75824a365cf143acd0db2581a440799a8d9dda7b093fc55fb3325b05dc5bc4617e64d548bc7529a6bb64a3562f7c202daf9640c4b6c6e489f42119f6e84e0
|
7
|
+
data.tar.gz: 05ed36b6fe5ad8745b4e4d27e44f1bdbf7097c59d4ff1bf5a31edf92ab72e157087e904a44d5e2147584eab58fcd050806f59130b77cf69692945d6920e89f77
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
## Flapjack Changelog
|
2
2
|
|
3
|
+
# 1.1.0 - 2014-09-10
|
4
|
+
- Feature: Add autorefresh for the web GUI (Closes: #494) #607 (@Hobbsee)
|
5
|
+
- Feature: twilio sms sending #633 (@jessereynolds)
|
6
|
+
- Feature: Flapjack command for httpchecker check engine #631 (@michaelneale)
|
7
|
+
- Feature: Purge historical check states cli #625 (@jessereynolds)
|
8
|
+
- Chore: bump Dockerfile to trusty and flapjack 1.0 #630 (@jessereynolds)
|
9
|
+
- Bug: Check freshness metrics appear to be broken #626 (@jessereynolds)
|
10
|
+
- Bug: Fix CMD to start flapjack with new cli format (Dockerfile) #629 (@auxesis)
|
11
|
+
- Bug: set key expiry properly for scheduled maintenance spanning current time #634 (@ali-graham)
|
12
|
+
- Bug: GET /media/id works for sms_twilio now #638 (@jessereynolds)
|
13
|
+
- Bug: expose newer media types in /edit_contacts #640 (@jessereynolds)
|
14
|
+
|
3
15
|
# 1.0.0 - 2014-08-21
|
4
16
|
- No changes
|
5
17
|
|
data/CONTRIBUTING.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#Contributing to ![Flapjack](http
|
1
|
+
#Contributing to ![Flapjack](http://flapjack.io/images/flapjack-2013-notext-transparent-50-50.png "Flapjack") Flapjack
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/flapjack/flapjack.png)](https://travis-ci.org/flapjack/flapjack)
|
4
4
|
|
data/Dockerfile
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
-
FROM ubuntu:
|
1
|
+
FROM stackbrew/ubuntu:trusty
|
2
2
|
|
3
|
-
RUN
|
3
|
+
RUN apt-get install -y gnupg
|
4
|
+
|
5
|
+
RUN gpg --keyserver keys.gnupg.net --recv-keys 803709B6
|
6
|
+
RUN gpg -a --export 803709B6 | apt-key add -
|
7
|
+
|
8
|
+
RUN echo "deb http://packages.flapjack.io/deb/1.0 trusty main" | tee /etc/apt/sources.list.d/flapjack.list
|
4
9
|
RUN apt-get update
|
5
|
-
RUN apt-
|
10
|
+
RUN apt-cache policy flapjack
|
11
|
+
RUN apt-get install -y flapjack
|
12
|
+
|
13
|
+
EXPOSE 3080 3081 3071 6380
|
6
14
|
|
7
|
-
CMD /etc/init.d/redis-flapjack start && /opt/flapjack/bin/flapjack start --no-daemonize
|
15
|
+
CMD /etc/init.d/redis-flapjack start && /opt/flapjack/bin/flapjack server start --no-daemonize
|
8
16
|
|
data/README.md
CHANGED
@@ -37,37 +37,43 @@ Additional check engines can be supported by adding additional receiver processe
|
|
37
37
|
|
38
38
|
**Ubuntu Precise 64 (12.04):**
|
39
39
|
|
40
|
+
Tell apt to trust the Flapjack package signing key:
|
41
|
+
|
42
|
+
```
|
43
|
+
gpg --keyserver keys.gnupg.net --recv-keys 803709B6
|
44
|
+
gpg -a --export 803709B6 | sudo apt-key add -
|
45
|
+
```
|
46
|
+
|
40
47
|
Add the Flapjack Debian repository to your Apt sources:
|
41
48
|
|
42
49
|
``` text
|
43
|
-
echo
|
44
|
-
sudo cp /tmp/flapjack.list /etc/apt/sources.list.d/flapjack.list
|
45
|
-
sudo apt-get update
|
50
|
+
echo "deb http://packages.flapjack.io/deb/1.0 precise main" | sudo tee /etc/apt/sources.list.d/flapjack.list
|
46
51
|
```
|
47
52
|
|
48
53
|
Install the latest Flapjack package:
|
49
54
|
|
50
55
|
``` text
|
56
|
+
sudo apt-get update
|
51
57
|
sudo apt-get install flapjack
|
52
58
|
```
|
53
59
|
|
54
|
-
Alternatively, [download the deb](http://packages.flapjack.io/deb/pool/main/f/flapjack/) and install using `sudo dpkg -i <filename>`
|
60
|
+
Alternatively, [download the deb](http://packages.flapjack.io/deb/1.0/pool/main/f/flapjack/) and install using `sudo dpkg -i <filename>`
|
55
61
|
|
56
|
-
The Flapjack package is an [Omnibus](https://github.com/opscode/omnibus
|
62
|
+
The Flapjack package is an [Omnibus](https://github.com/opscode/omnibus) package and as such contains most dependencies under `/opt/flapjack`, including Redis.
|
57
63
|
|
58
|
-
Installing the package will start Redis and Flapjack. You should now be able to access the Flapjack Web UI at:
|
64
|
+
Installing the package will start Redis (non standard port) and Flapjack. You should now be able to access the Flapjack Web UI at:
|
59
65
|
|
60
66
|
[http://localhost:3080/](http://localhost:3080)
|
61
67
|
|
62
|
-
And consume the REST API at:
|
68
|
+
And consume the [REST API](http://flapjack.io/docs/1.0/jsonapi/) at:
|
63
69
|
|
64
70
|
[http://localhost:3081/](http://localhost:3081)
|
65
71
|
|
66
|
-
N.B. The Redis installed by Flapjack runs on a non-standard port, so it doesn't conflict with other Redis instances you may already have installed.
|
72
|
+
N.B. The Redis installed by Flapjack runs on a non-standard port (6380), so it doesn't conflict with other Redis instances you may already have installed.
|
67
73
|
|
68
74
|
**Other OSes:**
|
69
75
|
|
70
|
-
Currently we only make a package for Ubuntu Precise (amd64). If you feel comfortable getting a ruby
|
76
|
+
Currently we only make a package for Ubuntu Precise (amd64). If you feel comfortable getting a ruby environment going on your preferred OS, then you can also just install Flapjack from rubygems.org:
|
71
77
|
|
72
78
|
```text
|
73
79
|
gem install flapjack
|
@@ -81,10 +87,10 @@ You'll also need Redis >= 2.6.12.
|
|
81
87
|
|
82
88
|
## Configuring
|
83
89
|
|
84
|
-
Have a look at the default config file and modify things as required.
|
90
|
+
Have a look at the [default config file](https://github.com/flapjack/flapjack/blob/master/etc/flapjack_config.yaml.example) and modify things as required. The package installer copies this to `/etc/flapjack/flapjack_config.yaml` if it doesn't already exist.
|
85
91
|
|
86
92
|
``` bash
|
87
|
-
#
|
93
|
+
# edit the config
|
88
94
|
sudo vi /etc/flapjack/flapjack_config.yaml
|
89
95
|
|
90
96
|
# reload the config
|
@@ -101,10 +107,10 @@ First up, start Redis if it's not already started:
|
|
101
107
|
|
102
108
|
``` bash
|
103
109
|
# status:
|
104
|
-
sudo /etc/init.d/redis status
|
110
|
+
sudo /etc/init.d/redis-flapjack status
|
105
111
|
|
106
112
|
# start:
|
107
|
-
sudo /etc/init.d/redis start
|
113
|
+
sudo /etc/init.d/redis-flapjack start
|
108
114
|
```
|
109
115
|
|
110
116
|
Operating Flapjack:
|
@@ -128,11 +134,11 @@ sudo /etc/init.d/flapjack start
|
|
128
134
|
|
129
135
|
## Using - Details
|
130
136
|
|
131
|
-
|
137
|
+
We are [updating](https://github.com/flapjack/flapjack/issues/624) this section of the docs.
|
132
138
|
|
133
139
|
## Developing Flapjack
|
134
140
|
|
135
|
-
Information on developing more Flapjack components or contributing to core Flapjack development can be found in the [
|
141
|
+
Information on developing more Flapjack components or contributing to core Flapjack development can be found in the [Developing](http://flapjack.io/docs/1.0/development/DEVELOPING/) section of [the docs](http://flapjack.io/docs/1.0/).
|
136
142
|
|
137
143
|
## Documentation Submodule
|
138
144
|
|
@@ -149,6 +155,7 @@ If you make changes to the documentation locally, here's how to publish them:
|
|
149
155
|
* git add, commit and push from inside the doc subdir
|
150
156
|
* Add, commit and push the doc dir from the root (this updates the pointer in the main git repo to the correct ref in the doc repo, we think...)
|
151
157
|
|
152
|
-
##
|
158
|
+
## RTFM
|
159
|
+
|
160
|
+
All of [the documentation](http://flapjack.io/docs).
|
153
161
|
|
154
|
-
[The Flapjack wiki](http://flapjack.io/docs/1.0/wiki/) has even more goodies
|
@@ -39,6 +39,7 @@ production:
|
|
39
39
|
queue: notifications
|
40
40
|
email_queue: email_notifications
|
41
41
|
sms_queue: sms_notifications
|
42
|
+
sms_twilio_queue: sms_twilio_notifications
|
42
43
|
sns_queue: sns_notifications
|
43
44
|
jabber_queue: jabber_notifications
|
44
45
|
pagerduty_queue: pagerduty_notifications
|
@@ -85,7 +86,7 @@ production:
|
|
85
86
|
# alert.text: '/etc/flapjack/templates/email/alert.text.erb'
|
86
87
|
# rollup.html: '/etc/flapjack/templates/email/rollup.html.erb'
|
87
88
|
# alert.html: '/etc/flapjack/templates/email/alert.html.erb'
|
88
|
-
#
|
89
|
+
# Sends SMS notifications via MessageNet (Australia only)
|
89
90
|
sms:
|
90
91
|
enabled: no
|
91
92
|
# the redis queue this pikelet will look for notifications on
|
@@ -100,6 +101,21 @@ production:
|
|
100
101
|
#templates:
|
101
102
|
# rollup.text: '/etc/flapjack/templates/sms/rollup.text.erb'
|
102
103
|
# alert.text: '/etc/flapjack/templates/sms/alert.text.erb'
|
104
|
+
# Sends SMS notifications via Twilio
|
105
|
+
sms_twilio:
|
106
|
+
enabled: no
|
107
|
+
queue: sms_twilio_notifications
|
108
|
+
account_sid: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
109
|
+
auth_token: "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
|
110
|
+
from: "+1xxxxxxxxxx"
|
111
|
+
logger:
|
112
|
+
level: INFO
|
113
|
+
syslog_errors: yes
|
114
|
+
# location of custom alert templates
|
115
|
+
# location of custom alert templates
|
116
|
+
#templates:
|
117
|
+
# rollup.text: '/etc/flapjack/templates/sms_twilio/rollup.text.erb'
|
118
|
+
# alert.text: '/etc/flapjack/templates/sms_twilio/alert.text.erb'
|
103
119
|
# Generates SNS notifications
|
104
120
|
sns:
|
105
121
|
enabled: no
|
@@ -150,6 +166,8 @@ production:
|
|
150
166
|
enabled: yes
|
151
167
|
port: 3080
|
152
168
|
timeout: 300
|
169
|
+
# Seconds between auto_refresh of entities/checks pages. Set to 0 to disable
|
170
|
+
auto_refresh: 120
|
153
171
|
access_log: "/var/log/flapjack/web_access.log"
|
154
172
|
api_url: "http://localhost:3081/"
|
155
173
|
# Full path to location of logo file, e.g. /etc/flapjack/custom_logo.png
|
@@ -233,6 +251,7 @@ development:
|
|
233
251
|
queue: notifications
|
234
252
|
email_queue: email_notifications
|
235
253
|
sms_queue: sms_notifications
|
254
|
+
sms_twilio_queue: sms_twilio_notifications
|
236
255
|
jabber_queue: jabber_notifications
|
237
256
|
pagerduty_queue: pagerduty_notifications
|
238
257
|
notification_log_file: log/notification.log
|
@@ -293,6 +312,22 @@ development:
|
|
293
312
|
#templates:
|
294
313
|
# rollup.text: '/etc/flapjack/templates/sms/rollup.text.erb'
|
295
314
|
# alert.text: '/etc/flapjack/templates/sms/alert.text.erb'
|
315
|
+
# Sends SMS messages via Twilio
|
316
|
+
sms_twilio:
|
317
|
+
enabled: no
|
318
|
+
queue: sms_twilio_notifications
|
319
|
+
account_sid: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
320
|
+
auth_token: "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
|
321
|
+
from: "+1xxxxxxxxxx"
|
322
|
+
logger:
|
323
|
+
level: INFO
|
324
|
+
syslog_errors: yes
|
325
|
+
# location of custom alert templates
|
326
|
+
# location of custom alert templates
|
327
|
+
#templates:
|
328
|
+
# rollup.text: '/etc/flapjack/templates/sms_twilio/rollup.text.erb'
|
329
|
+
# alert.text: '/etc/flapjack/templates/sms_twilio/alert.text.erb'
|
330
|
+
# Generates SNS notifications
|
296
331
|
# Connects to an XMPP (jabber) server, sends notifications (to rooms and individuals),
|
297
332
|
# handles acknowledgements from jabber users and other commands.
|
298
333
|
jabber:
|
@@ -335,6 +370,8 @@ development:
|
|
335
370
|
enabled: yes
|
336
371
|
port: 3080
|
337
372
|
timeout: 300
|
373
|
+
# Seconds between auto_refresh of entities/checks pages. Set to 0 to disable
|
374
|
+
auto_refresh: 120
|
338
375
|
access_log: "log/web_access.log"
|
339
376
|
api_url: "http://localhost:3081/"
|
340
377
|
# Full path to location of logo file, e.g. /etc/flapjack/custom_logo.png
|
@@ -0,0 +1,43 @@
|
|
1
|
+
@process
|
2
|
+
Feature: purge command line
|
3
|
+
As a systems administrator
|
4
|
+
I should be able to use purge
|
5
|
+
From the command line
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given a file named "purge.yaml" with:
|
9
|
+
"""
|
10
|
+
test:
|
11
|
+
redis:
|
12
|
+
db: 14
|
13
|
+
driver: ruby
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: Running with --help shows usage information
|
17
|
+
When I run `bundle exec bin/flapjack purge --help`
|
18
|
+
Then the exit status should be 0
|
19
|
+
And the output should contain "Purge data from Flapjack's database"
|
20
|
+
And the output should contain "--check arg"
|
21
|
+
|
22
|
+
Scenario: Running purge with no arguments exits uncleanly and shows usage
|
23
|
+
When I run `bundle exec bin/flapjack purge`
|
24
|
+
Then the exit status should not be 0
|
25
|
+
And the output should contain "Purge data from Flapjack's database"
|
26
|
+
|
27
|
+
#flapjack purge check_history --days 90
|
28
|
+
Scenario: Purge check data older than 90 days
|
29
|
+
When I run `bundle exec bin/flapjack -n test -c tmp/cucumber_cli/purge.yaml purge check_history --days 90`
|
30
|
+
Then the exit status should be 0
|
31
|
+
|
32
|
+
#flapjack purge check_history --days 2 --check "flapper.example:Flapper"
|
33
|
+
Scenario: keep only last two days of Flapper state changes
|
34
|
+
|
35
|
+
#flapjack purge check_history --state-changes +10
|
36
|
+
Scenario: purge all state changes except the newest 10 for all checks
|
37
|
+
|
38
|
+
#flapjack purge disabled_checks
|
39
|
+
Scenario: purge all data about disabled checks
|
40
|
+
|
41
|
+
#flapjack purge stale_checks --days 90
|
42
|
+
Scenario: purge all data about checks with no updates in the last 90 days
|
43
|
+
|
data/lib/flapjack/cli/flapper.rb
CHANGED
@@ -12,9 +12,13 @@ module Flapjack
|
|
12
12
|
# turn off reverse DNS resolution temporarily
|
13
13
|
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
begin
|
16
|
+
UDPSocket.open do |s|
|
17
|
+
s.connect '64.233.187.99', 1
|
18
|
+
s.addr.last
|
19
|
+
end
|
20
|
+
rescue Errno::ENETUNREACH => e
|
21
|
+
'127.0.0.1'
|
18
22
|
end
|
19
23
|
ensure
|
20
24
|
Socket.do_not_reverse_lookup = orig
|
@@ -36,7 +40,7 @@ module Flapjack
|
|
36
40
|
when !@options[:pidfile].nil?
|
37
41
|
@options[:pidfile]
|
38
42
|
when !@config_env['pid_dir'].nil?
|
39
|
-
@config_env['pid_dir']
|
43
|
+
File.join(@config_env['pid_dir'], 'flapper.pid')
|
40
44
|
else
|
41
45
|
"/var/run/flapjack/flapper.pid"
|
42
46
|
end
|
@@ -45,7 +49,7 @@ module Flapjack
|
|
45
49
|
when !@options[:logfile].nil?
|
46
50
|
@options[:logfile]
|
47
51
|
when !@config_env['log_dir'].nil?
|
48
|
-
@config_env['log_dir']
|
52
|
+
File.join(@config_env['log_dir'], 'flapper.log')
|
49
53
|
else
|
50
54
|
"/var/run/flapjack/flapper.log"
|
51
55
|
end
|
@@ -58,7 +62,7 @@ module Flapjack
|
|
58
62
|
print "flapper starting..."
|
59
63
|
print "\n" unless @options[:daemonize]
|
60
64
|
runner.execute(:daemonize => @options[:daemonize]) do
|
61
|
-
main(@options['bind-ip'], @options['bind-port'].to_i, @options[:frequency])
|
65
|
+
main(@options['bind-ip'] || Flapjack::CLI::Flapper.local_ip, @options['bind-port'].to_i, @options[:frequency])
|
62
66
|
end
|
63
67
|
puts " done."
|
64
68
|
end
|
@@ -184,8 +188,7 @@ command :flapper do |flapper|
|
|
184
188
|
|
185
189
|
start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
186
190
|
|
187
|
-
start.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to'
|
188
|
-
:default_value => Flapjack::CLI::Flapper.local_ip
|
191
|
+
start.flag [:b, 'bind-ip'], :desc => 'Override ADDRESS (IPv4 or IPv6) for flapper to bind to'
|
189
192
|
|
190
193
|
start.flag [:P, 'bind-port'], :desc => 'PORT for flapper to bind to (default: 12345)',
|
191
194
|
:default_value => '12345'
|
@@ -219,8 +222,7 @@ command :flapper do |flapper|
|
|
219
222
|
|
220
223
|
restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
221
224
|
|
222
|
-
restart.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to'
|
223
|
-
:default_value => Flapjack::CLI::Flapper.local_ip
|
225
|
+
restart.flag [:b, 'bind-ip'], :desc => 'Override ADDRESS (IPv4 or IPv6) for flapper to bind to'
|
224
226
|
|
225
227
|
restart.flag [:P, 'bind-port'], :desc => 'PORT for flapper to bind to (default: 12345)',
|
226
228
|
:default_value => 12345
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'hiredis'
|
4
|
+
require 'flapjack/configuration'
|
5
|
+
|
6
|
+
module Flapjack
|
7
|
+
module CLI
|
8
|
+
class Purge
|
9
|
+
|
10
|
+
def initialize(global_options, options)
|
11
|
+
@global_options = global_options
|
12
|
+
@options = options
|
13
|
+
|
14
|
+
config = Flapjack::Configuration.new
|
15
|
+
config.load(global_options[:config])
|
16
|
+
@config_env = config.all
|
17
|
+
|
18
|
+
if @config_env.nil? || @config_env.empty?
|
19
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
20
|
+
end
|
21
|
+
|
22
|
+
@redis_options = config.for_redis
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_history
|
26
|
+
# find all checks, or the check given
|
27
|
+
# purge old data for check
|
28
|
+
options = {}
|
29
|
+
if @options[:days]
|
30
|
+
options[:older_than] = @options[:days].to_i * 24 * 60 * 60
|
31
|
+
raise "days must be resolveable to an integer" unless @options[:days].to_i.to_s == @options[:days]
|
32
|
+
end
|
33
|
+
checks = if @options[:check]
|
34
|
+
[Flapjack::Data::EntityCheck.for_event_id(@options[:check], :redis => redis, :create_entity => true)]
|
35
|
+
else
|
36
|
+
Flapjack::Data::EntityCheck.all(:redis => redis, :create_entity => true)
|
37
|
+
end
|
38
|
+
purged = checks.map do |check|
|
39
|
+
p = check.purge_history(options)
|
40
|
+
p == 0 ? nil : p
|
41
|
+
end.compact
|
42
|
+
|
43
|
+
if purged.empty?
|
44
|
+
puts "Nothing to do"
|
45
|
+
else
|
46
|
+
puts "Purged #{purged.reduce(:+) || 0} historical check states over #{purged.length} checks."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def redis
|
53
|
+
@redis ||= Redis.new(@redis_options.merge(:driver => :ruby))
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Purge data from Flapjack's database"
|
61
|
+
command :purge do |purge|
|
62
|
+
|
63
|
+
purge.desc 'Purge check history'
|
64
|
+
purge.command :check_history do |check_history|
|
65
|
+
|
66
|
+
check_history.flag [:d, 'days'], :desc => "purge check history older than DAYS days ago",
|
67
|
+
:default_value => 90
|
68
|
+
|
69
|
+
check_history.flag [:c, 'check'], :desc => "affect history of only the CHECK"
|
70
|
+
|
71
|
+
check_history.action do |global_options,options,args|
|
72
|
+
purge = Flapjack::CLI::Purge.new(global_options, options)
|
73
|
+
purge.check_history
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -34,7 +34,7 @@ module Flapjack
|
|
34
34
|
when !@options[:pidfile].nil?
|
35
35
|
@options[:pidfile]
|
36
36
|
when !@config_env['pid_dir'].nil?
|
37
|
-
@config_env['pid_dir']
|
37
|
+
File.join(@config_env['pid_dir'], "#{@options[:type]}-receiver.pid")
|
38
38
|
else
|
39
39
|
"/var/run/flapjack/#{@options[:type]}-receiver.pid"
|
40
40
|
end
|
@@ -43,7 +43,7 @@ module Flapjack
|
|
43
43
|
when !@options[:logfile].nil?
|
44
44
|
@options[:logfile]
|
45
45
|
when !@config_env['log_dir'].nil?
|
46
|
-
@config_env['log_dir']
|
46
|
+
File.join(@config_env['log_dir'], "#{@options[:type]}-receiver.log")
|
47
47
|
else
|
48
48
|
"/var/run/flapjack/#{@options[:type]}-receiver.log"
|
49
49
|
end
|
@@ -633,6 +633,19 @@ command :receiver do |receiver|
|
|
633
633
|
end
|
634
634
|
end
|
635
635
|
|
636
|
+
receiver.desc 'HTTP checker for availability checking of services'
|
637
|
+
receiver.command :httpchecker do |httpchecker|
|
638
|
+
httpchecker.passthrough = true
|
639
|
+
httpchecker.action do |global_options, options, args|
|
640
|
+
libexec = Pathname.new(__FILE__).parent.parent.parent.parent.join('libexec').expand_path
|
641
|
+
httpchecker = libexec.join('httpchecker')
|
642
|
+
if httpchecker.exist?
|
643
|
+
Kernel.exec(httpchecker.to_s, *ARGV)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
|
636
649
|
receiver.desc 'HTTP API that caches and submits events'
|
637
650
|
receiver.command :httpbroker do |httpbroker|
|
638
651
|
httpbroker.passthrough = true
|
data/lib/flapjack/cli/server.rb
CHANGED
@@ -29,7 +29,7 @@ module Flapjack
|
|
29
29
|
when !@options[:pidfile].nil?
|
30
30
|
@options[:pidfile]
|
31
31
|
when !@config_env['pid_dir'].nil?
|
32
|
-
@config_env['pid_dir']
|
32
|
+
File.join(@config_env['pid_dir'], 'flapjack.pid')
|
33
33
|
else
|
34
34
|
"/var/run/flapjack/flapjack.pid"
|
35
35
|
end
|
@@ -38,7 +38,7 @@ module Flapjack
|
|
38
38
|
when !@options[:logfile].nil?
|
39
39
|
@options[:logfile]
|
40
40
|
when !@config_env['log_dir'].nil?
|
41
|
-
@config_env['log_dir']
|
41
|
+
File.join(@config_env['log_dir'], 'flapjack.log')
|
42
42
|
else
|
43
43
|
"/var/run/flapjack/flapjack.log"
|
44
44
|
end
|
@@ -22,7 +22,7 @@ module Flapjack
|
|
22
22
|
:media_intervals, :media_rollup_thresholds, :pagerduty_credentials
|
23
23
|
|
24
24
|
TAG_PREFIX = 'contact_tag'
|
25
|
-
ALL_MEDIA = ['email', 'sms', 'jabber', 'pagerduty', 'sns']
|
25
|
+
ALL_MEDIA = ['email', 'sms', 'sms_twilio', 'jabber', 'pagerduty', 'sns']
|
26
26
|
|
27
27
|
def self.all(options = {})
|
28
28
|
raise "Redis connection not set" unless redis = options[:redis]
|
@@ -63,6 +63,14 @@ module Flapjack
|
|
63
63
|
self.new(entity, check, :logger => logger, :redis => redis)
|
64
64
|
end
|
65
65
|
|
66
|
+
def self.all(options = {})
|
67
|
+
raise "Redis connection not set" unless redis = options[:redis]
|
68
|
+
checks = redis.keys('check:*').map {|c| c.match(/^check:(.*)$/) ; $1}
|
69
|
+
checks.map {|ec|
|
70
|
+
self.for_entity_id(ec, options)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
66
74
|
def self.find_current_for_entity_name(entity_name, options = {})
|
67
75
|
raise "Redis connection not set" unless redis = options[:redis]
|
68
76
|
redis.zrange("current_checks:#{entity_name}", 0, -1)
|
@@ -370,6 +378,7 @@ module Flapjack
|
|
370
378
|
#
|
371
379
|
def self.find_all_split_by_freshness(ages, options)
|
372
380
|
raise "Redis connection not set" unless redis = options[:redis]
|
381
|
+
logger = options[:logger]
|
373
382
|
|
374
383
|
raise "ages does not respond_to? :each and :each_with_index" unless ages.respond_to?(:each) && ages.respond_to?(:each_with_index)
|
375
384
|
raise "age values must respond_to? :to_i" unless ages.all? {|age| age.respond_to?(:to_i) }
|
@@ -382,10 +391,11 @@ module Flapjack
|
|
382
391
|
checks = []
|
383
392
|
# get all the current checks, with last update time
|
384
393
|
Flapjack::Data::Entity.all(:enabled => true, :redis => redis).each do |entity|
|
385
|
-
redis.zrange("current_checks:#{entity}", 0, -1, :withscores => true).each do |check, score|
|
386
|
-
checks << ["#{entity}:#{check}", score]
|
394
|
+
redis.zrange("current_checks:#{entity.name}", 0, -1, :withscores => true).each do |check, score|
|
395
|
+
checks << ["#{entity.name}:#{check}", score]
|
387
396
|
end
|
388
397
|
end
|
398
|
+
logger.debug("found #{checks.length} current checks on enabled entities") if logger
|
389
399
|
|
390
400
|
skeleton = ages.inject({}) {|memo, age| memo[age] = [] ; memo }
|
391
401
|
age_ranges = ages.reverse.each_cons(2)
|
@@ -512,8 +522,11 @@ module Flapjack
|
|
512
522
|
# if multiple scheduled maintenances found, find the end_time furthest in the future
|
513
523
|
most_futuristic = current_sched_ms.max {|sm| sm[:end_time] }
|
514
524
|
start_time = most_futuristic[:start_time]
|
515
|
-
|
516
|
-
|
525
|
+
|
526
|
+
duration = most_futuristic[:end_time] - current_time
|
527
|
+
if duration > 0
|
528
|
+
@redis.setex("#{@key}:scheduled_maintenance", duration.to_i, start_time)
|
529
|
+
end
|
517
530
|
end
|
518
531
|
|
519
532
|
# TODO allow summary to be changed as part of the termination
|
@@ -859,6 +872,39 @@ module Flapjack
|
|
859
872
|
@ack_hash
|
860
873
|
end
|
861
874
|
|
875
|
+
def purge_history(opts = {})
|
876
|
+
t = Time.now
|
877
|
+
older_than = opts[:older_than] # purge older than this number of seconds ago
|
878
|
+
raise ":older_than must be supplied" unless older_than
|
879
|
+
|
880
|
+
purge_stamps = historical_states(-1, t.to_i - older_than).map {|s| s[:timestamp]}
|
881
|
+
unless purge_stamps.empty?
|
882
|
+
@logger.info "purging #{purge_stamps.length} states from #{@key}" if @logger
|
883
|
+
deletees = []
|
884
|
+
purge_stamps.each do |timestamp|
|
885
|
+
deletees << "#{@key}:#{timestamp}:state"
|
886
|
+
deletees << "#{@key}:#{timestamp}:summary"
|
887
|
+
deletees << "#{@key}:#{timestamp}:count"
|
888
|
+
deletees << "#{@key}:#{timestamp}:check_latency"
|
889
|
+
end
|
890
|
+
@logger.info " deleting a bunch of keys 100 at a time..." if @logger
|
891
|
+
deletees.each_slice(100) do |batch|
|
892
|
+
@redis.del(batch)
|
893
|
+
end
|
894
|
+
@logger.info " removing a range of items from the #{@key}:sorted_state_timestamps sorted set" if @logger
|
895
|
+
@redis.zremrangebyscore("#{@key}:sorted_state_timestamps", '-inf', t.to_i - older_than)
|
896
|
+
@logger.info " getting the #{@key}:states list" if @logger
|
897
|
+
states = @redis.lrange("#{@key}:states", 0, -1)
|
898
|
+
index = 0
|
899
|
+
while states[index].to_i < older_than do
|
900
|
+
index += 1
|
901
|
+
end
|
902
|
+
@logger.info " trimming the #{@key}:states from #{index}, length #{states.length}" if @logger
|
903
|
+
@redis.ltrim("#{@key}:states", index, -1)
|
904
|
+
end
|
905
|
+
purge_stamps.length
|
906
|
+
end
|
907
|
+
|
862
908
|
def to_jsonapi(opts = {})
|
863
909
|
{
|
864
910
|
"name" => @check,
|
@@ -302,9 +302,9 @@ module Flapjack
|
|
302
302
|
end
|
303
303
|
|
304
304
|
when /^(?:find )?checks(?:\s+matching\s+\/(.+)\/)?\s+on\s+(?:entities matching\s+\/(.+)\/|([a-z0-9\-\.]+))/im
|
305
|
-
check_pattern
|
306
|
-
entity_pattern = $2 ? $2.
|
307
|
-
entity_name
|
305
|
+
check_pattern = $1 ? $1.strip : nil
|
306
|
+
entity_pattern = $2 ? $2.strip : nil
|
307
|
+
entity_name = $3
|
308
308
|
|
309
309
|
entity_names = if entity_name
|
310
310
|
[entity_name]
|
@@ -355,7 +355,7 @@ module Flapjack
|
|
355
355
|
end
|
356
356
|
|
357
357
|
when /^(?:find )?entities matching\s+\/(.+)\//im
|
358
|
-
pattern = $1.
|
358
|
+
pattern = $1.strip
|
359
359
|
entity_list = Flapjack::Data::Entity.find_all_name_matching(pattern, :redis => @redis)
|
360
360
|
|
361
361
|
if entity_list
|
@@ -380,9 +380,9 @@ module Flapjack
|
|
380
380
|
end
|
381
381
|
|
382
382
|
when /^(?:ack )?entities\s+\/(.+)\/(?:\s*(.*?)(?:\s*duration:.*?(\w+.*))?)$/i
|
383
|
-
entity_pattern = $1.
|
384
|
-
comment = $2 ? $2.
|
385
|
-
duration_str = $3 ? $3.
|
383
|
+
entity_pattern = $1.strip
|
384
|
+
comment = $2 ? $2.strip : nil
|
385
|
+
duration_str = $3 ? $3.strip : '1 hour'
|
386
386
|
duration = ChronicDuration.parse(duration_str)
|
387
387
|
entity_list = Flapjack::Data::Entity.find_all_name_matching(entity_pattern, :redis => @redis)
|
388
388
|
|
@@ -424,7 +424,7 @@ module Flapjack
|
|
424
424
|
end
|
425
425
|
|
426
426
|
when /^(?:status )?entities\s+\/(.+)\/.*$/im
|
427
|
-
entity_pattern = $1 ? $1.
|
427
|
+
entity_pattern = $1 ? $1.strip : nil
|
428
428
|
entity_names = Flapjack::Data::Entity.find_all_name_matching(entity_pattern, :redis => @redis)
|
429
429
|
|
430
430
|
if entity_names
|
@@ -454,10 +454,10 @@ module Flapjack
|
|
454
454
|
end
|
455
455
|
|
456
456
|
when /^(?:ack )?checks\s+\/(.+)\/\s+on\s+\/(.+)\/(?:\s*(.*?)(?:\s*duration:.*?(\w+.*))?)$/i
|
457
|
-
check_pattern = $1.
|
458
|
-
entity_pattern = $2.
|
459
|
-
comment = $3 ? $3.
|
460
|
-
duration_str = $4 ? $4.
|
457
|
+
check_pattern = $1.strip
|
458
|
+
entity_pattern = $2.strip
|
459
|
+
comment = $3 ? $3.strip : nil
|
460
|
+
duration_str = $4 ? $4.strip : '1 hour'
|
461
461
|
duration = ChronicDuration.parse(duration_str)
|
462
462
|
entity_list = Flapjack::Data::Entity.find_all_name_matching(entity_pattern, :redis => @redis)
|
463
463
|
|
@@ -505,8 +505,8 @@ module Flapjack
|
|
505
505
|
end
|
506
506
|
|
507
507
|
when /^(?:status )checks\s+\/(.+?)\/(?:\s+on\s+)?(?:\/(.+)?\/)?/i
|
508
|
-
check_pattern = $1 ? $1.
|
509
|
-
entity_pattern = $2 ? $2.
|
508
|
+
check_pattern = $1 ? $1.strip : nil
|
509
|
+
entity_pattern = $2 ? $2.strip : '.*'
|
510
510
|
entity_names = Flapjack::Data::Entity.find_all_name_matching(entity_pattern, :redis => @redis)
|
511
511
|
|
512
512
|
if entity_names
|
@@ -36,8 +36,9 @@ module Flapjack
|
|
36
36
|
|
37
37
|
contact_cache = {}
|
38
38
|
|
39
|
+
known_media_identifiers = Flapjack::Data::Contact::ALL_MEDIA.reject{|m| m == 'pagerduty'}.join('|')
|
39
40
|
media_ids.split(',').uniq.collect do |m_id|
|
40
|
-
m_id =~ /\A(.+)_(
|
41
|
+
m_id =~ /\A(.+)_(#{known_media_identifiers})\z/
|
41
42
|
|
42
43
|
contact_id = $1
|
43
44
|
media_type = $2
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'em-synchrony'
|
4
|
+
require 'em-synchrony/em-http'
|
5
|
+
require 'active_support/inflector'
|
6
|
+
|
7
|
+
require 'flapjack/data/alert'
|
8
|
+
require 'flapjack/utility'
|
9
|
+
|
10
|
+
module Flapjack
|
11
|
+
module Gateways
|
12
|
+
class SmsTwilio
|
13
|
+
|
14
|
+
# curl -X POST 'https://api.twilio.com/2010-04-01/Accounts/[AccountSid]/Messages.json' \
|
15
|
+
# --data-urlencode 'To=+61414123456' \
|
16
|
+
# --data-urlencode 'From=+61414123456' \
|
17
|
+
# --data-urlencode 'Body=Sausage' \
|
18
|
+
# -u [AccountSid]:[AuthToken]
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
include Flapjack::Utility
|
23
|
+
|
24
|
+
def start
|
25
|
+
@sent = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def perform(contents)
|
29
|
+
@logger.debug "Woo, got a notification to send out: #{contents.inspect}"
|
30
|
+
alert = Flapjack::Data::Alert.new(contents, :logger => @logger)
|
31
|
+
|
32
|
+
account_sid = @config["account_sid"]
|
33
|
+
auth_token = @config["auth_token"]
|
34
|
+
from = @config["from"]
|
35
|
+
endpoint = @config["endpoint"] || "https://api.twilio.com/2010-04-01/Accounts/#{account_sid}/Messages.json"
|
36
|
+
|
37
|
+
address = alert.address
|
38
|
+
notification_id = alert.notification_id
|
39
|
+
message_type = alert.rollup ? 'rollup' : 'alert'
|
40
|
+
|
41
|
+
my_dir = File.dirname(__FILE__)
|
42
|
+
sms_template_path = case
|
43
|
+
when @config.has_key?('templates') && @config['templates']["#{message_type}.text"]
|
44
|
+
@config['templates']["#{message_type}.text"]
|
45
|
+
else
|
46
|
+
my_dir + "/sms_twilio/#{message_type}.text.erb"
|
47
|
+
end
|
48
|
+
sms_template = ERB.new(File.read(sms_template_path), nil, '-')
|
49
|
+
|
50
|
+
@alert = alert
|
51
|
+
bnd = binding
|
52
|
+
|
53
|
+
begin
|
54
|
+
message = sms_template.result(bnd).chomp
|
55
|
+
rescue => e
|
56
|
+
@logger.error "Error while excuting the ERB for an sms: " +
|
57
|
+
"ERB being executed: #{sms_template_path}"
|
58
|
+
raise
|
59
|
+
end
|
60
|
+
|
61
|
+
if @config.nil? || (@config.respond_to?(:empty?) && @config.empty?)
|
62
|
+
@logger.error "sms_twilio config is missing"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
errors = []
|
67
|
+
|
68
|
+
safe_message = truncate(message, 159)
|
69
|
+
|
70
|
+
[[account_sid, "Twilio account_sid is missing"],
|
71
|
+
[auth_token, "Twilio auth_token is missing"],
|
72
|
+
[from, "SMS from address is missing"],
|
73
|
+
[address, "SMS address is missing"],
|
74
|
+
[notification_id, "Notification id is missing"]].each do |val_err|
|
75
|
+
|
76
|
+
next unless val_err.first.nil? || (val_err.first.respond_to?(:empty?) && val_err.first.empty?)
|
77
|
+
errors << val_err.last
|
78
|
+
end
|
79
|
+
|
80
|
+
unless errors.empty?
|
81
|
+
errors.each {|err| @logger.error err }
|
82
|
+
return
|
83
|
+
end
|
84
|
+
|
85
|
+
body_data = {'To' => address,
|
86
|
+
'From' => from,
|
87
|
+
'Body' => safe_message}
|
88
|
+
@logger.debug "body_data: #{body_data.inspect}"
|
89
|
+
@logger.debug "authorization: [#{account_sid}, #{auth_token[0..2]}...#{auth_token[-3..-1]}]"
|
90
|
+
|
91
|
+
http = EM::HttpRequest.new(endpoint).post(:body => body_data, :head => {'authorization' => [account_sid, auth_token]})
|
92
|
+
|
93
|
+
@logger.debug "server response: #{http.response}"
|
94
|
+
|
95
|
+
status = (http.nil? || http.response_header.nil?) ? nil : http.response_header.status
|
96
|
+
if (status >= 200) && (status <= 206)
|
97
|
+
@sent += 1
|
98
|
+
alert.record_send_success!
|
99
|
+
@logger.debug "Sent SMS via Twilio, response status is #{status}, " +
|
100
|
+
"notification_id: #{notification_id}"
|
101
|
+
else
|
102
|
+
@logger.error "Failed to send SMS via Twilio, response status is #{status}, " +
|
103
|
+
"notification_id: #{notification_id}"
|
104
|
+
end
|
105
|
+
rescue => e
|
106
|
+
@logger.error "Error generating or delivering sms to #{contents['address']}: #{e.class}: #{e.message}"
|
107
|
+
@logger.error e.backtrace.join("\n")
|
108
|
+
raise
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<%= @alert.type_sentence_case %>: '<%= @alert.check %>' on <%= @alert.entity -%>
|
2
|
+
<% unless ['acknowledgement', 'test'].include?(@alert.notification_type) -%>
|
3
|
+
is <%= @alert.state_title_case -%>
|
4
|
+
<% end -%>
|
5
|
+
at <%= Time.at(@alert.time).strftime('%-d %b %H:%M') %>, <%= @alert.summary -%>
|
@@ -95,6 +95,8 @@ module Flapjack
|
|
95
95
|
@logger.error "logo_image_path '#{logo_image_path}'' does not point to a valid file."
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
@auto_refresh = @config['auto_refresh'].respond_to?('to_i') && @config['auto_refresh'].to_i > 0 ? @config['auto_refresh'].to_i : false
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
@@ -133,6 +135,20 @@ module Flapjack
|
|
133
135
|
@default_logo_url = self.class.instance_variable_get('@default_logo_url')
|
134
136
|
@logo_image_file = self.class.instance_variable_get('@logo_image_file')
|
135
137
|
@logo_image_ext = self.class.instance_variable_get('@logo_image_ext')
|
138
|
+
@auto_refresh = self.class.instance_variable_get('@auto_refresh')
|
139
|
+
|
140
|
+
input = nil
|
141
|
+
query_string = (request.query_string.respond_to?(:length) &&
|
142
|
+
request.query_string.length > 0) ? "?#{request.query_string}" : ""
|
143
|
+
if logger.debug?
|
144
|
+
input = env['rack.input'].read
|
145
|
+
logger.debug("#{request.request_method} #{request.path_info}#{query_string} #{input}")
|
146
|
+
elsif logger.info?
|
147
|
+
input = env['rack.input'].read
|
148
|
+
input_short = input.gsub(/\n/, '').gsub(/\s+/, ' ')
|
149
|
+
logger.info("#{request.request_method} #{request.path_info}#{query_string} #{input_short[0..80]}")
|
150
|
+
end
|
151
|
+
env['rack.input'].rewind unless input.nil?
|
136
152
|
end
|
137
153
|
|
138
154
|
get '/img/branding.*' do
|
@@ -181,8 +197,11 @@ module Flapjack
|
|
181
197
|
end
|
182
198
|
|
183
199
|
get '/self_stats' do
|
200
|
+
logger.debug "calculating self_stats"
|
184
201
|
self_stats
|
202
|
+
logger.debug "calculating entity_stats"
|
185
203
|
entity_stats
|
204
|
+
logger.debug "calculating check_stats"
|
186
205
|
check_stats
|
187
206
|
|
188
207
|
erb 'self_stats.html'.to_sym
|
@@ -464,7 +483,7 @@ module Flapjack
|
|
464
483
|
end
|
465
484
|
@event_counters = redis.hgetall('event_counters')
|
466
485
|
@events_queued = redis.llen('events')
|
467
|
-
@current_checks_ages = Flapjack::Data::EntityCheck.find_all_split_by_freshness([0, 60, 300, 900, 3600], {:redis => redis, :counts => true } )
|
486
|
+
@current_checks_ages = Flapjack::Data::EntityCheck.find_all_split_by_freshness([0, 60, 300, 900, 3600], {:redis => redis, :logger => logger, :counts => true } )
|
468
487
|
end
|
469
488
|
|
470
489
|
def entity_stats(entities = nil)
|
@@ -287,7 +287,7 @@
|
|
287
287
|
initialize: function(options) {
|
288
288
|
var context = this;
|
289
289
|
|
290
|
-
_.each(['email', 'sms', 'jabber'], function(type) {
|
290
|
+
_.each(['email', 'sms', 'sms_twilio', 'sns', 'jabber'], function(type) {
|
291
291
|
var medium = context.collection.find(function(cm) {
|
292
292
|
return cm.get('type') == type;
|
293
293
|
});
|
@@ -338,9 +338,11 @@
|
|
338
338
|
render: function() {
|
339
339
|
var template_values = _.clone(this.model.attributes);
|
340
340
|
template_values['labels'] = {
|
341
|
-
'email'
|
342
|
-
'sms'
|
343
|
-
'
|
341
|
+
'email' : 'Email',
|
342
|
+
'sms' : 'SMS (MessageNet)',
|
343
|
+
'sms_twilio' : 'SMS (Twilio)',
|
344
|
+
'sns' : 'SMS (Amazon SNS)',
|
345
|
+
'jabber' : 'Jabber'
|
344
346
|
};
|
345
347
|
this.$el.html(this.template(template_values));
|
346
348
|
return this;
|
data/lib/flapjack/notifier.rb
CHANGED
@@ -15,6 +15,7 @@ require 'flapjack/utility'
|
|
15
15
|
|
16
16
|
require 'flapjack/gateways/email'
|
17
17
|
require 'flapjack/gateways/sms_messagenet'
|
18
|
+
require 'flapjack/gateways/sms_twilio'
|
18
19
|
require 'flapjack/gateways/aws_sns'
|
19
20
|
|
20
21
|
module Flapjack
|
@@ -159,12 +160,13 @@ module Flapjack
|
|
159
160
|
contents_tags = contents['tags']
|
160
161
|
contents['tags'] = contents_tags.is_a?(Set) ? contents_tags.to_a : contents_tags
|
161
162
|
|
163
|
+
# FIXME(@auxesis): change Resque jobs to use raw blpop
|
162
164
|
case media_type.to_sym
|
163
165
|
when :sms
|
164
|
-
# FIXME(@auxesis): change Resque jobs to use raw blpop
|
165
166
|
Resque.enqueue_to(@queues['sms'], Flapjack::Gateways::SmsMessagenet, contents)
|
167
|
+
when :sms_twilio
|
168
|
+
Resque.enqueue_to(@queues['sms_twilio'], Flapjack::Gateways::SmsTwilio, contents)
|
166
169
|
when :email
|
167
|
-
# FIXME(@auxesis): change Resque jobs to use raw blpop
|
168
170
|
Resque.enqueue_to(@queues['email'], Flapjack::Gateways::Email, contents)
|
169
171
|
when :sns
|
170
172
|
Resque.enqueue_to(@queues['sns'], Flapjack::Gateways::AwsSns, contents)
|
data/lib/flapjack/pikelet.rb
CHANGED
@@ -25,6 +25,7 @@ require 'flapjack/gateways/oobetet'
|
|
25
25
|
require 'flapjack/gateways/pagerduty'
|
26
26
|
require 'flapjack/gateways/email'
|
27
27
|
require 'flapjack/gateways/sms_messagenet'
|
28
|
+
require 'flapjack/gateways/sms_twilio'
|
28
29
|
require 'flapjack/gateways/aws_sns'
|
29
30
|
require 'flapjack/gateways/web'
|
30
31
|
require 'flapjack/logger'
|
@@ -156,9 +157,10 @@ module Flapjack
|
|
156
157
|
|
157
158
|
class Resque < Flapjack::Pikelet::Base
|
158
159
|
|
159
|
-
PIKELET_TYPES = {'email'
|
160
|
-
'sms'
|
161
|
-
'
|
160
|
+
PIKELET_TYPES = {'email' => Flapjack::Gateways::Email,
|
161
|
+
'sms' => Flapjack::Gateways::SmsMessagenet,
|
162
|
+
'sms_twilio' => Flapjack::Gateways::SmsTwilio,
|
163
|
+
'sns' => Flapjack::Gateways::AwsSns}
|
162
164
|
|
163
165
|
def self.create(type, opts = {})
|
164
166
|
self.new(type, PIKELET_TYPES[type], :config => opts[:config],
|
data/lib/flapjack/version.rb
CHANGED
@@ -27,8 +27,8 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
27
27
|
:tags => Flapjack::Data::TagSet.new([]),
|
28
28
|
:time_restrictions => [],
|
29
29
|
:unknown_media => [],
|
30
|
-
:warning_media => ['email', 'sms', 'jabber', 'pagerduty', 'sns'],
|
31
|
-
:critical_media => ['email', 'sms', 'jabber', 'pagerduty', 'sns'],
|
30
|
+
:warning_media => ['email', 'sms', 'sms_twilio', 'jabber', 'pagerduty', 'sns'],
|
31
|
+
:critical_media => ['email', 'sms', 'sms_twilio', 'jabber', 'pagerduty', 'sns'],
|
32
32
|
:unknown_blackhole => false,
|
33
33
|
:warning_blackhole => false,
|
34
34
|
:critical_blackhole => false}
|
@@ -272,7 +272,6 @@ describe Flapjack::Data::EntityCheck, :redis => true do
|
|
272
272
|
expect(duration).to eq(half_an_hour)
|
273
273
|
end
|
274
274
|
|
275
|
-
# TODO this should probably enforce that it starts in the future
|
276
275
|
it "creates a scheduled maintenance period covering the current time" do
|
277
276
|
t = Time.now.to_i
|
278
277
|
ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
|
@@ -294,6 +293,11 @@ describe Flapjack::Data::EntityCheck, :redis => true do
|
|
294
293
|
expect(duration).not_to be_nil
|
295
294
|
expect(duration).to be_a(Float)
|
296
295
|
expect(duration).to eq(2 * (60 * 60))
|
296
|
+
|
297
|
+
ttl = @redis.ttl("#{name}:#{check}:scheduled_maintenance")
|
298
|
+
expect(ttl).to be_within(20).of(60 * 60) # 20-second margin of error,
|
299
|
+
# should be large enough for a slow machine running the test -- duration
|
300
|
+
# is considered to start at the begininng of the period
|
297
301
|
end
|
298
302
|
|
299
303
|
it "creates an scheduled maintenance period from a human readable time" do
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flapjack/gateways/sms_twilio'
|
3
|
+
|
4
|
+
describe Flapjack::Gateways::SmsTwilio, :logger => true do
|
5
|
+
|
6
|
+
let(:lock) { double(Monitor) }
|
7
|
+
|
8
|
+
let(:config) { {'account_sid' => 'the_account_sid',
|
9
|
+
'auth_token' => 'the_auth_token',
|
10
|
+
'from' => 'the_from_address'
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
let(:time) { Time.new(2013, 10, 31, 13, 45) }
|
15
|
+
|
16
|
+
let(:time_str) { Time.at(time).strftime('%-d %b %H:%M') }
|
17
|
+
|
18
|
+
let(:message) { {'notification_type' => 'recovery',
|
19
|
+
'contact_first_name' => 'John',
|
20
|
+
'contact_last_name' => 'Smith',
|
21
|
+
'state' => 'ok',
|
22
|
+
'summary' => 'smile',
|
23
|
+
'last_state' => 'problem',
|
24
|
+
'last_summary' => 'frown',
|
25
|
+
'time' => time.to_i,
|
26
|
+
'address' => '555-555555',
|
27
|
+
'event_id' => 'example.com:ping',
|
28
|
+
'id' => '123456789',
|
29
|
+
'duration' => 55,
|
30
|
+
'state_duration' => 23
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
it "sends an SMS message" do
|
35
|
+
req = stub_request(:post, "https://api.twilio.com/2010-04-01/Accounts/the_account_sid/Messages.json").
|
36
|
+
to_return(:status => 201)
|
37
|
+
|
38
|
+
EM.synchrony do
|
39
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@config', config)
|
40
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@logger', @logger)
|
41
|
+
Flapjack::Gateways::SmsTwilio.start
|
42
|
+
Flapjack::Gateways::SmsTwilio.perform(message)
|
43
|
+
EM.stop
|
44
|
+
end
|
45
|
+
expect(req).to have_been_requested
|
46
|
+
end
|
47
|
+
|
48
|
+
it "truncates a long message a" do
|
49
|
+
long_msg = message.merge('summary' => 'Four score and seven years ago our ' +
|
50
|
+
'fathers brought forth on this continent, a new nation, conceived in ' +
|
51
|
+
'Liberty, and dedicated to the proposition that all men are created equal.')
|
52
|
+
|
53
|
+
body = {
|
54
|
+
'To' => '555-555555',
|
55
|
+
'From' => 'the_from_address',
|
56
|
+
'Body' => "Recovery: 'ping' on example.com is " +
|
57
|
+
"OK at #{time_str}, Four score and seven years ago " +
|
58
|
+
'our fathers brought forth on this continent, a new ' +
|
59
|
+
'nation, conceived i...'}
|
60
|
+
req = stub_request(:post, "https://api.twilio.com/2010-04-01/Accounts/the_account_sid/Messages.json").
|
61
|
+
with(:body => body).
|
62
|
+
with(:headers => {'Authorization'=>['the_account_sid', 'the_auth_token']}).
|
63
|
+
to_return(:status => 200)
|
64
|
+
|
65
|
+
EM.synchrony do
|
66
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@config', config)
|
67
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@logger', @logger)
|
68
|
+
Flapjack::Gateways::SmsTwilio.start
|
69
|
+
Flapjack::Gateways::SmsTwilio.perform(long_msg)
|
70
|
+
EM.stop
|
71
|
+
end
|
72
|
+
expect(req).to have_been_requested
|
73
|
+
end
|
74
|
+
|
75
|
+
it "does not send an SMS message with an invalid config" do
|
76
|
+
EM.synchrony do
|
77
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@config', config.reject {|k, v| k == 'auth_token'})
|
78
|
+
Flapjack::Gateways::SmsTwilio.instance_variable_set('@logger', @logger)
|
79
|
+
Flapjack::Gateways::SmsTwilio.start
|
80
|
+
Flapjack::Gateways::SmsTwilio.perform(message)
|
81
|
+
EM.stop
|
82
|
+
end
|
83
|
+
|
84
|
+
expect(WebMock).not_to have_requested(:post,
|
85
|
+
"https://api.twilio.com/2010-04-01/Accounts/the_account_sid/Messages.json")
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flapjack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lindsay Holmwood
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-
|
14
|
+
date: 2014-09-10 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: dante
|
@@ -396,6 +396,7 @@ files:
|
|
396
396
|
- features/cli_flapjack-nagios-receiver.feature
|
397
397
|
- features/cli_flapjack-populator.feature
|
398
398
|
- features/cli_flapper.feature
|
399
|
+
- features/cli_purge.feature
|
399
400
|
- features/cli_receive-events.feature
|
400
401
|
- features/cli_simulate-failed-check.feature
|
401
402
|
- features/events.feature
|
@@ -418,6 +419,7 @@ files:
|
|
418
419
|
- lib/flapjack/cli/flapper.rb
|
419
420
|
- lib/flapjack/cli/import.rb
|
420
421
|
- lib/flapjack/cli/maintenance.rb
|
422
|
+
- lib/flapjack/cli/purge.rb
|
421
423
|
- lib/flapjack/cli/receiver.rb
|
422
424
|
- lib/flapjack/cli/server.rb
|
423
425
|
- lib/flapjack/cli/simulate.rb
|
@@ -470,6 +472,9 @@ files:
|
|
470
472
|
- lib/flapjack/gateways/sms_messagenet.rb
|
471
473
|
- lib/flapjack/gateways/sms_messagenet/alert.text.erb
|
472
474
|
- lib/flapjack/gateways/sms_messagenet/rollup.text.erb
|
475
|
+
- lib/flapjack/gateways/sms_twilio.rb
|
476
|
+
- lib/flapjack/gateways/sms_twilio/alert.text.erb
|
477
|
+
- lib/flapjack/gateways/sms_twilio/rollup.text.erb
|
473
478
|
- lib/flapjack/gateways/web.rb
|
474
479
|
- lib/flapjack/gateways/web/public/css/bootstrap.css
|
475
480
|
- lib/flapjack/gateways/web/public/css/font-awesome.css
|
@@ -569,6 +574,7 @@ files:
|
|
569
574
|
- spec/lib/flapjack/gateways/oobetet_spec.rb
|
570
575
|
- spec/lib/flapjack/gateways/pagerduty_spec.rb
|
571
576
|
- spec/lib/flapjack/gateways/sms_messagenet_spec.rb
|
577
|
+
- spec/lib/flapjack/gateways/sms_twilio_spec.rb
|
572
578
|
- spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb
|
573
579
|
- spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb
|
574
580
|
- spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb
|
@@ -640,6 +646,7 @@ test_files:
|
|
640
646
|
- features/cli_flapjack-nagios-receiver.feature
|
641
647
|
- features/cli_flapjack-populator.feature
|
642
648
|
- features/cli_flapper.feature
|
649
|
+
- features/cli_purge.feature
|
643
650
|
- features/cli_receive-events.feature
|
644
651
|
- features/cli_simulate-failed-check.feature
|
645
652
|
- features/events.feature
|
@@ -687,6 +694,7 @@ test_files:
|
|
687
694
|
- spec/lib/flapjack/gateways/oobetet_spec.rb
|
688
695
|
- spec/lib/flapjack/gateways/pagerduty_spec.rb
|
689
696
|
- spec/lib/flapjack/gateways/sms_messagenet_spec.rb
|
697
|
+
- spec/lib/flapjack/gateways/sms_twilio_spec.rb
|
690
698
|
- spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb
|
691
699
|
- spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb
|
692
700
|
- spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb
|