flapjack 0.6.35 → 0.6.36

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.
data/Gemfile CHANGED
@@ -6,10 +6,11 @@ group :test do
6
6
  gem 'rspec'
7
7
  gem 'cucumber'
8
8
  gem 'delorean'
9
- gem 'rack-test'
9
+ gem 'rack-test', :git => "git://github.com/brynary/rack-test.git", :ref => "8153c07"
10
10
  gem 'resque_spec'
11
11
  gem 'webmock'
12
12
  gem 'guard'
13
+ gem 'rb-fsevent', '~> 0.9.1'
13
14
  gem 'guard-rspec'
14
15
  gem 'guard-cucumber'
15
16
  gem 'fuubar'
@@ -3,8 +3,8 @@
3
3
  # A HTTP-based API server, which provides queries to determine the status of
4
4
  # entities and the checks that are reported against them.
5
5
  #
6
- # There's a matching flapjack-diner gem which consumes data from this API
7
- # (currently at https://github.com/ali-graham/flapjack-diner -- this will change.)
6
+ # There's a matching flapjack-diner gem at https://github.com/flpjck/flapjack-diner
7
+ # which consumes data from this API.
8
8
 
9
9
  require 'time'
10
10
 
@@ -15,9 +15,34 @@ require 'flapjack/pikelet'
15
15
 
16
16
  require 'flapjack/api/entity_presenter'
17
17
 
18
+ require 'flapjack/data/contact'
18
19
  require 'flapjack/data/entity'
19
20
  require 'flapjack/data/entity_check'
20
21
 
22
+ # from https://github.com/sinatra/sinatra/issues/501
23
+ # TODO move to its own file
24
+ module Rack
25
+ class JsonParamsParser < Struct.new(:app)
26
+ def call(env)
27
+ if env['rack.input'] and not input_parsed?(env) and type_match?(env)
28
+ env['rack.request.form_input'] = env['rack.input']
29
+ data = env['rack.input'].read
30
+ env['rack.request.form_hash'] = data.empty?? {} : JSON.parse(data)
31
+ end
32
+ app.call(env)
33
+ end
34
+
35
+ def input_parsed? env
36
+ env['rack.request.form_input'].eql? env['rack.input']
37
+ end
38
+
39
+ def type_match? env
40
+ type = env['CONTENT_TYPE'] and
41
+ type.split(/\s*[;,]\s*/, 2).first.downcase == 'application/json'
42
+ end
43
+ end
44
+ end
45
+
21
46
  module Flapjack
22
47
 
23
48
  class API < Sinatra::Base
@@ -27,14 +52,18 @@ module Flapjack
27
52
  rescue_exception = Proc.new { |env, exception|
28
53
  logger.error exception.message
29
54
  logger.error exception.backtrace.join("\n")
30
- [503, {}, {:status => 503, :reason => exception.message}.to_json]
55
+ [503, {}, {:errors => [exception.message]}.to_json]
31
56
  }
32
57
 
33
58
  use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
34
59
  end
35
60
  use Rack::MethodOverride
61
+ use Rack::JsonParamsParser
62
+
36
63
  extend Flapjack::Pikelet
37
64
 
65
+ set :show_exceptions, 'development'.eql?(FLAPJACK_ENV)
66
+
38
67
  before do
39
68
  # will only initialise the first time it's run
40
69
  Flapjack::API.bootstrap
@@ -226,8 +255,61 @@ module Flapjack
226
255
  status 204
227
256
  end
228
257
 
