flapjack 0.6.39 → 0.6.40

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.
Files changed (66) hide show
  1. data/.gitignore +2 -2
  2. data/Gemfile +5 -1
  3. data/README.md +3 -2
  4. data/Rakefile +2 -1
  5. data/bin/flapjack +2 -2
  6. data/bin/flapjack-nagios-receiver +2 -8
  7. data/bin/flapjack-populator +11 -11
  8. data/etc/flapjack_config.yaml.example +28 -0
  9. data/features/steps/events_steps.rb +1 -1
  10. data/features/steps/notifications_steps.rb +7 -4
  11. data/features/support/env.rb +17 -6
  12. data/flapjack.gemspec +1 -0
  13. data/lib/flapjack/api.rb +72 -28
  14. data/lib/flapjack/configuration.rb +9 -1
  15. data/lib/flapjack/coordinator.rb +138 -162
  16. data/lib/flapjack/data/contact.rb +3 -1
  17. data/lib/flapjack/data/entity.rb +10 -1
  18. data/lib/flapjack/data/entity_check.rb +19 -21
  19. data/lib/flapjack/data/event.rb +26 -27
  20. data/lib/flapjack/data/message.rb +45 -0
  21. data/lib/flapjack/data/notification.rb +49 -0
  22. data/lib/flapjack/executive.rb +53 -74
  23. data/lib/flapjack/filters/acknowledgement.rb +14 -11
  24. data/lib/flapjack/jabber.rb +84 -18
  25. data/lib/flapjack/notification/email.rb +67 -37
  26. data/lib/flapjack/notification/sms.rb +40 -28
  27. data/lib/flapjack/oobetet.rb +1 -1
  28. data/lib/flapjack/pagerduty.rb +24 -15
  29. data/lib/flapjack/patches.rb +3 -1
  30. data/lib/flapjack/pikelet.rb +51 -20
  31. data/lib/flapjack/rack_logger.rb +8 -0
  32. data/lib/flapjack/version.rb +1 -1
  33. data/lib/flapjack/web.rb +51 -27
  34. data/spec/lib/flapjack/api_spec.rb +28 -3
  35. data/spec/lib/flapjack/coordinator_spec.rb +69 -43
  36. data/spec/lib/flapjack/data/contact_spec.rb +17 -9
  37. data/spec/lib/flapjack/data/entity_check_spec.rb +0 -25
  38. data/spec/lib/flapjack/data/entity_spec.rb +4 -0
  39. data/spec/lib/flapjack/data/global_spec.rb +6 -0
  40. data/spec/lib/flapjack/data/message_spec.rb +6 -0
  41. data/spec/lib/flapjack/data/notification_spec.rb +6 -0
  42. data/spec/lib/flapjack/executive_spec.rb +2 -2
  43. data/spec/lib/flapjack/jabber_spec.rb +8 -9
  44. data/spec/lib/flapjack/pagerduty_spec.rb +53 -45
  45. data/spec/lib/flapjack/utility_spec.rb +55 -0
  46. data/spec/lib/flapjack/web_spec.rb +7 -5
  47. data/tasks/events.rake +26 -59
  48. data/tasks/profile.rake +366 -0
  49. metadata +30 -19
  50. data/lib/flapjack/notification/common.rb +0 -23
  51. data/lib/flapjack/persistence/couch.rb +0 -5
  52. data/lib/flapjack/persistence/couch/connection.rb +0 -66
  53. data/lib/flapjack/persistence/couch/couch.rb +0 -63
  54. data/lib/flapjack/persistence/data_mapper.rb +0 -3
  55. data/lib/flapjack/persistence/data_mapper/data_mapper.rb +0 -67
  56. data/lib/flapjack/persistence/data_mapper/models/check.rb +0 -90
  57. data/lib/flapjack/persistence/data_mapper/models/check_template.rb +0 -20
  58. data/lib/flapjack/persistence/data_mapper/models/event.rb +0 -19
  59. data/lib/flapjack/persistence/data_mapper/models/node.rb +0 -18
  60. data/lib/flapjack/persistence/data_mapper/models/related_check.rb +0 -15
  61. data/lib/flapjack/persistence/sqlite3.rb +0 -3
  62. data/lib/flapjack/persistence/sqlite3/sqlite3.rb +0 -166
  63. data/lib/flapjack/transports/beanstalkd.rb +0 -50
  64. data/lib/flapjack/transports/result.rb +0 -58
  65. data/lib/flapjack/worker/application.rb +0 -121
  66. data/lib/flapjack/worker/cli.rb +0 -49
