flapjack 0.6.43 → 0.6.44
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/flapjack +4 -2
- data/bin/flapjack-nagios-receiver +4 -1
- data/bin/flapjack-populator +4 -1
- data/etc/flapjack_config.yaml.example +111 -106
- data/features/steps/notifications_steps.rb +6 -6
- data/lib/flapjack/configuration.rb +76 -24
- data/lib/flapjack/coordinator.rb +27 -44
- data/lib/flapjack/data/entity.rb +28 -7
- data/lib/flapjack/data/entity_check.rb +18 -20
- data/lib/flapjack/executive.rb +5 -4
- data/lib/flapjack/gateways/api.rb +391 -0
- data/lib/flapjack/gateways/api/entity_check_presenter.rb +185 -0
- data/lib/flapjack/gateways/api/entity_presenter.rb +70 -0
- data/lib/flapjack/gateways/base.rb +38 -0
- data/lib/flapjack/{notification → gateways}/email.rb +4 -5
- data/lib/flapjack/{notification → gateways}/email/alert.html.haml +0 -0
- data/lib/flapjack/{notification → gateways}/email/alert.text.erb +0 -0
- data/lib/flapjack/gateways/jabber.rb +387 -0
- data/lib/flapjack/gateways/oobetet.rb +241 -0
- data/lib/flapjack/gateways/pagerduty.rb +247 -0
- data/lib/flapjack/{notification → gateways}/sms.rb +5 -6
- data/lib/flapjack/{notification → gateways}/sms/messagenet.rb +1 -1
- data/lib/flapjack/gateways/web.rb +293 -0
- data/lib/flapjack/{web → gateways/web}/views/_css.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/_nav.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/check.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/contact.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/contacts.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/index.haml +0 -0
- data/lib/flapjack/{web → gateways/web}/views/self_stats.haml +0 -0
- data/lib/flapjack/pikelet.rb +0 -23
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +56 -36
- data/spec/lib/flapjack/data/entity_spec.rb +53 -4
- data/spec/lib/flapjack/{api → gateways/api}/entity_check_presenter_spec.rb +10 -13
- data/spec/lib/flapjack/{api → gateways/api}/entity_presenter_spec.rb +10 -10
- data/spec/lib/flapjack/{api_spec.rb → gateways/api_spec.rb} +14 -14
- data/spec/lib/flapjack/gateways/email_spec.rb +6 -0
- data/spec/lib/flapjack/{jabber_spec.rb → gateways/jabber_spec.rb} +9 -9
- data/spec/lib/flapjack/{oobetet_spec.rb → gateways/oobetet_spec.rb} +10 -10
- data/spec/lib/flapjack/{pagerduty_spec.rb → gateways/pagerduty_spec.rb} +11 -11
- data/spec/lib/flapjack/gateways/sms_spec.rb +6 -0
- data/spec/lib/flapjack/{web_spec.rb → gateways/web_spec.rb} +4 -4
- metadata +46 -79
- data/bin/install-flapjack-systemwide +0 -58
- data/features/steps/flapjack-importer_steps.rb +0 -109
- data/features/steps/flapjack-worker_steps.rb +0 -68
- data/lib/flapjack/api.rb +0 -388
- data/lib/flapjack/api/entity_check_presenter.rb +0 -181
- data/lib/flapjack/api/entity_presenter.rb +0 -66
- data/lib/flapjack/cli/worker_manager.rb +0 -46
- data/lib/flapjack/inifile.rb +0 -44
- data/lib/flapjack/jabber.rb +0 -383
- data/lib/flapjack/notifier_engine.rb +0 -40
- data/lib/flapjack/notifiers/mailer/init.rb +0 -3
- data/lib/flapjack/notifiers/mailer/mailer.rb +0 -51
- data/lib/flapjack/notifiers/xmpp/init.rb +0 -3
- data/lib/flapjack/notifiers/xmpp/xmpp.rb +0 -46
- data/lib/flapjack/oobetet.rb +0 -240
- data/lib/flapjack/pagerduty.rb +0 -242
- data/lib/flapjack/web.rb +0 -286
- data/spec.old/check_sandbox/echo +0 -3
- data/spec.old/check_sandbox/sandboxed_check +0 -5
- data/spec.old/configs/flapjack-notifier-couchdb.ini +0 -25
- data/spec.old/configs/flapjack-notifier.ini +0 -39
- data/spec.old/configs/recipients.ini +0 -14
- data/spec.old/helpers.rb +0 -15
- data/spec.old/inifile_spec.rb +0 -66
- data/spec.old/mock-notifiers/mock/init.rb +0 -3
- data/spec.old/mock-notifiers/mock/mock.rb +0 -19
- data/spec.old/notifier-directories/spoons/testmailer/init.rb +0 -20
- data/spec.old/notifier_application_spec.rb +0 -222
- data/spec.old/notifier_filters_spec.rb +0 -52
- data/spec.old/notifier_options_multiplexer_spec.rb +0 -71
- data/spec.old/notifier_options_spec.rb +0 -115
- data/spec.old/notifier_spec.rb +0 -57
- data/spec.old/notifiers/mailer_spec.rb +0 -36
- data/spec.old/notifiers/xmpp_spec.rb +0 -36
- data/spec.old/persistence/datamapper_spec.rb +0 -74
- data/spec.old/persistence/mock_persistence_backend.rb +0 -26
- data/spec.old/simple.ini +0 -6
- data/spec.old/spec.opts +0 -4
- data/spec.old/test-filters/blocker.rb +0 -13
- data/spec.old/test-filters/mock.rb +0 -13
- data/spec.old/transports/beanstalkd_spec.rb +0 -44
- data/spec.old/transports/mock_transport.rb +0 -58
- data/spec.old/worker_application_spec.rb +0 -62
- data/spec.old/worker_options_spec.rb +0 -83
- data/spec/lib/flapjack/notification/email_spec.rb +0 -6
- data/spec/lib/flapjack/notification/sms_spec.rb +0 -6
@@ -0,0 +1,241 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'eventmachine'
|
5
|
+
require 'em-synchrony'
|
6
|
+
require 'blather/client/client'
|
7
|
+
require 'em-synchrony/fiber_iterator'
|
8
|
+
require 'yajl/json_gem'
|
9
|
+
|
10
|
+
require 'flapjack/utility'
|
11
|
+
require 'flapjack/gateways/base'
|
12
|
+
|
13
|
+
module Flapjack
|
14
|
+
|
15
|
+
module Gateways
|
16
|
+
|
17
|
+
class Oobetet < Blather::Client
|
18
|
+
|
19
|
+
include Flapjack::Gateways::Generic
|
20
|
+
include Flapjack::Utility
|
21
|
+
|
22
|
+
log = Logger.new(STDOUT)
|
23
|
+
# log.level = Logger::DEBUG
|
24
|
+
log.level = Logger::INFO
|
25
|
+
Blather.logger = log
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@hostname = Socket.gethostname
|
29
|
+
@flapjacktest_jid = Blather::JID.new((@config['jabberid'] || 'flapjacktest') + "/#{@hostname}:#{Process.pid}")
|
30
|
+
|
31
|
+
super(@flapjacktest_jid, @config['password'], @config['server'], @config['port'].to_i)
|
32
|
+
|
33
|
+
logger.debug("Building jabber connection with jabberid: " +
|
34
|
+
@flapjacktest_jid.to_s + ", port: " + @config['port'].to_s +
|
35
|
+
", server: " + @config['server'].to_s + ", password: " +
|
36
|
+
@config['password'].to_s)
|
37
|
+
|
38
|
+
@pagerduty_events_api_url = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
|
39
|
+
|
40
|
+
if !@config['watched_check'] or !@config['watched_entity']
|
41
|
+
raise RuntimeError, 'Flapjack::Oobetet: watched_check and watched_entity must be defined in the config'
|
42
|
+
end
|
43
|
+
|
44
|
+
@check_matcher = '"' + @config['watched_check'] + '" on ' + @config['watched_entity']
|
45
|
+
@max_latency = @config['max_latency'] || 300
|
46
|
+
@flapjack_ok = true
|
47
|
+
|
48
|
+
t = Time.now.to_i
|
49
|
+
@times = { :last_problem => t,
|
50
|
+
:last_recovery => t,
|
51
|
+
:last_ack => t,
|
52
|
+
:last_ack_sent => t }
|
53
|
+
|
54
|
+
@last_alert = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# split out to ease testing
|
58
|
+
def register_handlers
|
59
|
+
register_handler :ready do |stanza|
|
60
|
+
EventMachine::Synchrony.next_tick do
|
61
|
+
on_ready(stanza)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
register_handler :message, :groupchat? do |stanza|
|
66
|
+
EventMachine::Synchrony.next_tick do
|
67
|
+
on_groupchat(stanza)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
register_handler :disconnected do |stanza|
|
72
|
+
ret = true
|
73
|
+
EventMachine::Synchrony.next_tick do
|
74
|
+
ret = on_disconnect(stanza)
|
75
|
+
end
|
76
|
+
ret
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Join the MUC Chat room after connecting.
|
82
|
+
def on_ready(stanza)
|
83
|
+
return if should_quit?
|
84
|
+
@connected_at = Time.now.to_i
|
85
|
+
logger.info("Jabber Connected")
|
86
|
+
if @config['rooms'] && @config['rooms'].length > 0
|
87
|
+
@config['rooms'].each do |room|
|
88
|
+
logger.info("Joining room #{room}")
|
89
|
+
presence = Blather::Stanza::Presence.new
|
90
|
+
presence.from = @flapjacktest_jid
|
91
|
+
presence.to = Blather::JID.new("#{room}/#{@config['alias']}")
|
92
|
+
presence << "<x xmlns='http://jabber.org/protocol/muc'/>"
|
93
|
+
write presence
|
94
|
+
say(room, "flapjack self monitoring (oobetet) started at #{Time.now}, g'day!", :groupchat)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# returning true to prevent the reactor loop from stopping
|
100
|
+
def on_disconnect(stanza)
|
101
|
+
return true if should_quit?
|
102
|
+
logger.warn("jabbers disconnected! reconnecting in 1 second ...")
|
103
|
+
EventMachine::Timer.new(1) do
|
104
|
+
connect # Blather::Client.connect
|
105
|
+
end
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
def on_groupchat(stanza)
|
110
|
+
return if should_quit?
|
111
|
+
|
112
|
+
stanza_body = stanza.body
|
113
|
+
|
114
|
+
logger.debug("groupchat stanza body: " + stanza_body)
|
115
|
+
logger.debug("groupchat message received: #{stanza.inspect}")
|
116
|
+
|
117
|
+
if (stanza_body =~ /^(?:problem|recovery|acknowledgement)/i) &&
|
118
|
+
(stanza_body =~ /^(\w+).*#{Regexp.escape(@check_matcher)}/)
|
119
|
+
|
120
|
+
# got something interesting
|
121
|
+
status = $1.downcase
|
122
|
+
t = Time.now.to_i
|
123
|
+
logger.debug("groupchat found the following state for #{@check_matcher}: #{status}")
|
124
|
+
|
125
|
+
case status
|
126
|
+
when 'problem'
|
127
|
+
logger.debug("updating @times last_problem")
|
128
|
+
@times[:last_problem] = t
|
129
|
+
when 'recovery'
|
130
|
+
logger.debug("updating @times last_recovery")
|
131
|
+
@times[:last_recovery] = t
|
132
|
+
when 'acknowledgement'
|
133
|
+
logger.debug("updating @times last_ack")
|
134
|
+
@times[:last_ack] = t
|
135
|
+
end
|
136
|
+
end
|
137
|
+
logger.debug("@times: #{@times.inspect}")
|
138
|
+
end
|
139
|
+
|
140
|
+
def check_timers
|
141
|
+
t = Time.now.to_i
|
142
|
+
breach = nil
|
143
|
+
@logger.debug("check_timers: inspecting @times #{@times.inspect}")
|
144
|
+
case
|
145
|
+
when @times[:last_problem] < (t - @max_latency)
|
146
|
+
breach = "haven't seen a test problem notification in the last #{@max_latency} seconds"
|
147
|
+
when @times[:last_recovery] < (t - @max_latency)
|
148
|
+
breach = "haven't seen a test recovery notification in the last #{@max_latency} seconds"
|
149
|
+
end
|
150
|
+
|
151
|
+
unless @flapjack_ok || breach
|
152
|
+
emit_jabber("Flapjack Self Monitoring is OK")
|
153
|
+
emit_pagerduty("Flapjack Self Monitoring is OK", 'resolve')
|
154
|
+
end
|
155
|
+
|
156
|
+
@flapjack_ok = !breach
|
157
|
+
|
158
|
+
return unless breach
|
159
|
+
@logger.error("Self monitoring has detected the following breach: #{breach}")
|
160
|
+
summary = "Flapjack Self Monitoring is Critical: #{breach} for #{@check_matcher}, "
|
161
|
+
summary += "from #{@hostname} at #{Time.now}"
|
162
|
+
|
163
|
+
if !@last_alert or @last_alert < (t - 55)
|
164
|
+
|
165
|
+
emit_jabber(summary)
|
166
|
+
emit_pagerduty(summary, 'trigger')
|
167
|
+
|
168
|
+
if !@last_alert or @last_alert < (t - 55)
|
169
|
+
msg = "NOTICE: Self monitoring has detected a failure and is unable to tell "
|
170
|
+
msg += "anyone about it. DON'T PANIC."
|
171
|
+
@logger.error msg
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def emit_jabber(summary)
|
178
|
+
if @config['rooms'] && @config['rooms'].length > 0
|
179
|
+
@config['rooms'].each do |room|
|
180
|
+
say(room, summary, :groupchat)
|
181
|
+
end
|
182
|
+
@last_alert = Time.now.to_i
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def emit_pagerduty(summary, event_type = 'trigger')
|
187
|
+
if @config['pagerduty_contact']
|
188
|
+
pagerduty_event = { :service_key => @config['pagerduty_contact'],
|
189
|
+
:incident_key => "Flapjack Self Monitoring from #{@hostname}",
|
190
|
+
:event_type => event_type,
|
191
|
+
:description => summary }
|
192
|
+
status, response = send_pagerduty_event(pagerduty_event)
|
193
|
+
if status == 200
|
194
|
+
@logger.debug("successfully sent pagerduty event")
|
195
|
+
@last_alert = Time.now.to_i
|
196
|
+
else
|
197
|
+
@logger.error("pagerduty returned #{status} #{response.inspect}")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def say(to, msg, using = :chat)
|
203
|
+
@logger.debug("Sending a jabber message to: #{to.to_s}, using: #{using.to_s}, message: #{msg}")
|
204
|
+
write Blather::Stanza::Message.new(to, msg, using)
|
205
|
+
end
|
206
|
+
|
207
|
+
def send_pagerduty_event(event)
|
208
|
+
options = { :body => Yajl::Encoder.encode(event) }
|
209
|
+
http = EM::HttpRequest.new(@pagerduty_events_api_url).post(options)
|
210
|
+
response = Yajl::Parser.parse(http.response)
|
211
|
+
status = http.response_header.status
|
212
|
+
logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}"
|
213
|
+
[status, response]
|
214
|
+
end
|
215
|
+
|
216
|
+
def main
|
217
|
+
logger.debug("New oobetet pikelet with the following options: #{@config.inspect}")
|
218
|
+
|
219
|
+
keepalive_timer = EM::Synchrony.add_periodic_timer(60) do
|
220
|
+
logger.debug("calling keepalive on the jabber connection")
|
221
|
+
write(' ') if connected?
|
222
|
+
end
|
223
|
+
|
224
|
+
setup
|
225
|
+
register_handlers
|
226
|
+
connect # Blather::Client.connect
|
227
|
+
|
228
|
+
until should_quit?
|
229
|
+
EM::Synchrony.sleep(10)
|
230
|
+
check_timers
|
231
|
+
end
|
232
|
+
|
233
|
+
keepalive_timer.cancel
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
|
@@ -0,0 +1,247 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'em-synchrony'
|
4
|
+
require 'em-synchrony/em-http'
|
5
|
+
|
6
|
+
require 'yajl/json_gem'
|
7
|
+
|
8
|
+
require 'flapjack/data/entity_check'
|
9
|
+
require 'flapjack/data/global'
|
10
|
+
require 'flapjack/redis_pool'
|
11
|
+
|
12
|
+
require 'flapjack/gateways/base'
|
13
|
+
|
14
|
+
module Flapjack
|
15
|
+
|
16
|
+
module Gateways
|
17
|
+
|
18
|
+
class Pagerduty
|
19
|
+
include Flapjack::Gateways::Generic
|
20
|
+
|
21
|
+
PAGERDUTY_EVENTS_API_URL = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
|
22
|
+
SEM_PAGERDUTY_ACKS_RUNNING = 'sem_pagerduty_acks_running'
|
23
|
+
|
24
|
+
alias_method :generic_bootstrap, :bootstrap
|
25
|
+
alias_method :generic_cleanup, :cleanup
|
26
|
+
|
27
|
+
def bootstrap(opts = {})
|
28
|
+
generic_bootstrap(opts)
|
29
|
+
|
30
|
+
@redis_config = opts[:redis_config]
|
31
|
+
@redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1)
|
32
|
+
|
33
|
+
logger.debug("New Pagerduty pikelet with the following options: #{@config.inspect}")
|
34
|
+
|
35
|
+
@pagerduty_acks_started = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def cleanup
|
39
|
+
@redis.empty! if @redis
|
40
|
+
@redis_timer.empty! if @redis_timer
|
41
|
+
generic_cleanup
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_shutdown_event(opts = {})
|
45
|
+
return unless redis = opts[:redis]
|
46
|
+
redis.rpush(@config['queue'], JSON.generate('notification_type' => 'shutdown'))
|
47
|
+
end
|
48
|
+
|
49
|
+
def main
|
50
|
+
logger.debug("pagerduty gateway - commencing main method")
|
51
|
+
raise "Can't connect to the pagerduty API" unless test_pagerduty_connection
|
52
|
+
|
53
|
+
# TODO: only clear this if there isn't another pagerduty gateway instance running
|
54
|
+
# or better, include an instance ID in the semaphore key name
|
55
|
+
@redis.del(SEM_PAGERDUTY_ACKS_RUNNING)
|
56
|
+
|
57
|
+
acknowledgement_timer = EM::Synchrony.add_periodic_timer(10) do
|
58
|
+
@redis_timer ||= Flapjack::RedisPool.new(:config => @redis_config, :size => 1)
|
59
|
+
find_pagerduty_acknowledgements_if_safe
|
60
|
+
end
|
61
|
+
|
62
|
+
queue = @config['queue']
|
63
|
+
events = {}
|
64
|
+
|
65
|
+
until should_quit?
|
66
|
+
logger.debug("pagerduty gateway is going into blpop mode on #{queue}")
|
67
|
+
events[queue] = @redis.blpop(queue, 0)
|
68
|
+
event = Yajl::Parser.parse(events[queue][1])
|
69
|
+
type = event['notification_type']
|
70
|
+
logger.debug("pagerduty notification event popped off the queue: " + event.inspect)
|
71
|
+
unless 'shutdown'.eql?(type)
|
72
|
+
event_id = event['event_id']
|
73
|
+
entity, check = event_id.split(':')
|
74
|
+
state = event['state']
|
75
|
+
summary = event['summary']
|
76
|
+
address = event['address']
|
77
|
+
|
78
|
+
headline = type.upcase
|
79
|
+
|
80
|
+
case type.downcase
|
81
|
+
when 'acknowledgement'
|
82
|
+
maint_str = "has been acknowledged"
|
83
|
+
pagerduty_type = 'acknowledge'
|
84
|
+
when 'problem'
|
85
|
+
maint_str = "is #{state.upcase}"
|
86
|
+
pagerduty_type = "trigger"
|
87
|
+
when 'recovery'
|
88
|
+
maint_str = "is #{state.upcase}"
|
89
|
+
pagerduty_type = "resolve"
|
90
|
+
when 'test'
|
91
|
+
maint_str = ""
|
92
|
+
pagerduty_type = "trigger"
|
93
|
+
headline = "TEST NOTIFICATION"
|
94
|
+
end
|
95
|
+
|
96
|
+
message = "#{type.upcase} - \"#{check}\" on #{entity} #{maint_str} - #{summary}"
|
97
|
+
|
98
|
+
pagerduty_event = { :service_key => address,
|
99
|
+
:incident_key => event_id,
|
100
|
+
:event_type => pagerduty_type,
|
101
|
+
:description => message }
|
102
|
+
|
103
|
+
send_pagerduty_event(pagerduty_event)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
acknowledgement_timer.cancel
|
108
|
+
end
|
109
|
+
|
110
|
+
# considering this as part of the public API -- exposes it for testing.
|
111
|
+
def find_pagerduty_acknowledgements_if_safe
|
112
|
+
|
113
|
+
# ensure we're the only instance of the pagerduty acknowledgement check running (with a naive
|
114
|
+
# timeout of five minutes to guard against stale locks caused by crashing code) either in this
|
115
|
+
# process or in other processes
|
116
|
+
if (@pagerduty_acks_started and @pagerduty_acks_started > (Time.now.to_i - 300)) or
|
117
|
+
@redis_timer.get(SEM_PAGERDUTY_ACKS_RUNNING) == 'true'
|
118
|
+
logger.debug("skipping looking for acks in pagerduty as this is already happening")
|
119
|
+
return
|
120
|
+
end
|
121
|
+
|
122
|
+
@pagerduty_acks_started = Time.now.to_i
|
123
|
+
@redis_timer.set(SEM_PAGERDUTY_ACKS_RUNNING, 'true')
|
124
|
+
@redis_timer.expire(SEM_PAGERDUTY_ACKS_RUNNING, 300)
|
125
|
+
|
126
|
+
find_pagerduty_acknowledgements
|
127
|
+
|
128
|
+
@redis_timer.del(SEM_PAGERDUTY_ACKS_RUNNING)
|
129
|
+
@pagerduty_acks_started = nil
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def test_pagerduty_connection
|
135
|
+
noop = { "service_key" => "11111111111111111111111111111111",
|
136
|
+
"incident_key" => "Flapjack is running a NOOP",
|
137
|
+
"event_type" => "nop",
|
138
|
+
"description" => "I love APIs with noops." }
|
139
|
+
code, results = send_pagerduty_event(noop)
|
140
|
+
return true if code == 200 && results['status'] =~ /success/i
|
141
|
+
logger.error "Error: test_pagerduty_connection: API returned #{code.to_s} #{results.inspect}"
|
142
|
+
false
|
143
|
+
end
|
144
|
+
|
145
|
+
def send_pagerduty_event(event)
|
146
|
+
options = { :body => Yajl::Encoder.encode(event) }
|
147
|
+
http = EM::HttpRequest.new(PAGERDUTY_EVENTS_API_URL).post(options)
|
148
|
+
response = Yajl::Parser.parse(http.response)
|
149
|
+
status = http.response_header.status
|
150
|
+
logger.debug "send_pagerduty_event got a return code of #{status.to_s} - #{response.inspect}"
|
151
|
+
[status, response]
|
152
|
+
end
|
153
|
+
|
154
|
+
def find_pagerduty_acknowledgements
|
155
|
+
|
156
|
+
logger.debug("looking for acks in pagerduty for unack'd problems")
|
157
|
+
|
158
|
+
unacknowledged_failing_checks = Flapjack::Data::Global.unacknowledged_failing_checks(:redis => @redis_timer)
|
159
|
+
|
160
|
+
@logger.debug "found unacknowledged failing checks as follows: " + unacknowledged_failing_checks.join(', ')
|
161
|
+
|
162
|
+
unacknowledged_failing_checks.each do |entity_check|
|
163
|
+
pagerduty_credentials = entity_check.pagerduty_credentials(:redis => @redis_timer)
|
164
|
+
check = entity_check.check
|
165
|
+
|
166
|
+
if pagerduty_credentials.empty?
|
167
|
+
@logger.debug("No pagerduty credentials found for #{entity_check.entity_name}:#{check}, skipping")
|
168
|
+
next
|
169
|
+
end
|
170
|
+
|
171
|
+
# FIXME: try each set of credentials until one works (may have stale contacts turning up)
|
172
|
+
options = pagerduty_credentials.first.merge('check' => check)
|
173
|
+
|
174
|
+
acknowledged = pagerduty_acknowledged?(options)
|
175
|
+
if acknowledged.nil?
|
176
|
+
@logger.debug "#{check} is not acknowledged in pagerduty, skipping"
|
177
|
+
next
|
178
|
+
end
|
179
|
+
|
180
|
+
pg_acknowledged_by = acknowledged[:pg_acknowledged_by]
|
181
|
+
@logger.debug "#{check} is acknowledged in pagerduty, creating flapjack acknowledgement... "
|
182
|
+
who_text = ""
|
183
|
+
if !pg_acknowledged_by.nil? && !pg_acknowledged_by['name'].nil?
|
184
|
+
who_text = " by #{pg_acknowledged_by['name']}"
|
185
|
+
end
|
186
|
+
entity_check.create_acknowledgement('summary' => "Acknowledged on PagerDuty" + who_text)
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
def pagerduty_acknowledged?(opts)
|
192
|
+
subdomain = opts['subdomain']
|
193
|
+
username = opts['username']
|
194
|
+
password = opts['password']
|
195
|
+
check = opts['check']
|
196
|
+
|
197
|
+
t = Time.now.utc
|
198
|
+
|
199
|
+
url = 'https://' + subdomain + '.pagerduty.com/api/v1/incidents'
|
200
|
+
query = { 'fields' => 'incident_number,status,last_status_change_by',
|
201
|
+
'since' => (t - (60*60*24*7)).iso8601, # the last week
|
202
|
+
'until' => (t + (60*60*24)).iso8601, # 1 day in the future
|
203
|
+
'incident_key' => check,
|
204
|
+
'status' => 'acknowledged' }
|
205
|
+
|
206
|
+
options = { :head => { 'authorization' => [username, password] },
|
207
|
+
:query => query }
|
208
|
+
|
209
|
+
http = EM::HttpRequest.new(url).get(options)
|
210
|
+
# DEBUG flapjack-pagerduty: pagerduty_acknowledged?: decoded response as:
|
211
|
+
# {"incidents"=>[{"incident_number"=>40, "status"=>"acknowledged",
|
212
|
+
# "last_status_change_by"=>{"id"=>"PO1NWPS", "name"=>"Jesse Reynolds",
|
213
|
+
# "email"=>"jesse@bulletproof.net",
|
214
|
+
# "html_url"=>"http://bltprf.pagerduty.com/users/PO1NWPS"}}], "limit"=>100, "offset"=>0,
|
215
|
+
# "total"=>1}
|
216
|
+
begin
|
217
|
+
response = Yajl::Parser.parse(http.response)
|
218
|
+
rescue Yajl::ParseError
|
219
|
+
@logger.error("failed to parse json from a post to #{url} ... response headers and body follows...")
|
220
|
+
@logger.error(http.response_header.inspect)
|
221
|
+
@logger.error(http.response)
|
222
|
+
return nil
|
223
|
+
end
|
224
|
+
status = http.response_header.status
|
225
|
+
|
226
|
+
@logger.debug("pagerduty_acknowledged?: decoded response as: #{response.inspect}")
|
227
|
+
if response.nil?
|
228
|
+
@logger.error('no valid response received from pagerduty!')
|
229
|
+
return nil
|
230
|
+
end
|
231
|
+
|
232
|
+
if response['incidents'].nil?
|
233
|
+
@logger.error('no incidents found in response')
|
234
|
+
return nil
|
235
|
+
end
|
236
|
+
|
237
|
+
return nil if response['incidents'].empty?
|
238
|
+
|
239
|
+
{:pg_acknowledged_by => response['incidents'].first['last_status_change_by']}
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|