258
+ post '/entities' do
259
+ pass unless 'application/json'.eql?(request.content_type)
260
+ content_type :json
261
+
262
+ errors = []
263
+ ret = nil
264
+
265
+ entities = params[:entities]
266
+ if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
267
+ entities.each do |entity|
268
+ unless entity['id']
269
+ errors << "Entity not imported as it has no id: #{entity.inspect}"
270
+ next
271
+ end
272
+ Flapjack::Data::Entity.add(entity, :redis => @@redis)
273
+ end
274
+ ret = 200
275
+ else
276
+ ret = 403
277
+ errors << "No valid entities were submitted"
278
+ end
279
+ errors.empty? ? ret : [ret, {}, {:errors => [errors]}.to_json]
280
+ end
281
+
282
+ post '/contacts' do
283
+ begin
284
+ pass unless 'application/json'.eql?(request.content_type)
285
+ content_type :json
286
+
287
+ errors = []
288
+ ret = nil
289
+
290
+ contacts = params[:contacts]
291
+ if contacts && contacts.is_a?(Enumerable) && contacts.any? {|c| !c['id'].nil?}
292
+ Flapjack::Data::Contact.delete_all
293
+ contacts.each do |contact|
294
+ unless contact['id']
295
+ logger.warn "Contact not imported as it has no id: #{contact.inspect}"
296
+ next
297
+ end
298
+ Flapjack::Data::Contact.add(contact, :redis => @@redis)
299
+ end
300
+ ret = 200
301
+ else
302
+ ret = 403
303
+ errors << "No valid contacts were submitted"
304
+ end
305
+ errors.empty? ? ret : [ret, {}, {:errors => [errors]}.to_json]
306
+ rescue Exception => e
307
+ puts e.message
308
+ end
309
+ end
310
+
229
311
  not_found do
230
- [404, {}, {:status => 404, :reason => "Not found"}.to_json]
312
+ [404, {}, {:errors => ["Not found"]}.to_json]
231
313
  end
232
314
 
233
315
  private
@@ -25,6 +25,21 @@ module Flapjack
25
25
  union
26
26
  end
27
27
 
28
+ def self.delete_all(options = {})
29
+ raise "Redis connection not set" unless redis = options[:redis]
30
+
31
+ contacts = redis.keys('contact:*')
32
+
33
+ contacts.each do |c|
34
+ c =~ /^contact:(\d+)$/
35
+ id = $1
36
+
37
+ redis.del("contact:#{id}")
38
+ redis.del("contact_media:#{id}")
39
+ redis.del("contact_pagerduty:#{id}")
40
+ end
41
+ end
42
+
28
43
  # NB: should probably be called in the context of a Redis multi block; not doing so
29
44
  # here as calling classes may well be adding/updating multiple records in the one
30
45
  # operation
@@ -34,9 +49,9 @@ module Flapjack
34
49
  redis.del("contact:#{contact['id']}")
35
50
  redis.del("contact_media:#{contact['id']}")
36
51
  redis.del("contact_pagerduty:#{contact['id']}")