@@ -4,7 +4,7 @@ require 'flapjack/data/contact'
4
4
 
5
5
  describe Flapjack::Data::Contact, :redis => true do
6
6
 
7
- it "returns a list of all contacts" do
7
+ def add_contacts
8
8
  Flapjack::Data::Contact.add({'id' => '362',
9
9
  'first_name' => 'John',
10
10
  'last_name' => 'Johnson',
@@ -15,21 +15,21 @@ describe Flapjack::Data::Contact, :redis => true do
15
15
  'last_name' => 'Janeley',
16
16
  'email' => 'janej@example.com'},
17
17
  :redis => @redis)
18
+ end
19
+
20
+ it "returns a list of all contacts" do
21
+ add_contacts
18
22
 
19
23
  contacts = Flapjack::Data::Contact.all(:redis => @redis)
20
24
  contacts.should_not be_nil
21
25
  contacts.should be_an(Array)
22
26
  contacts.should have(2).contacts
23
- contacts[0].id.should == '362'
24
- contacts[1].id.should == '363'
27
+ contacts[0].name.should == 'Jane Janeley'
28
+ contacts[1].name.should == 'John Johnson'
25
29
  end
26
30
 
27
31
  it "finds a contact by id" do
28
- Flapjack::Data::Contact.add({'id' => '362',
29
- 'first_name' => 'John',
30
- 'last_name' => 'Johnson',
31
- 'email' => 'johnj@example.com' },
32
- :redis => @redis)
32
+ add_contacts
33
33
 
34
34
  contact = Flapjack::Data::Contact.find_by_id('362', :redis => @redis)
35
35
  contact.should_not be_nil
@@ -38,7 +38,15 @@ describe Flapjack::Data::Contact, :redis => true do
38
38
 
39
39
  it "finds all contacts for a check on an entity"
40
40
 
41
- it "deletes all contacts"
41
+ it "deletes all contacts" do
42
+ add_contacts
43
+
44
+ Flapjack::Data::Contact.delete_all(:redis => @redis)
45
+ contact = Flapjack::Data::Contact.find_by_id('362', :redis => @redis)
46
+ contact.should be_nil
47
+ contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
48
+ contact.should be_nil
49
+ end
42
50
 
43
51
  it "returns pagerduty credentials for a contact"
44
52
 
@@ -214,31 +214,6 @@ describe Flapjack::Data::EntityCheck, :redis => true do
214
214
 
215
215
  end
216
216
 
217
- it "creates an event" do
218
- ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
219
- t = Time.now.to_i
220
- ec.create_event('type' => 'service',
221
- 'state' => 'ok',
222
- 'summary' => 'everything checked out',
223
- 'time' => t)
224
- event_json = @redis.rpop('events')
225
- event_json.should_not be_nil
226
- event = nil
227
- expect {
228
- event = JSON.parse(event_json)
229
- }.not_to raise_error
230
- event.should_not be_nil
231
- event.should be_a(Hash)
232
- event.should == {
233
- 'entity' => name,
234
- 'check' => check,
235
- 'type' => 'service',
236
- 'state' => 'ok',
237
- 'summary' => 'everything checked out',
238
- 'time' => t
239
- }
240
- end
241
-
242
217
  it "creates an acknowledgement" do
243
218
  ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
244
219
  t = Time.now.to_i
@@ -35,6 +35,10 @@ describe Flapjack::Data::Entity, :redis => true do
35
35
  end
36
36
 
37
37
  it "returns a list of all entities" do
