flapjack-diner 0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ module Flapjack
2
+ class ArgumentValidator
3
+
4
+ attr_reader :query
5
+
6
+ def initialize(query = {})
7
+ @errors = []
8
+ @query = query
9
+ end
10
+
11
+ def validate(args)
12
+ args = args.dup
13
+ validations = args.delete(:as)
14
+ validations = [validations] unless validations.is_a?(Array)
15
+
16
+ if elements = args[:query]
17
+ elements = [elements] unless elements.is_a?(Array)
18
+ validations.each do |validation|
19
+ __send__(validation.to_s.downcase, *elements)
20
+ end
21
+ end
22
+
23
+ raise ArgumentError.new(@errors.join('; ')) unless @errors.empty?
24
+ end
25
+
26
+ private
27
+
28
+ def time(*elements)
29
+ elements.each do |element|
30
+ if target = @query[element]
31
+ @errors << "'#{target}' should contain some kind of time object which responds to." unless target.respond_to?(:iso8601)
32
+ end
33
+ end
34
+ end
35
+
36
+ def required(*elements)
37
+ elements.each do |element|
38
+ @errors << "'#{element}' is required." if @query[element].nil?
39
+ end
40
+ end
41
+
42
+ def respond_to?(name, include_private = false)
43
+ !classify_name(name).nil? || super
44
+ end
45
+
46
+ def method_missing(name, *args)
47
+ return super unless klass = classify_name(name)
48
+ elements = args
49
+ elements.each do |element|
50
+ @errors << "'#{element}' is expected to be a #{klass}" unless @query[element].is_a?(klass)
51
+ end
52
+ end
53
+
54
+ def classify_name(name)
55
+ class_name = name.to_s.split('_').map(&:capitalize).join
56
+ Module.const_get(class_name)
57
+ rescue NameError
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ module Flapjack
2
+ module Diner
3
+ VERSION = "0.12"
4
+ end
5
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+ require "flapjack-diner/argument_validator"
3
+
4
+ describe Flapjack::ArgumentValidator do
5
+
6
+ context 'required' do
7
+
8
+ let(:query) do
9
+ {:entity => 'myservice', :check => 'HOST'}
10
+ end
11
+
12
+ subject { Flapjack::ArgumentValidator.new(query) }
13
+
14
+ it 'does not raise an exception when query entity is valid' do
15
+ lambda { subject.validate(:query => :entity, :as => :required) }.should_not raise_exception(ArgumentError)
16
+ end
17
+
18
+ it 'raises ArgumentError when query entity is invalid' do
19
+ query[:entity] = nil
20
+ lambda { subject.validate(:query => :entity, :as => :required) }.should raise_exception(ArgumentError)
21
+ end
22
+
23
+ it 'handles arrays as query values valid' do
24
+ lambda { subject.validate(:query => [:entity, :check], :as => :required) }.should_not raise_exception(ArgumentError)
25
+ end
26
+
27
+ it 'handles arrays as query values invalid' do
28
+ query[:check] = nil
29
+ lambda { subject.validate(:query => [:entity, :check], :as => :required) }.should raise_exception(ArgumentError)
30
+ end
31
+ end
32
+
33
+ context 'time' do
34
+
35
+ let(:query) do
36
+ {:start_time => Time.now, :duration => 10}
37
+ end
38
+
39
+ subject { Flapjack::ArgumentValidator.new(query) }
40
+
41
+ it 'does not raise an exception when query start_time is valid' do
42
+ lambda { subject.validate(:query => :start_time, :as => :time) }.should_not raise_exception(ArgumentError)
43
+ end
44
+
45
+ it 'raises an exception when query start_time is invalid' do
46
+ query[:start_time] = 1234
47
+ lambda { subject.validate(:query => :start_time, :as => :time) }.should raise_exception(ArgumentError)
48
+ end
49
+
50
+ it 'handles arrays as query values valid' do
51
+ query[:end_time] = Time.now
52
+ lambda { subject.validate(:query => [:start_time, :end_time], :as => :time) }.should_not raise_exception(ArgumentError)
53
+ end
54
+
55
+ it 'handles arrays as query values invalid' do
56
+ query[:end_time] = 3904
57
+ lambda { subject.validate(:query => [:start_time, :end_time], :as => :time) }.should raise_exception(ArgumentError)
58
+ end
59
+
60
+ it 'handles dates as query values' do
61
+ query[:end_time] = Date.today
62
+ lambda { subject.validate(:query => :end_time, :as => :time) }.should_not raise_exception(ArgumentError)
63
+ end
64
+ end
65
+
66
+ context 'integer via method missing' do
67
+
68
+ let(:query) do
69
+ {:start_time => Time.now, :duration => 10}
70
+ end
71
+
72
+ subject { Flapjack::ArgumentValidator.new(query) }
73
+
74
+ it 'does not raise an exception when query duration is valid' do
75
+ lambda { subject.validate(:query => :duration, :as => :integer) }.should_not raise_exception(ArgumentError)
76
+ end
77
+
78
+ it 'raises an exception when query duration is invalid' do
79
+ query[:duration] = '23'
80
+ lambda { subject.validate(:query => :duration, :as => :integer) }.should raise_exception(ArgumentError)
81
+ end
82
+ end
83
+
84
+ context 'multiple validations' do
85
+
86
+ let(:query) do
87
+ {:start_time => Time.now, :duration => 10}
88
+ end
89
+
90
+ subject { Flapjack::ArgumentValidator.new(query) }
91
+
92
+ it 'does not raise an exception when query start_time is valid' do
93
+ lambda { subject.validate(:query => :start_time, :as => [:time, :required]) }.should_not raise_exception(ArgumentError)
94
+ end
95
+
96
+ it 'raises an exception when query start_time is invalid' do
97
+ query[:start_time] = nil
98
+ lambda { subject.validate(:query => :start_time, :as => [:time, :required]) }.should raise_exception(ArgumentError)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,877 @@
1
+ require 'spec_helper'
2
+ require 'flapjack-diner'
3
+
4
+ describe Flapjack::Diner do
5
+
6
+ let(:server) { 'flapjack.com' }
7
+ let(:entity) { 'ex-abcd-data-17.example.com' }
8
+ let(:check) { 'ping'}
9
+
10
+ let(:rule_data) {
11
+ {"contact_id" => "21",
12
+ "entity_tags" => ["database","physical"],
13
+ "entities" => ["foo-app-01.example.com"],
14
+ "time_restrictions" => nil,
15
+ "warning_media" => ["email"],
16
+ "critical_media" => ["sms", "email"],
17
+ "warning_blackhole" => false,
18
+ "critical_blackhole" => false
19
+ }
20
+ }
21
+
22
+ let(:response) { '{"key":"value"}' }
23
+ let(:response_body) { {'key' => 'value'} }
24
+
25
+ before(:each) do
26
+ Flapjack::Diner.base_uri(server)
27
+ Flapjack::Diner.logger = nil
28
+ end
29
+
30
+ after(:each) do
31
+ WebMock.reset!
32
+ end
33
+
34
+ it "returns a json list of entities" do
35
+ req = stub_request(:get, "http://#{server}/entities").to_return(
36
+ :body => response)
37
+
38
+ result = Flapjack::Diner.entities
39
+ req.should have_been_requested
40
+ result.should_not be_nil
41
+ result.should == response_body
42
+ end
43
+
44
+ it "returns a json list of entities from a non-standard port" do
45
+ Flapjack::Diner.base_uri('flapjack.com:54321')
46
+
47
+ req = stub_request(:get, "http://#{server}:54321/entities").to_return(
48
+ :body => response)
49
+
50
+ result = Flapjack::Diner.entities
51
+ req.should have_been_requested
52
+ result.should_not be_nil
53
+ result.should == response_body
54
+ end
55
+
56
+ it "returns a json list of checks for an entity" do
57
+ req = stub_request(:get, "http://#{server}/checks/#{entity}").to_return(
58
+ :body => response)
59
+
60
+ result = Flapjack::Diner.checks(entity)
61
+ req.should have_been_requested
62
+ result.should_not be_nil
63
+ result.should == response_body
64
+ end
65
+
66
+ it "returns a json list of check statuses for an entity" do
67
+ req = stub_request(:get, "http://#{server}/status").
68
+ with(:query => {:entity => entity}).
69
+ to_return(:body => response)
70
+
71
+ result = Flapjack::Diner.status(entity)
72
+ req.should have_been_requested
73
+ result.should_not be_nil
74
+ result.should == response_body
75
+ end
76
+
77
+ it "returns a list of entity statuses for a bulk query" do
78
+ req = stub_request(:get, "http://#{server}/status").
79
+ with(:query => {:entity => ['abc.net', 'def.com'], :check => {'ghi.net' => 'ping', 'jkl.org' => ['ping', 'ssh']}}).
80
+ to_return(:body => response)
81
+
82
+ result = Flapjack::Diner.bulk_status(:entity => ['abc.net', 'def.com'], :check => {'ghi.net' => 'ping', 'jkl.org' => ['ping', 'ssh']})
83
+ req.should have_been_requested
84
+ result.should_not be_nil
85
+ result.should == response_body
86
+ end
87
+
88
+ it "returns a single check status for an entity" do
89
+ req = stub_request(:get, "http://#{server}/status").
90
+ with(:query => {:check => {entity => check}}).
91
+ to_return(:body => response)
92
+
93
+ result = Flapjack::Diner.status(entity, :check => check)
94
+ req.should have_been_requested
95
+ result.should_not be_nil
96
+ result.should == response_body
97
+ end
98
+
99
+ it "returns a list of scheduled maintenance periods for all checks on an entity" do
100
+ req = stub_request(:get, "http://#{server}/scheduled_maintenances").
101
+ with(:query => {:entity => entity}).
102
+ to_return(:body => response)
103
+
104
+ result = Flapjack::Diner.scheduled_maintenances(entity)
105
+ req.should have_been_requested
106
+ result.should_not be_nil
107
+ result.should == response_body
108
+ end
109
+
110
+ it "returns a list of scheduled maintenance periods for a check on an entity" do
111
+ req = stub_request(:get, "http://#{server}/scheduled_maintenances").
112
+ with(:query => {:check => {entity => check}}).
113
+ to_return(:body => response)
114
+
115
+ result = Flapjack::Diner.scheduled_maintenances(entity, :check => check)
116
+ req.should have_been_requested
117
+ result.should_not be_nil
118
+ result.should == response_body
119
+ end
120
+
121
+ it "returns a list of scheduled maintenance periods for a bulk query" do
122
+ req = stub_request(:get, "http://#{server}/scheduled_maintenances").
123
+ with(:query => {:entity => 'abc.net', :check => {'def.org' => 'ping'}}).
124
+ to_return(:body => response)
125
+
126
+ result = Flapjack::Diner.bulk_scheduled_maintenances(:entity => 'abc.net', :check => {'def.org' => 'ping'})
127
+ req.should have_been_requested
128
+ result.should_not be_nil
129
+ result.should == response_body
130
+ end
131
+
132
+ it "returns a list of unscheduled maintenance periods for all checks on an entity" do
133
+ req = stub_request(:get, "http://#{server}/unscheduled_maintenances").
134
+ with(:query => {:entity => entity}).
135
+ to_return(:body => response)
136
+
137
+ result = Flapjack::Diner.unscheduled_maintenances(entity)
138
+ req.should have_been_requested
139
+ result.should_not be_nil
140
+ result.should == response_body
141
+ end
142
+
143
+ it "returns a list of unscheduled maintenance periods for a check on an entity" do
144
+ req = stub_request(:get, "http://#{server}/unscheduled_maintenances").
145
+ with(:query => {:check => {entity => check}}).
146
+ to_return(:body => response)
147
+
148
+ result = Flapjack::Diner.unscheduled_maintenances(entity, :check => check)
149
+ req.should have_been_requested
150
+ result.should_not be_nil
151
+ result.should == response_body
152
+ end
153
+
154
+ it "returns a list of unscheduled maintenance periods for a bulk query" do
155
+ req = stub_request(:get, "http://#{server}/unscheduled_maintenances").
156
+ with(:query => {:entity => 'abc.net', :check => {'def.org' => 'ping'}}).
157
+ to_return(:body => response)
158
+
159
+ result = Flapjack::Diner.bulk_unscheduled_maintenances(:entity => 'abc.net', :check => {'def.org' => 'ping'})
160
+ req.should have_been_requested
161
+ result.should_not be_nil
162
+ result.should == response_body
163
+ end
164
+
165
+ it "returns a list of outages for all checks on an entity" do
166
+ req = stub_request(:get, "http://#{server}/outages").
167
+ with(:query => {:entity => entity}).
168
+ to_return(:body => response)
169
+
170
+ result = Flapjack::Diner.outages(entity)
171
+ req.should have_been_requested
172
+ result.should_not be_nil
173
+ result.should == response_body
174
+ end
175
+
176
+ it "returns a list of outages for a check on an entity" do
177
+ req = stub_request(:get, "http://#{server}/outages").
178
+ with(:query => {:check => {entity => check}}).
179
+ to_return(:body => response)
180
+
181
+ result = Flapjack::Diner.outages(entity, :check => check)
182
+ req.should have_been_requested
183
+ result.should_not be_nil
184
+ result.should == response_body
185
+ end
186
+
187
+ it "returns a list of outages for a bulk query" do
188
+ req = stub_request(:get, "http://#{server}/outages").
189
+ with(:query => {:entity => 'abc.net', :check => {'def.org' => 'ping'}}).
190
+ to_return(:body => response)
191
+
192
+ result = Flapjack::Diner.bulk_outages(:entity => 'abc.net', :check => {'def.org' => 'ping'})
193
+ req.should have_been_requested
194
+ result.should_not be_nil
195
+ result.should == response_body
196
+ end
197
+
198
+ it "returns a list of downtimes for all checks on an entity" do
199
+ req = stub_request(:get, "http://#{server}/downtime").
200
+ with(:query => {:entity => entity}).
201
+ to_return(:body => response)
202
+
203
+ result = Flapjack::Diner.downtime(entity)
204
+ req.should have_been_requested
205
+ result.should_not be_nil
206
+ result.should == response_body
207
+ end
208
+
209
+ it "returns a list of downtimes for all checks on an entity between two times" do
210
+ start = Time.iso8601('2011-08-01T00:00:00+10:00')
211
+ finish = Time.iso8601('2011-08-31T00:00:00+10:00')
212
+
213
+ req = stub_request(:get, "http://#{server}/downtime").
214
+ with(:query => {:entity => entity, :start_time => start.iso8601, :end_time => finish.iso8601}).
215
+ to_return(:body => response)
216
+
217
+ result = Flapjack::Diner.downtime(entity, :start_time => start, :end_time => finish)
218
+ req.should have_been_requested
219
+ result.should_not be_nil
220
+ result.should == response_body
221
+ end
222
+
223
+ it "returns a list of downtimes for a check on an entity" do
224
+ req = stub_request(:get, "http://#{server}/downtime").
225
+ with(:query => {:check => {entity => check}}).
226
+ to_return(:body => response)
227
+
228
+ result = Flapjack::Diner.downtime(entity, :check => check)
229
+ req.should have_been_requested
230
+ result.should_not be_nil
231
+ result.should == response_body
232
+ end
233
+
234
+ it "returns a list of downtimes for a bulk query between two times" do
235
+ start = Time.iso8601('2011-08-01T00:00:00+10:00')
236
+ finish = Time.iso8601('2011-08-31T00:00:00+10:00')
237
+
238
+ req = stub_request(:get, "http://#{server}/downtime").
239
+ with(:query => {:entity => 'abc.net', :check => {'def.org' => 'ping'},
240
+ :start_time => start.iso8601, :end_time => finish.iso8601}).
241
+ to_return(:body => response)
242
+
243
+ result = Flapjack::Diner.bulk_downtime(:entity => 'abc.net', :check => {'def.org' => 'ping'},
244
+ :start_time => start, :end_time => finish)
245
+ req.should have_been_requested
246
+ result.should_not be_nil
247
+ result.should == response_body
248
+ end
249
+
250
+ it "acknowledges a check's state for an entity" do
251
+ req = stub_request(:post, "http://#{server}/acknowledgements").with(
252
+ :body => {:check => {entity => check}, :summary => 'dealing with it'}).to_return(
253
+ :status => 204)
254
+
255
+ result = Flapjack::Diner.acknowledge!(entity, check, :summary => 'dealing with it')
256
+ req.should have_been_requested
257
+ result.should be_true
258
+ end
259
+
260
+ it "acknowledges all checks on an entity" do
261
+ req = stub_request(:post, "http://#{server}/acknowledgements").with(
262
+ :body => {:entity => entity, :summary => 'dealing with it'},
263
+ :headers => {'Content-Type' => 'application/json'}).to_return(
264
+ :status => 204)
265
+
266
+ result = Flapjack::Diner.bulk_acknowledge!(:entity => entity, :summary => 'dealing with it')
267
+ req.should have_been_requested
268
+ result.should be_true
269
+ end
270
+
271
+ it "acknowledges checks from multiple entities" do
272
+ req = stub_request(:post, "http://#{server}/acknowledgements").with(
273
+ :body => {:entity => [entity, 'lmn.net'], :summary => 'dealing with it'}).to_return(
274
+ :status => 204)
275
+
276
+ result = Flapjack::Diner.bulk_acknowledge!(:entity => [entity, 'lmn.net'], :summary => 'dealing with it')
277
+ req.should have_been_requested
278
+ result.should be_true
279
+ end
280
+
281
+ it "generates test notifications for a check on an entity" do
282
+ req = stub_request(:post, "http://#{server}/test_notifications").with(
283
+ :body => {:check => {entity => check}, :summary => 'testing notifications'}).to_return(
284
+ :status => 204)
285
+
286
+ result = Flapjack::Diner.test_notifications!(entity, check, :summary => 'testing notifications')
287
+ req.should have_been_requested
288
+ result.should be_true
289
+ end
290
+
291
+ it "generates test notifications for all checks on an entity" do
292
+ req = stub_request(:post, "http://#{server}/test_notifications").with(
293
+ :body => {:entity => entity, :summary => 'testing notifications'}).to_return(
294
+ :status => 204)
295
+
296
+ result = Flapjack::Diner.bulk_test_notifications!(:entity => entity, :summary => 'testing notifications')
297
+ req.should have_been_requested
298
+ result.should be_true
299
+ end
300
+
301
+ it "generates test notifications for checks from multiple entities" do
302
+ req = stub_request(:post, "http://#{server}/test_notifications").with(
303
+ :body => {:entity => [entity, 'lmn.net'], :summary => 'testing notifications'}).to_return(
304
+ :status => 204)
305
+
306
+ result = Flapjack::Diner.bulk_test_notifications!(:entity => [entity, 'lmn.net'], :summary => 'testing notifications')
307
+ req.should have_been_requested
308
+ result.should be_true
309
+ end
310
+
311
+ it "creates a scheduled maintenance period for an entity" do
312
+ start_time = Time.now
313
+ duration = 60 * 30 # in seconds, so 30 minutes
314
+ summary = "fixing everything"
315
+
316
+ req = stub_request(:post, "http://#{server}/scheduled_maintenances").
317
+ with(:body => {:check => {entity => check}, :start_time => start_time.iso8601,
318
+ :duration => duration, :summary => summary},
319
+ :headers => {'Content-Type'=>'application/json'}).
320
+ to_return(:status => 204)
321
+
322
+ result = Flapjack::Diner.create_scheduled_maintenance!(entity, check,
323
+ :start_time => start_time, :duration => duration, :summary => summary)
324
+ req.should have_been_requested
325
+ result.should be_true
326
+ end
327
+
328
+ it "creates scheduled maintenance periods for all checks on an entity" do
329
+ start_time = Time.now
330
+ duration = 60 * 30 # in seconds, so 30 minutes
331
+ summary = "fixing everything"
332
+
333
+ req = stub_request(:post, "http://#{server}/scheduled_maintenances").
334
+ with(:body => {:entity => entity, :start_time => start_time.iso8601,
335
+ :duration => duration, :summary => summary},
336
+ :headers => {'Content-Type'=>'application/json'}).
337
+ to_return(:status => 204)
338
+
339
+ result = Flapjack::Diner.bulk_create_scheduled_maintenance!(:entity => entity,
340
+ :start_time => start_time, :duration => duration, :summary => summary)
341
+ req.should have_been_requested
342
+ result.should be_true
343
+ end
344
+
345
+ it "creates scheduled maintenance periods for checks from multiple entities" do
346
+ start_time = Time.now
347
+ duration = 60 * 30 # in seconds, so 30 minutes
348
+ summary = "fixing everything"
349
+
350
+ req = stub_request(:post, "http://#{server}/scheduled_maintenances").
351
+ with(:body => {:check => {entity => 'ping', 'pqr.org' => 'ssh'}, :start_time => start_time.iso8601,
352
+ :duration => duration, :summary => summary},
353
+ :headers => {'Content-Type'=>'application/json'}).
354
+ to_return(:status => 204)
355
+
356
+ result = Flapjack::Diner.bulk_create_scheduled_maintenance!(:check => {entity => 'ping', 'pqr.org' => 'ssh'},
357
+ :start_time => start_time, :duration => duration, :summary => summary)
358
+ req.should have_been_requested
359
+ result.should be_true
360
+ end
361
+
362
+ it "deletes a scheduled maintenance period for a check on an entity" do
363
+ start_time = Time.now
364
+
365
+ req = stub_request(:delete, "http://#{server}/scheduled_maintenances").
366
+ with(:body => {:check => {entity => check}, :start_time => start_time.iso8601},
367
+ :headers => {'Content-Type'=>'application/json'}).
368
+ to_return(:status => 204)
369
+
370
+ result = Flapjack::Diner.delete_scheduled_maintenance!(entity, check,
371
+ :start_time => start_time)
372
+ req.should have_been_requested
373
+ result.should be_true
374
+ end
375
+
376
+ it "deletes scheduled maintenance periods for all checks on an entity" do
377
+ start_time = Time.now
378
+
379
+ req = stub_request(:delete, "http://#{server}/scheduled_maintenances").
380
+ with(:body => {:entity => entity, :start_time => start_time.iso8601},
381
+ :headers => {'Content-Type'=>'application/json'}).
382
+ to_return(:status => 204)
383
+
384
+ result = Flapjack::Diner.bulk_delete_scheduled_maintenance!(:entity => entity,
385
+ :start_time => start_time)
386
+ req.should have_been_requested
387
+ result.should be_true
388
+ end
389
+
390
+ it "deletes scheduled maintenance periods for checks from multiple entities" do
391
+ start_time = Time.now
392
+
393
+ req = stub_request(:delete, "http://#{server}/scheduled_maintenances").
394
+ with(:body => {:check => {entity => 'ping', 'pqr.org' => 'ssh'},
395
+ :start_time => start_time.iso8601},
396
+ :headers => {'Content-Type'=>'application/json'}).
397
+ to_return(:status => 204)
398
+
399
+ result = Flapjack::Diner.bulk_delete_scheduled_maintenance!(:check => {entity => 'ping', 'pqr.org' => 'ssh'},
400
+ :start_time => start_time)
401
+ req.should have_been_requested
402
+ result.should be_true
403
+ end
404
+
405
+ it "deletes an unscheduled maintenance period for a check on an entity" do
406
+ end_time = Time.now
407
+
408
+ req = stub_request(:delete, "http://#{server}/unscheduled_maintenances").
409
+ with(:body => {:check => {entity => check}, :end_time => end_time.iso8601},
410
+ :headers => {'Content-Type'=>'application/json'}).
411
+ to_return(:status => 204)
412
+
413
+ result = Flapjack::Diner.delete_unscheduled_maintenance!(entity, check,
414
+ :end_time => end_time)
415
+ req.should have_been_requested
416
+ result.should be_true
417
+ end
418
+
419
+ it "deletes scheduled maintenance periods for all checks on an entity" do
420
+ end_time = Time.now
421
+
422
+ req = stub_request(:delete, "http://#{server}/unscheduled_maintenances").
423
+ with(:body => {:entity => entity, :end_time => end_time.iso8601},
424
+ :headers => {'Content-Type'=>'application/json'}).
425
+ to_return(:status => 204)
426
+
427
+ result = Flapjack::Diner.bulk_delete_unscheduled_maintenance!(:entity => entity,
428
+ :end_time => end_time)
429
+ req.should have_been_requested
430
+ result.should be_true
431
+ end
432
+
433
+ it "deletes scheduled maintenance periods for checks from multiple entities" do
434
+ end_time = Time.now
435
+
436
+ req = stub_request(:delete, "http://#{server}/unscheduled_maintenances").
437
+ with(:body => {:check => {entity => 'ping', 'pqr.org' => 'ssh'},
438
+ :end_time => end_time.iso8601},
439
+ :headers => {'Content-Type'=>'application/json'}).
440
+ to_return(:status => 204)
441
+
442
+ result = Flapjack::Diner.bulk_delete_unscheduled_maintenance!(:check => {entity => 'ping', 'pqr.org' => 'ssh'},
443
+ :end_time => end_time)
444
+ req.should have_been_requested
445
+ result.should be_true
446
+ end
447
+
448
+
449
+ it "returns a list of contacts" do
450
+ req = stub_request(:get, "http://#{server}/contacts").to_return(
451
+ :body => response)
452
+
453
+ result = Flapjack::Diner.contacts
454
+ req.should have_been_requested
455
+ result.should_not be_nil
456
+ result.should == response_body
457
+ end
458
+
459
+ it "returns a single contact" do
460
+ contact_id = '21'
461
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}").to_return(
462
+ :body => response)
463
+
464
+ result = Flapjack::Diner.contact(contact_id)
465
+ req.should have_been_requested
466
+ result.should_not be_nil
467
+ result.should == response_body
468
+ end
469
+
470
+ it "returns notification rules for a contact" do
471
+ contact_id = '21'
472
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/notification_rules").to_return(
473
+ :body => response)
474
+
475
+ result = Flapjack::Diner.notification_rules(contact_id)
476
+ req.should have_been_requested
477
+ result.should_not be_nil
478
+ result.should == response_body
479
+ end
480
+
481
+ it "returns a single notification rule" do
482
+ rule_id = '00001'
483
+ req = stub_request(:get, "http://#{server}/notification_rules/#{rule_id}").
484
+ to_return(:body => response)
485
+
486
+ result = Flapjack::Diner.notification_rule(rule_id)
487
+ req.should have_been_requested
488
+ result.should_not be_nil
489
+ result.should == response_body
490
+ end
491
+
492
+ it "creates a notification rule" do
493
+ rule_result = rule_data.merge('id' => '00001')
494
+
495
+ req = stub_request(:post, "http://#{server}/notification_rules").
496
+ with(:body => rule_data,
497
+ :headers => {'Content-Type'=>'application/json'}).
498
+ to_return(:body => rule_result.to_json)
499
+
500
+ result = Flapjack::Diner.create_notification_rule!(rule_data)
501
+ req.should have_been_requested
502
+ result.should == rule_result
503
+ end
504
+
505
+ it "updates a notification rule" do
506
+ rule_id = '00001'
507
+
508
+ rule_data_with_id = rule_data.merge('id' => rule_id)
509
+
510
+ req = stub_request(:put, "http://#{server}/notification_rules/#{rule_id}").
511
+ with(:body => rule_data_with_id,
512
+ :headers => {'Content-Type'=>'application/json'}).
513
+ to_return(:body => rule_data_with_id.to_json)
514
+
515
+ result = Flapjack::Diner.update_notification_rule!(rule_id, rule_data_with_id)
516
+ req.should have_been_requested
517
+ result.should == rule_data_with_id
518
+ end
519
+
520
+ it "deletes a notification rule" do
521
+ rule_id = '00001'
522
+ req = stub_request(:delete, "http://#{server}/notification_rules/#{rule_id}").to_return(
523
+ :status => 204)
524
+
525
+ result = Flapjack::Diner.delete_notification_rule!(rule_id)
526
+ req.should have_been_requested
527
+ result.should be_true
528
+ end
529
+
530
+ it "gets a list of entity tags" do
531
+ req = stub_request(:get, "http://#{server}/entities/#{entity}/tags").to_return(
532
+ :body => ['web', 'app'].to_json)
533
+
534
+ result = Flapjack::Diner.entity_tags(entity)
535
+ req.should have_been_requested
536
+ result.should == ['web', 'app']
537
+ end
538
+
539
+ it "adds tags to an entity" do
540
+ req = stub_request(:post, "http://#{server}/entities/#{entity}/tags").
541
+ with(:body => {:tag => ['web', 'app']},
542
+ :headers => {'Content-Type'=>'application/json'}).
543
+ to_return(:body => ['web', 'app'].to_json)
544
+
545
+ result = Flapjack::Diner.add_entity_tags!(entity, 'web', 'app')
546
+ req.should have_been_requested
547
+ result.should == ['web', 'app']
548
+ end
549
+
550
+ it "deletes tags from an entity" do
551
+ req = stub_request(:delete, "http://#{server}/entities/#{entity}/tags").
552
+ with(:body => {:tag => ['web']},
553
+ :headers => {'Content-Type'=>'application/json'}).
554
+ to_return(:status => 204)
555
+
556
+ result = Flapjack::Diner.delete_entity_tags!(entity, 'web')
557
+ req.should have_been_requested
558
+ result.should be_true
559
+ end
560
+
561
+ it "gets a list of contact tags" do
562
+ contact_id = 21
563
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/tags").to_return(
564
+ :body => ['user', 'admin'].to_json)
565
+
566
+ result = Flapjack::Diner.contact_tags(contact_id)
567
+ req.should have_been_requested
568
+ result.should == ['user', 'admin']
569
+ end
570
+
571
+ it "gets tags for a contact's linked entities" do
572
+ contact_id = 21
573
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/entity_tags").to_return(
574
+ :body => {'entity_1' => ['web', 'app']}.to_json)
575
+
576
+ result = Flapjack::Diner.contact_entitytags(contact_id)
577
+ req.should have_been_requested
578
+ result.should == {'entity_1' => ['web', 'app']}
579
+ end
580
+
581
+ it "adds tags to a contact's linked entities" do
582
+ contact_id = 21
583
+ req = stub_request(:post, "http://#{server}/contacts/#{contact_id}/entity_tags").
584
+ with(:body => {:entity => {'entity_1' => ['web', 'app']}},
585
+ :headers => {'Content-Type'=>'application/json'}).
586
+ to_return(:body => {'entity_1' => ['web', 'app']}.to_json)
587
+
588
+ result = Flapjack::Diner.add_contact_entitytags!(contact_id, {'entity_1' => ['web', 'app']})
589
+ req.should have_been_requested
590
+ result.should == {'entity_1' => ['web', 'app']}
591
+ end
592
+
593
+ it "deletes tags from a contact's linked entities" do
594
+ contact_id = 21
595
+ req = stub_request(:delete, "http://#{server}/contacts/#{contact_id}/entity_tags").
596
+ with(:body => {:entity => {'entity_1' => ['web', 'app']}},
597
+ :headers => {'Content-Type'=>'application/json'}).
598
+ to_return(:status => 204)
599
+
600
+ result = Flapjack::Diner.delete_contact_entitytags!(contact_id, {'entity_1' => ['web', 'app']})
601
+ req.should have_been_requested
602
+ result.should be_true
603
+ end
604
+
605
+ it "adds tags to a contact" do
606
+ contact_id = 21
607
+ req = stub_request(:post, "http://#{server}/contacts/#{contact_id}/tags").
608
+ with(:body => {:tag => ['admin', 'user']},
609
+ :headers => {'Content-Type'=>'application/json'}).
610
+ to_return(:body => ['admin', 'user'].to_json)
611
+
612
+ result = Flapjack::Diner.add_contact_tags!(contact_id, 'admin', 'user')
613
+ req.should have_been_requested
614
+ result.should == ['admin', 'user']
615
+ end
616
+
617
+ it "deletes tags from a contact" do
618
+ contact_id = 21
619
+ req = stub_request(:delete, "http://#{server}/contacts/#{contact_id}/tags").
620
+ with(:body => {:tag => ['admin']},
621
+ :headers => {'Content-Type'=>'application/json'}).
622
+ to_return(:status => 204)
623
+
624
+ result = Flapjack::Diner.delete_contact_tags!(contact_id, 'admin')
625
+ req.should have_been_requested
626
+ result.should be_true
627
+ end
628
+
629
+ it "returns a list of a contact's notification media values" do
630
+ contact_id = '21'
631
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/media").to_return(
632
+ :body => response)
633
+
634
+ result = Flapjack::Diner.contact_media(contact_id)
635
+ req.should have_been_requested
636
+ result.should_not be_nil
637
+ result.should == response_body
638
+ end
639
+
640
+ it "returns the values for a contact's notification medium" do
641
+ contact_id = '21'
642
+ media = 'sms'
643
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/media/#{media}").to_return(
644
+ :body => response)
645
+
646
+ result = Flapjack::Diner.contact_medium(contact_id, media)
647
+ req.should have_been_requested
648
+ result.should_not be_nil
649
+ result.should == response_body
650
+ end
651
+
652
+ it "updates a contact's notification medium" do
653
+ contact_id = '21'
654
+ media_type = 'sms'
655
+ media_data = {"address" => "dmitri@example.com",
656
+ "interval" => 900}
657
+
658
+ req = stub_request(:put, "http://#{server}/contacts/#{contact_id}/media/#{media_type}").with(
659
+ :body => media_data).to_return(:body => media_data.to_json)
660
+
661
+ result = Flapjack::Diner.update_contact_medium!(contact_id, media_type, media_data)
662
+ req.should have_been_requested
663
+ result.should == media_data
664
+ end
665
+
666
+ it "deletes a contact's notification medium" do
667
+ contact_id = '21'
668
+ media = 'sms'
669
+ req = stub_request(:delete, "http://#{server}/contacts/#{contact_id}/media/#{media}").to_return(
670
+ :status => 204)
671
+
672
+ result = Flapjack::Diner.delete_contact_medium!(contact_id, media)
673
+ req.should have_been_requested
674
+ result.should be_true
675
+ end
676
+
677
+ it "returns a contact's timezone" do
678
+ contact_id = '21'
679
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/timezone").to_return(
680
+ :body => response)
681
+
682
+ result = Flapjack::Diner.contact_timezone(contact_id)
683
+ req.should have_been_requested
684
+ result.should_not be_nil
685
+ result.should == response_body
686
+ end
687
+
688
+ it "updates a contact's timezone" do
689
+ contact_id = '21'
690
+ timezone_data = {'timezone' => "Australia/Perth"}
691
+
692
+ req = stub_request(:put, "http://#{server}/contacts/#{contact_id}/timezone").with(
693
+ :body => timezone_data).to_return(:body => timezone_data.to_json)
694
+
695
+ result = Flapjack::Diner.update_contact_timezone!(contact_id, timezone_data['timezone'])
696
+ req.should have_been_requested
697
+ result.should == timezone_data
698
+ end
699
+
700
+ it "deletes a contact's timezone" do
701
+ contact_id = '21'
702
+ req = stub_request(:delete, "http://#{server}/contacts/#{contact_id}/timezone").to_return(
703
+ :status => 204)
704
+
705
+ result = Flapjack::Diner.delete_contact_timezone!(contact_id)
706
+ req.should have_been_requested
707
+ result.should be_true
708
+ end
709
+
710
+ it "returns nil with last_error available when requesting the timezone for a non existant contact" do
711
+ contact_id = 'jkfldsj'
712
+ req = stub_request(:get, "http://#{server}/contacts/#{contact_id}/timezone").to_return(
713
+ :body => '{"errors": ["Not found"]}', :status => 404)
714
+
715
+ result = Flapjack::Diner.contact_timezone(contact_id)
716
+ last_error = Flapjack::Diner.last_error
717
+ req.should have_been_requested
718
+ result.should be_nil
719
+ last_error.should_not be_nil
720
+ end
721
+
722
+ context "logging" do
723
+
724
+ let(:logger) { mock('logger') }
725
+
726
+ before do
727
+ Flapjack::Diner.logger = logger
728
+ end
729
+
730
+ it "logs a GET request without a path" do
731
+ req = stub_request(:get, "http://#{server}/entities").to_return(
732
+ :body => response)
733
+
734
+ logger.should_receive(:info).with("GET http://#{server}/entities")
735
+ logger.should_receive(:info).with(" Response Code: 200")
736
+ logger.should_receive(:info).with(" Response Body: #{response}")
737
+
738
+ result = Flapjack::Diner.entities
739
+ req.should have_been_requested
740
+ result.should_not be_nil
741
+ result.should == response_body
742
+ end
743
+
744
+ it "logs a GET request with a path" do
745
+ req = stub_request(:get, "http://#{server}/checks/#{entity}").to_return(
746
+ :body => response)
747
+
748
+ logger.should_receive(:info).with("GET http://#{server}/checks/#{entity}")
749
+ logger.should_receive(:info).with(" Response Code: 200")
750
+ logger.should_receive(:info).with(" Response Body: #{response}")
751
+
752
+ result = Flapjack::Diner.checks(entity)
753
+ req.should have_been_requested
754
+ result.should_not be_nil
755
+ result.should == response_body
756
+ end
757
+
758
+ it "logs a POST request" do
759
+ req = stub_request(:post, "http://#{server}/acknowledgements").
760
+ with(:body => {:check => {entity => check}, :summary => 'dealing with it'},
761
+ :headers => {'Content-Type'=>'application/json'}).
762
+ to_return(:status => 204)
763
+ logger.should_receive(:info).with("POST http://#{server}/acknowledgements\n" +
764
+ " Params: {:summary=>\"dealing with it\", :check=>{\"ex-abcd-data-17.example.com\"=>\"ping\"}}")
765
+ logger.should_receive(:info).with(" Response Code: 204")
766
+
767
+ result = Flapjack::Diner.acknowledge!(entity, check, :summary => 'dealing with it')
768
+ req.should have_been_requested
769
+ result.should be_true
770
+ end
771
+
772
+ it "logs a JSON put request" do
773
+ contact_id = '21'
774
+ timezone_data = {:timezone => "Australia/Perth"}
775
+
776
+ req = stub_request(:put, "http://#{server}/contacts/#{contact_id}/timezone").with(
777
+ :body => timezone_data).to_return(:body => timezone_data.to_json, :status => [200, ' OK'])
778
+
779
+ logger.should_receive(:info).
780
+ with("PUT http://#{server}/contacts/#{contact_id}/timezone\n Params: #{timezone_data.inspect}")
781
+ logger.should_receive(:info).with(" Response Code: 200 OK")
782
+ logger.should_receive(:info).with(" Response Body: #{timezone_data.to_json}")
783
+
784
+ result = Flapjack::Diner.update_contact_timezone!(contact_id, timezone_data[:timezone])
785
+ req.should have_been_requested
786
+ result.should == {'timezone' => "Australia/Perth"}
787
+ end
788
+
789
+ it "logs a DELETE request" do
790
+ contact_id = '21'
791
+ req = stub_request(:delete, "http://#{server}/contacts/#{contact_id}/timezone").to_return(
792
+ :status => 204)
793
+
794
+ logger.should_receive(:info).with("DELETE http://#{server}/contacts/#{contact_id}/timezone")
795
+ logger.should_receive(:info).with(" Response Code: 204")
796
+
797
+ result = Flapjack::Diner.delete_contact_timezone!(contact_id)
798
+ req.should have_been_requested
799
+ result.should be_true
800
+ end
801
+
802
+ end
803
+
804
+ context "problems" do
805
+
806
+ it "raises an exception on network failure" do
807
+ req = stub_request(:get, "http://#{server}/entities").to_timeout
808
+
809
+ expect {
810
+ Flapjack::Diner.entities
811
+ }.to raise_error
812
+ req.should have_been_requested
813
+ end
814
+
815
+ it "raises an exception on invalid JSON data" do
816
+ req = stub_request(:get, "http://#{server}/entities").to_return(
817
+ :body => "{")
818
+
819
+ expect {
820
+ Flapjack::Diner.entities
821
+ }.to raise_error
822
+ req.should have_been_requested
823
+ end
824
+
825
+ it "raises an exception if a required argument is not provided" do
826
+ req = stub_request(:get, /http:\/\/#{server}\/*/)
827
+
828
+ expect {
829
+ Flapjack::Diner.check_status(entity, nil)
830
+ }.to raise_error
831
+ req.should_not have_been_requested
832
+ end
833
+
834
+ it "raises an exception if bulk queries don't have entity or check arguments" do
835
+ req = stub_request(:get, /http:\/\/#{server}\/*/)
836
+
837
+ expect {
838
+ Flapjack::Diner.bulk_downtime({})
839
+ }.to raise_error
840
+ req.should_not have_been_requested
841
+ end
842
+
843
+ it "raises an exception if bulk queries have invalid entity arguments" do
844
+ req = stub_request(:get, /http:\/\/#{server}\/*/)
845
+
846
+ expect {
847
+ Flapjack::Diner.bulk_scheduled_maintenances(:entity => 23)
848
+ }.to raise_error
849
+ req.should_not have_been_requested
850
+ end
851
+
852
+ it "raises an exception if bulk queries have invalid check arguments" do
853
+ req = stub_request(:get, /http:\/\/#{server}\/*/)
854
+
855
+ expect {
856
+ Flapjack::Diner.bulk_outages(:check => {'abc.com' => ['ping', 5]})
857
+ }.to raise_error
858
+ req.should_not have_been_requested
859
+ end
860
+
861
+ it "raises an exception if a time argument is provided with the wrong data type" do
862
+ start_str = '2011-08-01T00:00:00+10:00'
863
+ finish_str = '2011-08-31T00:00:00+10:00'
864
+
865
+ start = Time.iso8601(start_str)
866
+
867
+ req = stub_request(:get, /http:\/\/#{server}\/*/)
868
+
869
+ expect {
870
+ Flapjack::Diner.downtime(entity, :start_time => start, :end_time => finish_str)
871
+ }.to raise_error
872
+ req.should_not have_been_requested
873
+ end
874
+
875
+ end
876
+
877
+ end