37
- redis.hset("contact:#{contact['id']}", 'first_name', contact['first_name'])
38
- redis.hset("contact:#{contact['id']}", 'last_name', contact['last_name'])
39
- redis.hset("contact:#{contact['id']}", 'email', contact['email'])
52
+ ['first_name', 'last_name', 'email'].each do |field|
53
+ redis.hset("contact:#{contact['id']}", field, contact[field])
54
+ end
40
55
  contact['media'].each_pair {|medium, address|
41
56
  case medium
42
57
  when 'pagerduty'
@@ -60,6 +60,17 @@ module Flapjack
60
60
  @redis.exists("#{@key}:scheduled_maintenance")
61
61
  end
62
62
 
63
+ # return data about current maintenance (scheduled or unscheduled, as specified)
64
+ def current_maintenance(opts)
65
+ sched = opts[:scheduled] ? 'scheduled' : 'unscheduled'
66
+ ts = @redis.get("#{@key}:#{sched}_maintenance")
67
+ return unless ts
68
+ {:start_time => ts.to_i,
69
+ :duration => @redis.zscore("#{@key}:#{sched}_maintenances", ts),
70
+ :summary => @redis.get("#{@key}:#{ts}:#{sched}_maintenance:summary"),
71
+ }
72
+ end
73
+
63
74
  # creates, or modifies, an event object and adds it to the events list in redis
64
75
  # 'type' => 'service',
65
76
  # 'state' => state,
@@ -136,7 +147,28 @@ module Flapjack
136
147
  @redis.zadd("#{@key}:sorted_scheduled_maintenance_timestamps", start_time, start_time)
137
148
 
138
149
  # scheduled maintenance periods have changed, revalidate
139
- update_scheduled_maintenance(:revalidate => true)
150
+ update_current_scheduled_maintenance(:revalidate => true)
151
+ end
152
+
153
+ # change the end time of a scheduled maintenance (including when one is current)
154
+ def update_scheduled_maintenance(start_time, patches = {})
155
+
156
+ # check if there is such a scheduled maintenance period
157
+ old_duration = @redis.zscore("#{@key}:scheduled_maintenances", start_time)
158
+ raise ArgumentError, 'no such scheduled maintenance period can be found' unless old_duration
159
+ raise ArgumentError, 'no handled patches have been supplied' unless patches[:end_time]
160
+
161
+ if patches[:end_time]
162
+ end_time = patches[:end_time]
163
+ raise ArgumentError unless end_time > start_time
164
+ old_end_time = start_time + old_duration
165
+ duration = end_time - start_time
166
+ @redis.zadd("#{@key}:scheduled_maintenances", duration, start_time)
167
+ end
168
+
169
+ # scheduled maintenance periods have changed, revalidate
170
+ update_current_scheduled_maintenance(:revalidate => true)
171
+
140
172
  end
141
173
 
142
174
  # delete a scheduled maintenance
@@ -148,12 +180,12 @@ module Flapjack
148
180
  @redis.zremrangebyscore("#{@key}:sorted_scheduled_maintenance_timestamps", start_time, start_time)
149
181
 
150
182
  # scheduled maintenance periods have changed, revalidate
151
- update_scheduled_maintenance(:revalidate => true)
183
+ update_current_scheduled_maintenance(:revalidate => true)
152
184
  end
153
185
 
154
186
  # if not in scheduled maintenance, looks in scheduled maintenance list for a check to see if
155
187
  # current state should be set to scheduled maintenance, and sets it as appropriate
156
- def update_scheduled_maintenance(opts = {})
188
+ def update_current_scheduled_maintenance(opts = {})
157
189
  if opts[:revalidate]
158
190
  @redis.del("#{@key}:scheduled_maintenance")
159
191
  else
@@ -252,7 +284,6 @@ module Flapjack
252
284
  ln = {:problem => last_problem_notification,
253
285
  :recovery => last_recovery_notification,
254
286
  :acknowledgement => last_acknowledgement_notification }
255
- puts "***** last_notifications_of_each_type for #{@key.inspect}: #{ln.inspect}"
256
287
  ln
257
288
  end
258
289
 
@@ -161,7 +161,7 @@ module Flapjack
161
161
  result[:skip_filters] = true
162
162
  end
163
163
 
164
- entity_check.update_scheduled_maintenance
164
+ entity_check.update_current_scheduled_maintenance
165
165
 
166
166
  # Action events represent human or automated interaction with Flapjack
167
167
  when 'action'
@@ -21,7 +21,8 @@ module Flapjack
21
21
  @log.error "Filter: Acknowledgement: unknown entity for event '#{event.id}'"
22
22
  else
23
23
  ec.create_unscheduled_maintenance(:start_time => timestamp,
24
- :duration => (event.duration || (4 * 60 * 60)))
24
+ :duration => (event.duration || (4 * 60 * 60)),
25
+ :summary => event.summary)
25
26
  message = "unscheduled maintenance created for #{event.id}"
26
27
  end
27
28
  else
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.6.35"
4
+ VERSION = "0.6.36"
5
5
  end
@@ -62,9 +62,9 @@ module Flapjack
62
62
  end
63
63
 
64
64
  get '/check' do
65
- begin
65
+ #begin
66
66
  @entity = params[:entity]
67
- @check = params[:check]
67
+ @check = params[:check]
68
68
 
69
69
  entity_check = get_entity_check(@entity, @check)
70
70
  return 404 if entity_check.nil?
@@ -76,17 +76,18 @@ module Flapjack
76
76
  @check_last_change = last_change
77
77
  @check_summary = entity_check.summary
78
78
  @last_notifications = entity_check.last_notifications_of_each_type
79
- @in_scheduled_maintenance = entity_check.in_scheduled_maintenance?
80
- @in_unscheduled_maintenance = entity_check.in_unscheduled_maintenance?
81
79
  @scheduled_maintenances = entity_check.maintenances(nil, nil, :scheduled => true)
82
80
  @acknowledgement_id = entity_check.failed? ?
83
81
  entity_check.event_count_at(entity_check.last_change) : nil
84
82
 
83
+ @current_scheduled_maintenance = entity_check.current_maintenance(:scheduled => true)
84
+ @current_unscheduled_maintenance = entity_check.current_maintenance(:scheduled => false)
85
+
85
86
  haml :check
86
- rescue Exception => e
87
- puts e.message
88
- puts e.backtrace.join("\n")
89
- end
87
+ #rescue Exception => e
88
+ # puts e.message
89
+ # puts e.backtrace.join("\n")
90
+ #end
90
91
 