38
+
39
+ pending "Broken with redis 2.6, which changes the default ordering. " +
40
+ "I have a fix for this in another branch, will handle on merge."
41
+
38
42
  Flapjack::Data::Entity.add({'id' => '5000',
39
43
  'name' => name},
40
44
  :redis => @redis)
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/data/global'
3
+
4
+ describe Flapjack::Data::Global do
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/data/message'
3
+
4
+ describe Flapjack::Data::Message do
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/data/notification'
3
+
4
+ describe Flapjack::Data::Notification do
5
+
6
+ end
@@ -11,7 +11,6 @@ describe Flapjack::Executive, :redis => true do
11
11
  redis.should_receive(:rpush).with('events', %q{{"type":"shutdown","host":"","service":"","state":""}})
12
12
 
13
13
  executive = Flapjack::Executive.new
14
- executive.bootstrap(:redis => @redis)
15
14
  executive.add_shutdown_event(:redis => redis)
16
15
  end
17
16
 
@@ -35,14 +34,15 @@ describe Flapjack::Executive, :redis => true do
35
34
  Flapjack::Data::Event.should_receive(:next).and_return(shutdown_evt)
36
35
 
37
36
  executive = Flapjack::Executive.new
37
+ Flapjack::RedisPool.should_receive(:new).and_return(@redis)
38
38
  executive.bootstrap(:config => {})
39
39
  @redis.should_receive(:empty!)
40
- executive.should_receive(:build_redis_connection_pool).and_return(@redis)
41
40
 
42
41
  # hacky, but the behaviour it's mimicking (shutdown from another thread) isn't
43
42
  # conducive to nice tests
44
43
  executive.stub(:should_quit?).and_return(false, true)
45
44
  executive.main
45
+ executive.cleanup
46
46
 
47
47
  # TODO these will need to be made relative to the running instance,
48
48
  # and a list of the running instances maintained somewhere
@@ -15,17 +15,12 @@ describe Flapjack::Jabber do
15
15
 
16
16
  let(:stanza) { mock('stanza') }
17
17
 
18
- it "is initialized" do
19
- fj = Flapjack::Jabber.new
20
- fj.should_not be_nil
21
- end
22
-
23
18
  it "hooks up event handlers to the appropriate methods" do
24
19
  Socket.should_receive(:gethostname).and_return('thismachine')
25
20
 
26
21
  fj = Flapjack::Jabber.new
22
+ Flapjack::RedisPool.should_receive(:new)
27
23
  fj.bootstrap(:config => config)
28
- fj.should_receive(:build_redis_connection_pool)
29
24
 
30
25
  EventMachine::Synchrony.should_receive(:next_tick).exactly(4).times.and_yield
31
26
 
@@ -46,10 +41,9 @@ describe Flapjack::Jabber do
46
41
 
47
42
  it "joins a chat room after connecting" do
48
43
  fj = Flapjack::Jabber.new
44
+ Flapjack::RedisPool.should_receive(:new).twice
49
45
  fj.bootstrap(:config => config)
50
46
 
51
- fj.should_receive(:build_redis_connection_pool)
52
-
53
47
  fj.should_receive(:connected?).and_return(true)
54
48
  fj.should_receive(:write).with(an_instance_of(Blather::Stanza::Presence))
55
49
  fj.should_receive(:write).with(an_instance_of(Blather::Stanza::Message))
@@ -79,6 +73,7 @@ describe Flapjack::Jabber do
79
73
  and_return(entity_check)
80
74
 
81
75
  fj = Flapjack::Jabber.new
76
+ Flapjack::RedisPool.should_receive(:new)
82
77
  fj.bootstrap(:config => config)
83
78
  fj.instance_variable_set('@redis_handler', redis)
84
79
 
@@ -95,6 +90,7 @@ describe Flapjack::Jabber do
95
90
  stanza.should_receive(:from).and_return(from)
96
91
 
97
92
  fj = Flapjack::Jabber.new
93
+ Flapjack::RedisPool.should_receive(:new)
98
94
  fj.bootstrap(:config => config)
99
95
 
100
96
  fj.should_receive(:connected?).and_return(true)
@@ -105,6 +101,7 @@ describe Flapjack::Jabber do
105
101
 
106
102
  it "reconnects when disconnected (if not quitting)" do
107
103
  fj = Flapjack::Jabber.new
