flapjack-diner 0.12

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.
@@ -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