91
92
  end
92
93
 
@@ -105,15 +106,13 @@ module Flapjack
105
106
  ack = entity_check.create_acknowledgement('summary' => (@summary || ''),
106
107
  'acknowledgement_id' => @acknowledgement_id, 'duration' => @duration)
107
108
 
108
- # FIXME: make this a flash message on the check page and delete the acknowledge page
109
- @acknowledge_success = !!ack
110
- [201, haml(:acknowledge)]
109
+ redirect back
111
110
  end
112
111
 
113
112
  # FIXME: there is bound to be a more idiomatic / restful way of doing this
114
113
  post '/end_unscheduled_maintenance/:entity/:check' do
115
114
  @entity = params[:entity]
116
- @check = params[:check]
115
+ @check = params[:check]
117
116
 
118
117
  entity_check = get_entity_check(@entity, @check)
119
118
  return 404 if entity_check.nil?
@@ -130,7 +129,7 @@ module Flapjack
130
129
  duration = ChronicDuration.parse(params[:duration])
131
130
  summary = params[:summary]
132
131
 
133
- entity_check = get_entity_check(params[:entity], params[:check])
132
+ entity_check = get_entity_check(params[:entity], params[:check])
134
133
  return 404 if entity_check.nil?
135
134
 
136
135
  entity_check.create_scheduled_maintenance(:start_time => start_time,
@@ -139,6 +138,33 @@ module Flapjack
139
138
  redirect back
140
139
  end
141
140
 
141
+ # modify scheduled maintenance
142
+ patch '/scheduled_maintenances/:entity/:check' do
143
+
144
+ begin
145
+ puts "params: #{params.inspect}"
146
+
147
+ entity_check = get_entity_check(params[:entity], params[:check])
148
+ return 404 if entity_check.nil?
149
+
150
+ end_time = Chronic.parse(params[:end_time]).to_i
151
+ start_time = params[:start_time].to_i
152
+ raise ArgumentError, "start time parsed to zero" unless start_time > 0
153
+
154
+ patches = {}
155
+ patches[:end_time] = end_time if end_time && (end_time > start_time)
156
+
157
+ raise ArgumentError.new("no valid data received to patch with") if patches.empty?
158
+
159
+ entity_check.update_scheduled_maintenance(start_time, patches)
160
+ redirect back
161
+
162
+ rescue Exception => e
163
+ puts e.message
164
+ puts e.backtrace.join("\n")
165
+ end
166
+ end
167
+
142
168
  # delete a scheduled maintenance
143
169
  delete '/scheduled_maintenances/:entity/:check' do
144
170
  entity_check = get_entity_check(params[:entity], params[:check])
@@ -49,7 +49,7 @@
49
49
  %form{:action => "/acknowledgements/#{@entity}/#{@check}", :method => "post"}
50
50
  %h2
51
51
  State: #{@check_state ? @check_state.upcase : ''}
52
- - if (['warning', 'critical'].include?(@check_state) and !(@in_unscheduled_maintenance || @in_scheduled_maintenance))
52
+ - if (['warning', 'critical'].include?(@check_state) and !(@current_unscheduled_maintenance || @current_scheduled_maintenance))
53
53
  %input{:type => 'hidden', :name => 'acknowledgement_id', :value => "#{@acknowledgement_id}"}
54
54
  %input{:type => 'submit', :value => 'Acknowledge', :class => 'button'}
55
55
  with
@@ -59,14 +59,13 @@
59
59
  %label{:for => 'duration'}
60
60
  duration:
61
61
  %input{:type => 'text', :name => 'duration', :value => ''}
62
- - if @in_unscheduled_maintenance
63
- %h3 (Acknowledged)
64
- - if @in_scheduled_maintenance
65
- %h3 (Scheduled Maintenance)
66
- - if @in_unscheduled_maintenance
62
+ - if @current_unscheduled_maintenance
63
+ %h3 (Acknowledged - #{@current_unscheduled_maintenance[:summary]})
67
64
  %form{:action => "/end_unscheduled_maintenance/#{@entity}/#{@check}", :method => "post"}
68
65
  %p
69
66
  %input{:type => 'submit', :value => 'End Unscheduled Maintenance (Unacknowledge)', :class => 'button'}
67
+ - if @current_scheduled_maintenance
68
+ %h3 (Scheduled Maintenance - #{@current_scheduled_maintenance[:summary]})
70
69
  %h3 Output: #{@check_summary}
71
70
  %table
72
71
  %tr
@@ -128,12 +127,19 @@
128
127
  %td= summary
129
128
  %td
130
129
  - if end_time > Time.now.to_i
131
- %form{ :action => "/scheduled_maintenances/#{@entity}/#{@check}", :method => "post"}
132
- %input{:type => 'hidden', :name => '_method', :value => 'delete'}
133
- %input{:type => 'hidden', :name => 'start_time', :value => start_time}
134
- %input{:type => 'submit', :value => 'Delete', :class => 'button'}
130
+ - if start_time > Time.now.to_i
131
+ %form{ :action => "/scheduled_maintenances/#{@entity}/#{@check}", :method => "post"}
132
+ %input{:type => 'hidden', :name => '_method', :value => 'delete'}
133
+ %input{:type => 'hidden', :name => 'start_time', :value => start_time}
134
+ %input{:type => 'submit', :value => 'Delete', :class => 'button'}
135
+ - else
136
+ %form{ :action => "/scheduled_maintenances/#{@entity}/#{@check}", :method => "post"}
137
+ %input{:type => 'hidden', :name => '_method', :value => 'patch'}
138
+ %input{:type => 'hidden', :name => 'start_time', :value => start_time}
139
+ %input{:type => 'hidden', :name => 'end_time', :value => 'now'}
140
+ %input{:type => 'submit', :value => 'End Now', :class => 'button'}
135
141
  - else
136
- %p No scheduled maintenance
142
+ %p No maintenance is scheduled
137
143
  %h4 Add Scheduled Maintenace
138
144
  %form{:action => "/scheduled_maintenances/#{@entity}/#{@check}", :method => "post"}
139
145
  %fieldset
@@ -167,4 +167,103 @@ describe 'Flapjack::API', :sinatra => true do
167
167
  last_response.body.should == result_json
168
168
  end
169
169
 
170
+ it "creates entities from a submitted list" do
171
+ entities = {'entities' =>
172
+ [
173
+ {"id" => "10001",
174
+ "name" => "clientx-app-01",
175
+ "contacts" => ["0362","0363","0364"]
176
+ },
177
+ {"id" => "10002",
178
+ "name" => "clientx-app-02",
179
+ "contacts" => ["0362"]
180
+ }
181
+ ]
182
+ }
183
+ Flapjack::Data::Entity.should_receive(:add).twice
184
+
185
+ post "/entities", entities.to_json, {'CONTENT_TYPE' => 'application/json'}
186
+ last_response.status.should == 200
187
+ end
188
+
189
+ it "does not create entities if the data is improperly formatted" do
190
+ Flapjack::Data::Entity.should_not_receive(:add)
191
+
192
+ post "/entities", {'entities' => ["Hello", "there"]}.to_json,
193
+ {'CONTENT_TYPE' => 'application/json'}
194
+ last_response.status.should == 403
195
+ end
196
+
197
+ it "does not create entities if they don't contain an id" do
198
+ entities = {'entities' =>
199
+ [
200
+ {"id" => "10001",
201
+ "name" => "clientx-app-01",
202
+ "contacts" => ["0362","0363","0364"]
203
+ },
204
+ {"name" => "clientx-app-02",
205
+ "contacts" => ["0362"]
206
+ }
207
+ ]
208
+ }
209
+ Flapjack::Data::Entity.should_receive(:add)
210
+
211
+ post "/entities", entities.to_json, {'CONTENT_TYPE' => 'application/json'}
212
+ last_response.status.should == 200
213
+ end
214
+
215
+ it "creates contacts from a submitted list" do
216
+ contacts = {'contacts' =>
217
+ [{"id" => "0362",
218
+ "first_name" => "John",
219
+ "last_name" => "Smith",
220
+ "email" => "johns@example.dom",
221
+ "media" => {"email" => "johns@example.dom",
222
+ "jabber" => "johns@conference.localhost"}},
223
+ {"id" => "0363",
224
+ "first_name" => "Jane",
225
+ "last_name" => "Jones",
226
+ "email" => "jane@example.dom",
227
+ "media" => {"email" => "jane@example.dom"}}
228
+ ]
229
+ }
230
+
231
+ Flapjack::Data::Contact.should_receive(:delete_all)
232
+ Flapjack::Data::Contact.should_receive(:add).twice
233
+
234
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
235
+ last_response.status.should == 200
236
+ end
237
+
238
+ it "does not create contacts if the data is improperly formatted" do
239
+ Flapjack::Data::Contact.should_not_receive(:delete_all)
240
+ Flapjack::Data::Contact.should_not_receive(:add)
241
+
242
+ post "/contacts", {'contacts' => ["Hello", "again"]}.to_json,
243
+ {'CONTENT_TYPE' => 'application/json'}
244
+ last_response.status.should == 403
245
+ end
246
+
247
+ it "does not create contacts if they don't contain an id" do
248
+ contacts = {'contacts' =>
249
+ [{"id" => "0362",
250
+ "first_name" => "John",
251
+ "last_name" => "Smith",
252
+ "email" => "johns@example.dom",
253
+ "media" => {"email" => "johns@example.dom",
254
+ "jabber" => "johns@conference.localhost"}},
255
+ {"first_name" => "Jane",
256
+ "last_name" => "Jones",
257
+ "email" => "jane@example.dom",
258
+ "media" => {"email" => "jane@example.dom"}}
259
+ ]
260
+ }
261
+
262
+ Flapjack::Data::Contact.should_receive(:delete_all)
263
+ Flapjack::Data::Contact.should_receive(:add)
264
+
265
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
266
+ last_response.status.should == 200
267
+ end
268
+
170
269
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ require 'flapjack/data/contact'
4
+
5
+ describe Flapjack::Data::Contact, :redis => true do
6
+
7
+ it "finds all contacts for a check on an entity"
8
+
9
+ it "deletes all contacts"
10
+
11
+ it "adds a contact"
12
+
13
+ it "returns pagerduty credentials for a contact"
14
+
15
+ end
@@ -152,6 +152,10 @@ describe Flapjack::Data::EntityCheck, :redis => true do
152
152
 
153
153
  it "creates a scheduled maintenance period covering the current time"
154
154
 
155
+ it "updates a scheduled maintenance period for a future time"
156
+
157
+ it "updates a scheduled maintenance period covering the current time"
158
+
155
159
  it "removes a scheduled maintenance period for a future time"
156
160
 
157
161
  it "removes a scheduled maintenance period covering a current time"
@@ -395,4 +399,4 @@ describe Flapjack::Data::EntityCheck, :redis => true do
395
399
  ec.last_recovery_notification.should == t
396
400
  end
397
401
 
398
- end
402
+ end
@@ -101,10 +101,10 @@ describe Flapjack::Web, :sinatra => true, :redis => true do
101
101
  entity_check.should_receive(:last_change).and_return(time - (3 * 60 * 60))
102
102
  entity_check.should_receive(:summary).and_return('all good')
103
103
  entity_check.should_receive(:last_notifications_of_each_type).and_return(last_notifications)
104
- entity_check.should_receive(:in_scheduled_maintenance?).and_return(false)
105
- entity_check.should_receive(:in_unscheduled_maintenance?).and_return(false)
106
104
  entity_check.should_receive(:maintenances).with(nil, nil, :scheduled => true).and_return([])
107
105
  entity_check.should_receive(:failed?).and_return(false)
106
+ entity_check.should_receive(:current_maintenance).with(:scheduled => true).and_return(false)
107
+ entity_check.should_receive(:current_maintenance).with(:scheduled => false).and_return(false)
108
108
 
109
109
  Flapjack::Data::Entity.should_receive(:find_by_name).
110
110
  with(entity_name, :redis => @redis).and_return(entity)
@@ -142,7 +142,7 @@ describe Flapjack::Web, :sinatra => true, :redis => true do
142
142
  with(an_instance_of(Hash))
143
143
 
144
144
  post "/acknowledgements/#{entity_name_esc}/ping"
145
- last_response.status.should == 201
145
+ last_response.status.should == 302
146
146
  end
147
147
 
148
148
  it "creates a scheduled maintenance period for an entity check" do
@@ -169,6 +169,26 @@ describe Flapjack::Web, :sinatra => true, :redis => true do
169
169
  last_response.status.should == 302
170
170
  end
171
171
 
172
+ # FIXME: how to support the patch http method? ... also, is putting the post data into the url the
173
+ # way to go here?
174
+ it "updates a scheduled maintenance period for an entity check" do
175
+ t = Time.now.to_i
176
+
177
+ start_time = t - (24 * 60 * 60)
178
+
179
+ Flapjack::Data::Entity.should_receive(:find_by_name).
180
+ with(entity_name, :redis => @redis).and_return(entity)
181
+
182
+ Flapjack::Data::EntityCheck.should_receive(:for_entity).
183
+ with(entity, 'ping', :redis => @redis).and_return(entity_check)
184
+
185
+ entity_check.should_receive(:update_scheduled_maintenance).
186
+ with(start_time, {:end_time => t})
187
+
188
+ patch "/scheduled_maintenances/#{entity_name_esc}/ping", {"start_time" => start_time, "end_time" => 'now'}
189
+ last_response.status.should == 302
190
+ end
191
+
172
192
  it "deletes a scheduled maintenance period for an entity check" do
173
193
  t = Time.now.to_i
174
194
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flapjack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.35
4
+ version: 0.6.36
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-09-25 00:00:00.000000000 Z
14
+ date: 2012-09-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: daemons
@@ -458,7 +458,6 @@ files:
458
458
  - lib/flapjack/utility.rb
459
459
  - lib/flapjack/version.rb
460
460
  - lib/flapjack/web.rb
461
- - lib/flapjack/web/views/acknowledge.haml
462
461
  - lib/flapjack/web/views/check.haml
463
462
  - lib/flapjack/web/views/index.haml
464
463
  - lib/flapjack/web/views/self_stats.haml
@@ -495,6 +494,7 @@ files:
495
494
  - spec/lib/flapjack/api/entity_presenter_spec.rb
496
495
  - spec/lib/flapjack/api_spec.rb
497
496
  - spec/lib/flapjack/coordinator_spec.rb
497
+ - spec/lib/flapjack/data/contact_spec.rb
498
498
  - spec/lib/flapjack/data/entity_check_spec.rb
499
499
  - spec/lib/flapjack/data/entity_spec.rb
500
500
  - spec/lib/flapjack/data/event_spec.rb
@@ -567,6 +567,7 @@ test_files:
567
567
  - spec/lib/flapjack/api/entity_presenter_spec.rb
568
568
  - spec/lib/flapjack/api_spec.rb
569
569
  - spec/lib/flapjack/coordinator_spec.rb
570
+ - spec/lib/flapjack/data/contact_spec.rb
570
571
  - spec/lib/flapjack/data/entity_check_spec.rb
571
572
  - spec/lib/flapjack/data/entity_spec.rb
572
573
  - spec/lib/flapjack/data/event_spec.rb
@@ -1,55 +0,0 @@
1
- !!! 5
2
- %html
3
- %head
4
- :css
5
- * { margin: 0; padding: 0; }
6
- html { font-size: 62.5%; }
7
- body { font-size: 16px; }
8
- div#wrapper {
9
- margin: 24px auto;
10
- width: 1000px;
11
- }
12
- h1, h2, h3, h4, h5 {
13
- font-family: Helvetica Neue, sans-serif;
14
- margin-bottom: 12px;
15
- }
16
- table {
17
- text-align: left;
18
- width: 100%;
19
- }
20
- table th {
21
- font-family: Helvetica Neue, sans-serif;
22
- background-color: #eee;
23
- }
24
- table td, table th {
25
- padding: 4px;
26
- }
27
- table td.critical {
28
- background-color: #fb9a99;
29
- }
30
- table td.down {
31
- background-color: #fb9a99;
32
- }
33
- table td.warning {
34
- background-color: #f9bb34;
35
- }
36
- table td.ok {
37
- background-color: #B2DF8A;
38
- }
39
- table td.up {
40
- background-color: #B2DF8A;
41
- }
42
- %body
43
- %div#wrapper
44
- %p
45
- %a(title='Dashboard' href='/') All Checks
46
- |
47
- %a(title='Dashboard' href='/failing') Failing Checks
48
- - if @acknowledge_success
49
- %h1
50
- %a(href="/check?entity=#{@entity}&check=#{@check}") #{@check} on #{@entity}
51
- has been acknowledged
52
- - else
53
- %h1
54
- Failed to acknowledge
55
- %a(href="/check?entity=#{@entity}&check=#{@check}") #{@check} on #{@entity}