104
+ Flapjack::RedisPool.should_receive(:new)
108
105
  fj.bootstrap(:config => config)
109
106
 
110
107
  EventMachine::Timer.should_receive(:new).with(1).and_yield
@@ -119,6 +116,7 @@ describe Flapjack::Jabber do
119
116
  redis.should_receive(:rpush).with('jabber_notifications', %q{{"notification_type":"shutdown"}})
120
117
 
121
118
  fj = Flapjack::Jabber.new
119
+ Flapjack::RedisPool.should_receive(:new)
122
120
  fj.bootstrap(:config => config)
123
121
 
124
122
  fj.add_shutdown_event(:redis => redis)
@@ -136,8 +134,8 @@ describe Flapjack::Jabber do
136
134
  redis.should_receive(:empty!)
137
135
 
138
136
  fj = Flapjack::Jabber.new
137
+ Flapjack::RedisPool.should_receive(:new).and_return(redis)
139
138
  fj.bootstrap(:config => config)
140
- fj.should_receive(:build_redis_connection_pool).and_return(redis)
141
139
  fj.should_receive(:register_handler).exactly(4).times
142
140
 
143
141
  fj.should_receive(:connect)
@@ -153,6 +151,7 @@ describe Flapjack::Jabber do
153
151
  fj.should_receive(:close)
154
152
 
155
153
  fj.main
154
+ fj.cleanup
156
155
  end
157
156
 
158
157
  end
@@ -12,17 +12,19 @@ describe Flapjack::Pagerduty, :redis => true do
12
12
 
13
13
  it "prompts the blocking redis connection to quit" do
14
14
  redis = mock('redis')
15
- redis.should_receive(:rpush).with(nil, %q{{"notification_type":"shutdown"}})
15
+ redis.should_receive(:rpush).with(config['queue'], %q{{"notification_type":"shutdown"}})
16
16
 
17
- pagerduty = Flapjack::Pagerduty.new
18
- pagerduty.bootstrap
19
- pagerduty.add_shutdown_event(:redis => redis)
17
+ fp = Flapjack::Pagerduty.new
18
+ Flapjack::RedisPool.should_receive(:new)
19
+ fp.bootstrap(:config => config)
20
+ fp.add_shutdown_event(:redis => redis)
20
21
  end
21
22
 
22
23
  it "doesn't look for acknowledgements if this search is already running" do
23
24
  @redis.set(Flapjack::Pagerduty::SEM_PAGERDUTY_ACKS_RUNNING, 'true')
24
25
 
25
26
  fp = Flapjack::Pagerduty.new
27
+ Flapjack::RedisPool.should_receive(:new)
26
28
  fp.bootstrap(:config => config)
27
29
  fp.instance_variable_set("@redis_timer", @redis)
28
30
 
@@ -32,6 +34,7 @@ describe Flapjack::Pagerduty, :redis => true do
32
34
 
33
35
  it "looks for acknowledgements if the search is not already running" do
34
36
  fp = Flapjack::Pagerduty.new
37
+ Flapjack::RedisPool.should_receive(:new)
35
38
  fp.bootstrap(:config => config)
36
39
  fp.instance_variable_set("@redis_timer", @redis)
37
40
 
@@ -45,33 +48,34 @@ describe Flapjack::Pagerduty, :redis => true do
45
48
 
46
49
  # NB: needs to run in synchrony block to catch the evented HTTP requests
47
50
  it "looks for acknowledgements via the PagerDuty API" do
51
+ check = 'PING'
52
+ Time.should_receive(:now).and_return(time)
53
+ since = (time.utc - (60*60*24*7)).iso8601 # the last week
54
+ unt = (time.utc + (60*60*24)).iso8601 # 1 day in the future
55
+
56
+ response = {"incidents" =>
57
+ [{"incident_number" => 12,
58
+ "status" => "acknowledged",
59
+ "last_status_change_by" => {"id"=>"ABCDEFG", "name"=>"John Smith",
60
+ "email"=>"johns@example.com",
61
+ "html_url"=>"http://flpjck.pagerduty.com/users/ABCDEFG"}
62
+ }
63
+ ],
64
+ "limit"=>100,
65
+ "offset"=>0,
66
+ "total"=>1}
67
+
68
+ stub_request(:get, "https://flpjck.pagerduty.com/api/v1/incidents?" +
69
+ "fields=incident_number,status,last_status_change_by&incident_key=#{check}&" +
70
+ "since=#{since}&status=acknowledged&until=#{unt}").
71
+ with(:headers => {'Authorization'=>['flapjack', 'password123']}).
72
+ to_return(:status => 200, :body => response.to_json, :headers => {})
73
+
48
74
  EM.synchrony do
