upstreamstatus 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd0f5883836782fed4233bd0ace4cd5154c4bc31
4
- data.tar.gz: c6711826ac9880fafeec8503830d65a8450b59ab
3
+ metadata.gz: 551dd8502211ecb555bed1af238fdbb134bb822e
4
+ data.tar.gz: 6f898adcff62a5ea936973848173d6dd12ebbefc
5
5
  SHA512:
6
- metadata.gz: 9219c273817d132304dca8cfe47403d2f41d2cb5c55af3df67ed16fb7429b69d14a224ff312b7df56110e0af1de392b4cb0739ef41670f008185dc5d46e34024
7
- data.tar.gz: 83c547e71abdc2a041d4cdad1b26c37980b51af03c4148bab8db16766e60282e00910d8b603fdb614cdcb61f6106f15f8f62a62502046d26941801beba953fc8
6
+ metadata.gz: 68d220a9b70a101755492030c8b001fb1aee2fbb0b5f3b9258b3a08a2484b7f04f1cbf30b84f09783c0c17c685d8d9f9188a72d39de0edf401b2286f467d953e
7
+ data.tar.gz: f46a8d49bfbc90aa324036894b3cc0a9b75bbb291407da17e6fbb0f10f22e023983e2e11ad685b4e8ea29fb10105200d99a2ac67589cd9efe951a5345531ab06
@@ -1,3 +1,3 @@
1
1
  class Upstreamstatus
2
- VERSION = "0.2.6"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -9,6 +9,8 @@ require 'json'
9
9
  require 'sentry-raven'
10
10
  require 'pagerduty'
11
11
  require 'time'
12
+ require 'socket'
13
+ require 'byebug'
12
14
 
13
15
  class Upstreamstatus
14
16
  extend Forwardable
@@ -48,24 +50,26 @@ class Upstreamstatus
48
50
  end
49
51
  end
50
52
 
53
+ def down_hosts
54
+ current_status['servers']['server'].select { |s| s['status'] != 'up' }
55
+ end
56
+
51
57
  def run
52
- down_hosts =
53
- current_status['servers']['server'].select { |s| s['status'] != 'up' }
58
+ clear_active_alerts
54
59
 
55
- if down_hosts.empty?
56
- clear_active_alerts!
57
- exit 0
58
- end
60
+ exit 0 if down_hosts.empty?
59
61
 
60
62
  puts "Detected down hosts:\n"
61
63
  print_hosts down_hosts
62
64
  logger.info "Detected down hosts: #{down_hosts.to_json}"
63
65
 
64
66
  if opts[:notify]
65
- notify(
66
- 'One or more API upstream hosts listed as down',
67
- JSON.pretty_generate(down_hosts)
68
- )
67
+ down_hosts.each do |host|
68
+ notify(
69
+ "Upstream host #{host['upstream']} listed as down",
70
+ host
71
+ )
72
+ end
69
73
  end
70
74
  exit 1
71
75
  rescue Interrupt => e
@@ -84,73 +88,71 @@ class Upstreamstatus
84
88
  end
85
89
 
86
90
  def current_status
87
- return fake_response if opts[:simulate]
91
+ @current_status ||= begin
92
+ return fake_response if opts[:simulate]
88
93
 
89
- r = Unirest.get status_check_url
94
+ r = Unirest.get status_check_url
90
95
 
91
- unless (200..299).include?(r.code)
92
- fail "Error code: #{r.code}\n" \
93
- "Headers: #{r.headers}" \
94
- "Body: #{r.body}"
95
- end
96
+ unless (200..299).include?(r.code)
97
+ fail "Error code: #{r.code}\n" \
98
+ "Headers: #{r.headers}" \
99
+ "Body: #{r.body}"
100
+ end
96
101
 
97
- r.body
102
+ r.body
103
+ end
98
104
  end
99
105
 
100
106
  private
101
107
 