49
75
  fp = Flapjack::Pagerduty.new
76
+ Flapjack::RedisPool.should_receive(:new)
50
77
  fp.bootstrap(:config => config)
51
78
 
52
- check = 'PING'
53
- Time.should_receive(:now).and_return(time)
54
- since = (time.utc - (60*60*24*7)).iso8601 # the last week
55
- unt = (time.utc + (60*60*24)).iso8601 # 1 day in the future
56
-
57
- response = {"incidents" =>
58
- [{"incident_number" => 12,
59
- "status" => "acknowledged",
60
- "last_status_change_by" => {"id"=>"ABCDEFG", "name"=>"John Smith",
61
- "email"=>"johns@example.com",
62
- "html_url"=>"http://flpjck.pagerduty.com/users/ABCDEFG"}
63
- }
64
- ],
65
- "limit"=>100,
66
- "offset"=>0,
67
- "total"=>1}
68
-
69
- stub_request(:get, "https://flpjck.pagerduty.com/api/v1/incidents?" +
70
- "fields=incident_number,status,last_status_change_by&incident_key=#{check}&" +
71
- "since=#{since}&status=acknowledged&until=#{unt}").
72
- with(:headers => {'Authorization'=>['flapjack', 'password123']}).
73
- to_return(:status => 200, :body => response.to_json, :headers => {})
74
-
75
79
  result = fp.send(:pagerduty_acknowledged?, 'subdomain' => 'flpjck', 'username' => 'flapjack',
76
80
  'password' => 'password123', 'check' => check)
77
81
 
@@ -86,6 +90,7 @@ describe Flapjack::Pagerduty, :redis => true do
86
90
 
87
91
  it "creates acknowledgements when pagerduty acknowledgements are found" do
88
92
  fp = Flapjack::Pagerduty.new
93
+ Flapjack::RedisPool.should_receive(:new)
89
94
  fp.bootstrap(:config => config)
90
95
 
91
96
  entity_check = mock('entity_check')
@@ -115,8 +120,8 @@ describe Flapjack::Pagerduty, :redis => true do
115
120
  redis.should_receive(:empty!)
116
121
 
117
122
  fp = Flapjack::Pagerduty.new
123
+ Flapjack::RedisPool.should_receive(:new).and_return(redis)
118
124
  fp.bootstrap(:config => config)
119
- fp.should_receive(:build_redis_connection_pool).and_return(redis)
120
125
 
121
126
  fp.should_receive(:should_quit?).exactly(3).times.and_return(false, false, true)