102
- def pd_incidents
103
- @pd_incidents ||= begin
104
- r = Unirest.get(
105
- "#{pagerduty_api_url}/incidents",
106
- parameters: { service: pagerduty_service_id }
108
+ def notify(msg, host)
109
+ if active_alert?(host['upstream'])
110
+ puts "Already an active alert. Not sending anything (message: #{msg})"
111
+ else
112
+ puts "Notifying PagerDuty (message: #{msg})"
113
+ pagerduty.trigger(
114
+ msg,
115
+ incident_key: "upstreamstatus #{Socket.gethostname} #{host['upstream']}",
116
+ client: Socket.gethostname,
117
+ details: host
107
118
  )
108
- fail "Result: #{r.inspect}" unless (200..299).include?(r.code)
109
- r.body['incidents']
110
119
  end
111
120
  end
112
121
 
113
- def fake_response
114
- {
115
- 'servers' => {
116
- 'total' => 2,
117
- 'generation' => 99,
118
- 'server' => [
119
- {
120
- 'index' => 0,
121
- 'upstream' => 'testupstream',
122
- 'name' => '10.0.0.1 =>8080',
123
- 'status' => 'up',
124
- 'rise' => 10_459,
125
- 'fall' => 0,
126
- 'type' => 'http',
127
- 'port' => 0
128
- },
129
- {
130
- 'index' => 1,
131
- 'upstream' => 'testupstream',
132
- 'name' => '10.0.0.2 =>8080',
133
- 'status' => 'down',
134
- 'rise' => 10_029,
135
- 'fall' => 0,
136
- 'type' => 'http',
137
- 'port' => 0
138
- }
139
- ]
122
+ def active_alert?(host)
123
+ active_alerts.find do |a|
124
+ a['incident_key'] == "upstreamstatus #{Socket.gethostname} #{host['upstream']}"
125
+ end
126
+ end
127
+
128
+ def active_alerts
129
+ @active_alerts ||= active_alerts_paged
130
+ end
131
+
132
+ def active_alerts_paged(offset = 0)
133
+ r = Unirest.get(
134
+ "#{pagerduty_api_url}/incidents",
135
+ parameters: {
136
+ service: pagerduty_service_id,
137
+ status: 'triggered,acknowledged',
138
+ offset: offset
140
139
  }
141
- }
140
+ )
141
+ fail "Result: #{r.inspect}" unless (200..299).include?(r.code)
142
+ pointer = r.body['limit'] + offset
143
+ r.body['incidents'] + (pointer < r.body['total'] ? active_alerts_paged(pointer) : [])
142
144
  end
143
145
 
144
- def clear_active_alerts!
146
+ def clear_active_alerts
145
147
  return unless opts[:notify]
146
- pd_incidents.each do |i|
147
- resolve_incident i['incident_key'] unless i['status'] == 'resolved'
148
+ active_alerts.reject { |a| down_hosts_incident_keys.include? a['incident_key'] }.each do |a|
149
+ puts "Resolving incident: #{a['incident_key']}"
150
+ pagerduty.get_incident(a['incident_key']).resolve
148
151
  end
149
152
  end
150
153
 
151
- def resolve_incident(incident_key)
152
- puts "Resolving incident: #{incident_key}"
153
- pagerduty.get_incident(incident_key).resolve
154
+ def down_hosts_incident_keys
155
+ down_hosts.map { |host| "upstreamstatus #{Socket.gethostname} #{host['upstream']}" }
154
156
  end
155
157
 
156
158
  def logger
@@ -161,39 +163,6 @@ class Upstreamstatus
161
163
  @pagerduty ||= Pagerduty.new pagerduty_api_key
162
164
  end
163
165
 
164
- def notify(msg, details)
165
- if active_alert?(msg)
166
- puts "Already an active alert. Not sending anything (message: #{msg})"
167
- else
168
- puts "Notifying PagerDuty (message: #{msg})"
169
- pd = pagerduty.trigger(
170
- msg,
171
- client: ENV['hostname'],
172
- details: details
173
- )
174
-
175
- # You may have noticed that this will overwrite any previously active
176
- # alerts, regardless of whether they are the "same" alert. This is a known
177
- # limitation.
178
-
179
- File.write(
180
- '/var/run/active_upstream_alert',
181
- {
182
- 'Incident Key' => pd.incident_key,
183
- 'Message' => msg,
184
- 'Details' => details
185
- }.to_json
186
- )
187
- end
188
- end
189
-
190
- def active_alert?(msg)
191
- pd_incidents.find do |incident|
192
- incident['status'] != 'resolved' &&
193
- incident['trigger_summary_data']['description'] == msg
194
- end
195
- end
196
-
197
166
  def opts
198
167
  @opts ||= Trollop.options do
199
168
  opt :notify,
@@ -223,4 +192,45 @@ class Upstreamstatus
223
192
  def defaults
224
193
  { 'status_check_url' => 'http://localhost:8069/status?format=json' }
225
194
  end
195
+
196
+ def fake_response
197
+ {
198
+ 'servers' => {
199
+ 'total' => 2,
200
+ 'generation' => 99,
201
+ 'server' => [
202
+ {
203
+ 'index' => 0,
204
+ 'upstream' => 'testupstream0',
205
+ 'name' => '10.0.0.1 =>8080',
206
+ 'status' => 'up',
207
+ 'rise' => 10_459,
208
+ 'fall' => 0,
209
+ 'type' => 'http',
210
+ 'port' => 0
211
+ },
212
+ {
213
+ 'index' => 1,
214
+ 'upstream' => 'testupstream1',
215
+ 'name' => '10.0.0.2 =>8080',
216
+ 'status' => 'down',
217
+ 'rise' => 10_029,
218
+ 'fall' => 0,
219
+ 'type' => 'http',
220
+ 'port' => 0
221
+ },
222
+ {
223
+ 'index' => 2,
224
+ 'upstream' => 'testupstream2',
225
+ 'name' => '10.0.0.2 =>8080',
226
+ 'status' => 'down',
227
+ 'rise' => 10_029,
228
+ 'fall' => 0,
229
+ 'type' => 'http',
230
+ 'port' => 0
231
+ }
232
+ ]
233
+ }
234
+ }
235
+ end
226
236
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: upstreamstatus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Herot
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-12 00:00:00.000000000 Z
11
+ date: 2016-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: unirest
@@ -179,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
179
  version: '0'
180
180
  requirements: []
181
181
  rubyforge_project:
182
- rubygems_version: 2.4.5
182
+ rubygems_version: 2.5.1
183
183
  signing_key:
184
184
  specification_version: 4
185
185
  summary: Parse the output of the Nginx Upstream Check plugin