122
127
  redis.should_receive(:blpop).twice.and_return(
@@ -128,21 +133,22 @@ describe Flapjack::Pagerduty, :redis => true do
128
133
  fp.should_receive(:send_pagerduty_event)
129
134
 
130
135
  fp.main
136
+ fp.cleanup
131
137
  end
132
138
 
133
139
  it "tests the pagerduty connection" do
134
- EM.synchrony do
140
+ evt = { "service_key" => "11111111111111111111111111111111",
141
+ "incident_key" => "Flapjack is running a NOOP",
142
+ "event_type" => "nop",
143
+ "description" => "I love APIs with noops." }
144
+ body = evt.to_json
135
145
 
136
- evt = { "service_key" => "11111111111111111111111111111111",
137
- "incident_key" => "Flapjack is running a NOOP",
138
- "event_type" => "nop",
139
- "description" => "I love APIs with noops." }
140
-
141
- body = evt.to_json
142
- stub_request(:post, "https://events.pagerduty.com/generic/2010-04-15/create_event.json").
143
- with(:body => body).to_return(:status => 200, :body => '{"status":"success"}', :headers => {})
146
+ stub_request(:post, "https://events.pagerduty.com/generic/2010-04-15/create_event.json").
147
+ with(:body => body).to_return(:status => 200, :body => '{"status":"success"}', :headers => {})
144
148
 
149
+ EM.synchrony do
145
150
  fp = Flapjack::Pagerduty.new
151
+ Flapjack::RedisPool.should_receive(:new)
146
152
  fp.bootstrap(:config => config)
147
153
 
148
154
  ret = fp.send(:test_pagerduty_connection)
@@ -153,17 +159,19 @@ describe Flapjack::Pagerduty, :redis => true do
153
159
  end
154
160
 
155
161
  it "sends an event to pagerduty" do
156
- EM.synchrony do
162
+ evt = {"service_key" => "abcdefg",
163
+ "incident_key" => "Flapjack test",
164
+ "event_type" => "nop",
165
+ "description" => "Not really sent anyway"}
166
+ body = evt.to_json
157
167
 
158
- evt = {"service_key" => "abcdefg",
159
- "incident_key" => "Flapjack test",
160
- "event_type" => "nop",
161
- "description" => "Not really sent anyway"}
162
- body = evt.to_json
163
- stub_request(:post, "https://events.pagerduty.com/generic/2010-04-15/create_event.json").
164
- with(:body => body).to_return(:status => 200, :body => "", :headers => {})
168
+ stub_request(:post, "https://events.pagerduty.com/generic/2010-04-15/create_event.json").
169
+ with(:body => body).to_return(:status => 200, :body => "", :headers => {})
170
+
171
+ EM.synchrony do
165
172
 
166
173
  fp = Flapjack::Pagerduty.new
174
+ Flapjack::RedisPool.should_receive(:new)
167
175
  fp.bootstrap(:config => config)
168
176
 
169
177
  ret = fp.send(:send_pagerduty_event, evt)
@@ -0,0 +1,55 @@
1
+
2
+ require 'spec_helper'
3
+ require 'flapjack/utility'
4
+
5
+ describe Flapjack::Utility do
6
+
7
+ context "relative time ago" do
8
+
9
+ # ported from sinatra_more tests for the method
10
+ include Flapjack::Utility
11
+
12
+ let(:time) { Time.new }
13
+
14
+ before(:each) do
15
+ Time.should_receive(:now).and_return(time)
16
+ end
17
+
18
+ it 'displays now as a minute ago' do
19
+ 'about a minute'.should == relative_time_ago(time - 60)
20
+ end
21
+ it "displays a few minutes ago" do
22
+ '4 minutes'.should == relative_time_ago(time - (4 * 60))
23
+ end
24
+ it "displays an hour ago" do
25
+ 'about 1 hour'.should == relative_time_ago(time - (65 * 60))
26
+ end
27
+ it "displays a few hours ago" do
28
+ 'about 3 hours'.should == relative_time_ago(time - (185 * 60))
29
+ end
30
+ it "displays a day ago" do
31
+ '1 day'.should == relative_time_ago(time - (24 * 60 * 60))
32
+ end
33
+ it "displays about 2 days ago" do
34
+ 'about 2 days'.should == relative_time_ago(time - (2 * 24 * 60 * 60) + (5 * 60))
35
+ end
36
+ it "displays a few days ago" do
37
+ '5 days'.should == relative_time_ago(time - (5 * 24 * 60 * 60) - (5 * 60))
38
+ end
39
+ it "displays a month ago" do
40
+ 'about 1 month'.should == relative_time_ago(time - (32 * 24 * 60 * 60) - (5 * 60))
41
+ end
42
+ it "displays a few months ago" do
43
+ '6 months'.should == relative_time_ago(time - (180 * 24 * 60 * 60) - (5 * 60))
44
+ end
45
+ it "displays a year ago" do
46
+ 'about 1 year'.should == relative_time_ago(time - (365 * 24 * 60 * 60) - (5 * 60))
47
+ end
48
+ it "displays a few years ago" do
49
+ 'over 7 years'.should == relative_time_ago(time - (2800 * 24 * 60 * 60) + (5 * 60))
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+