flapjack 0.7.17 → 0.7.18

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/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## Flapjack Changelog
2
2
 
3
+ # 0.7.18 - 2013-07-05
4
+ - Feature: delete currently active scheduled maintenance via api should truncate from Time.now gh-242 (@ali-graham)
5
+
3
6
  # 0.7.17 - 2013-07-04
4
7
  - Feature: split API methods into two separate files, also specs gh-215 (@ali-graham)
5
8
  - Feature: unlock ruby version, build with Ruby 2 in travis gh-237 (@ali-graham)
@@ -131,37 +131,39 @@ module Flapjack
131
131
  update_current_scheduled_maintenance(:revalidate => true)
132
132
  end
133
133
 
134
- # change the end time of a scheduled maintenance (including when one is current)
135
- # TODO allow to update summary as well
136
- def update_scheduled_maintenance(start_time, patches = {})
137
-
138
- # check if there is such a scheduled maintenance period
139
- old_duration = @redis.zscore("#{@key}:scheduled_maintenances", start_time)
140
- raise ArgumentError, 'no such scheduled maintenance period can be found' unless old_duration
141
- raise ArgumentError, 'no handled patches have been supplied' unless patches[:end_time]
142
-
143
- if patches[:end_time]
144
- end_time = patches[:end_time]
145
- raise ArgumentError, "end time must be after start time" unless end_time > start_time
146
- old_end_time = start_time + old_duration
147
- duration = end_time - start_time
148
- @redis.zadd("#{@key}:scheduled_maintenances", duration, start_time)
149
- end
134
+ # TODO allow summary to be changed as part of the termination
135
+ def end_scheduled_maintenance(start_time)
136
+ raise ArgumentError, 'start time must be supplied as a Unix timestamp' unless start_time && start_time.is_a?(Integer)
150
137
 
151
- # scheduled maintenance periods have changed, revalidate
152
- update_current_scheduled_maintenance(:revalidate => true)
153
- end
138
+ # don't do anything if a scheduled maintenance period with that start time isn't stored
139
+ duration = @redis.zscore("#{@key}:scheduled_maintenances", start_time)
140
+ return false if duration.nil?
154
141
 
155
- # delete a scheduled maintenance
156
- def delete_scheduled_maintenance(opts = {})
157
- start_time = opts[:start_time]
158
- @redis.del("#{@key}:#{start_time}:scheduled_maintenance:summary")
159
- @redis.zrem("#{@key}:scheduled_maintenances", start_time)
142
+ current_time = Time.now.to_i
160
143
 
161
- @redis.zremrangebyscore("#{@key}:sorted_scheduled_maintenance_timestamps", start_time, start_time)
144
+ if start_time > current_time
145
+ # the scheduled maintenance period (if it exists) is in the future
146
+ @redis.del("#{@key}:#{start_time}:scheduled_maintenance:summary")
147
+ @redis.zrem("#{@key}:scheduled_maintenances", start_time)
162
148
 
163
- # scheduled maintenance periods have changed, revalidate
164
- update_current_scheduled_maintenance(:revalidate => true)
149
+ @redis.zremrangebyscore("#{@key}:sorted_scheduled_maintenance_timestamps", start_time, start_time)
150
+
151
+ # scheduled maintenance periods (may) have changed, revalidate
152
+ update_current_scheduled_maintenance(:revalidate => true)
153
+
154
+ return true
155
+ elsif (start_time + duration) > current_time
156
+ # it spans the current time, so we'll stop it at that point
157
+ new_duration = current_time - start_time
158
+ @redis.zadd("#{@key}:scheduled_maintenances", new_duration, start_time)
159
+
160
+ # scheduled maintenance periods have changed, revalidate
161
+ update_current_scheduled_maintenance(:revalidate => true)
162
+
163
+ return true
164
+ end
165
+
166
+ false
165
167
  end
166
168
 
167
169
  # if not in scheduled maintenance, looks in scheduled maintenance list for a check to see if
@@ -174,9 +176,9 @@ module Flapjack
174
176
  end
175
177
 
176
178
  # are we within a scheduled maintenance period?
177
- t = Time.now.to_i
179
+ current_time = Time.now.to_i
178
180
  current_sched_ms = maintenances(nil, nil, :scheduled => true).select {|sm|
179
- (sm[:start_time] <= t) && (t < sm[:end_time])
181
+ (sm[:start_time] <= current_time) && (current_time < sm[:end_time])
180
182
  }
181
183
  return if current_sched_ms.empty?
182
184
 
@@ -270,8 +270,7 @@ module Flapjack
270
270
  start_time = validate_and_parsetime(params[:start_time])
271
271
  halt( err(403, "start time must be provided") ) unless start_time
272
272
  opts = {}
273
- opts[:start_time] = start_time.to_i
274
- proc {|entity_check| entity_check.delete_scheduled_maintenance(opts) }
273
+ proc {|entity_check| entity_check.end_scheduled_maintenance(start_time.to_i) }
275
274
  when 'unscheduled_maintenances'
276
275
  end_time = validate_and_parsetime(params[:end_time])
277
276
  opts = {}
@@ -247,30 +247,12 @@ module Flapjack
247
247
  redirect back
248
248
  end
249
249
 
250
- # modify scheduled maintenance
251
- patch '/scheduled_maintenances/:entity/:check' do
252
- entity_check = get_entity_check(params[:entity], params[:check])
253
- return 404 if entity_check.nil?
254
-
255
- end_time = Chronic.parse(params[:end_time]).to_i
256
- start_time = params[:start_time].to_i
257
- raise ArgumentError, "start time parsed to zero" unless start_time > 0
258
-
259
- patches = {}
260
- patches[:end_time] = end_time if end_time && (end_time > start_time)
261
-
262
- raise ArgumentError.new("no valid data received to patch with") if patches.empty?
263
-
264
- entity_check.update_scheduled_maintenance(start_time, patches)
265
- redirect back
266
- end
267
-
268
250
  # delete a scheduled maintenance
269
251
  delete '/scheduled_maintenances/:entity/:check' do
270
252
  entity_check = get_entity_check(params[:entity], params[:check])
271
253
  return 404 if entity_check.nil?
272
254
 
273
- entity_check.delete_scheduled_maintenance(:start_time => params[:start_time].to_i)
255
+ entity_check.end_scheduled_maintenance(params[:start_time].to_i)
274
256
  redirect back
275
257
  end
276
258
 
@@ -3,6 +3,7 @@
3
3
  - head = render_haml('_head.haml', self)
4
4
  - foot = render_haml('_foot.haml', self)
5
5
  - check_path_escaped = URI.escape(@entity, ' #&;/=?') << '/' << URI.escape(@check, ' #&;/=?')
6
+ - current_time = Time.now
6
7
  %html
7
8
  %head
8
9
  %title Flapjack - Check: #{@entity}:#{@check}
@@ -26,7 +27,6 @@
26
27
  duration:
27
28
  %input{:type => 'text', :name => 'duration', :value => ''}
28
29
  e.g. "5 hours"
29
- - current_time = (@current_unscheduled_maintenance || @current_scheduled_maintenance) ? Time.now : nil
30
30
  - if @current_unscheduled_maintenance
31
31
  %h3 (Acknowledged - #{@current_unscheduled_maintenance[:summary]})
32
32
  - start = Time.at(@current_unscheduled_maintenance[:start_time])
@@ -125,18 +125,12 @@
125
125
  %td= ChronicDuration.output(duration)
126
126
  %td= summary
127
127
  %td
128
- - if end_time > Time.now.to_i
129
- - if start_time > Time.now.to_i
130
- %form{ :action => "/scheduled_maintenances/#{check_path_escaped}", :method => "post"}
131
- %input{:type => 'hidden', :name => '_method', :value => 'delete'}
132
- %input{:type => 'hidden', :name => 'start_time', :value => start_time}
133
- %input{:type => 'submit', :value => 'Delete', :class => 'button'}
134
- - else
135
- %form{ :action => "/scheduled_maintenances/#{check_path_escaped}", :method => "post"}
136
- %input{:type => 'hidden', :name => '_method', :value => 'patch'}
137
- %input{:type => 'hidden', :name => 'start_time', :value => start_time}
138
- %input{:type => 'hidden', :name => 'end_time', :value => 'now'}
139
- %input{:type => 'submit', :value => 'End Now', :class => 'button'}
128
+ - if end_time > current_time.to_i
129
+ - label = (start_time > current_time.to_i) ? 'Delete' : 'End Now'
130
+ %form{ :action => "/scheduled_maintenances/#{check_path_escaped}", :method => "post"}
131
+ %input{:type => 'hidden', :name => '_method', :value => 'delete'}
132
+ %input{:type => 'hidden', :name => 'start_time', :value => start_time}
133
+ %input{:type => 'submit', :value => label, :class => 'button'}
140
134
  - else
141
135
  %p No maintenance is scheduled
142
136
  %h4 Add Scheduled Maintenance
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.7.17"
4
+ VERSION = "0.7.18"
5
5
  end
@@ -181,63 +181,13 @@ describe Flapjack::Data::EntityCheck, :redis => true do
181
181
  duration.should == 2 * (60 * 60)
182
182
  end
183
183
 
184
- it "updates a scheduled maintenance period for a future time" do
185
- t = Time.now.to_i
186
- ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
187
- ec.create_scheduled_maintenance(:start_time => t + (60 * 60),
188
- :duration => 2 * (60 * 60), :summary => "2 hours")
189
-
190
- ec.update_scheduled_maintenance(t + (60 * 60), :end_time => t + (4 * (60 * 60)))
191
- smps = ec.maintenances(nil, nil, :scheduled => true)
192
- smps.should_not be_nil
193
- smps.should be_an(Array)
194
- smps.should have(1).scheduled_maintenance_period
195
- smps[0].should be_a(Hash)
196
-
197
- start_time = smps[0][:start_time]
198
- start_time.should_not be_nil
199
- start_time.should be_an(Integer)
200
- start_time.should == (t + (60 * 60))
201
-
202
- duration = smps[0][:duration]
203
- duration.should_not be_nil
204
- duration.should be_a(Float)
205
- duration.should == 3 * (60 * 60)
206
- end
207
-
208
- # TODO this should probably enforce that it starts in the future
209
- it "updates a scheduled maintenance period covering the current time", :time => true do
184
+ it "removes a scheduled maintenance period for a future time" do
210
185
  t = Time.now.to_i
211
186
  ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
212
187
  ec.create_scheduled_maintenance(:start_time => t + (60 * 60),
213
188
  :duration => 2 * (60 * 60), :summary => "2 hours")
214
189
 
215
- Delorean.time_travel_to( Time.at(t + (90 * 60)) )
216
-
217
- ec.update_scheduled_maintenance(t + (60 * 60), :end_time => t + (4 * (60 * 60)))
218
- smps = ec.maintenances(nil, nil, :scheduled => true)
219
- smps.should_not be_nil
220
- smps.should be_an(Array)
221
- smps.should have(1).scheduled_maintenance_period
222
- smps[0].should be_a(Hash)
223
-
224
- start_time = smps[0][:start_time]
225
- start_time.should_not be_nil
226
- start_time.should be_an(Integer)
227
- start_time.should == (t + (60 * 60))
228
-
229
- duration = smps[0][:duration]
230
- duration.should_not be_nil
231
- duration.should be_a(Float)
232
- duration.should == 3 * (60 * 60)
233
- end
234
-
235
- it "fails to update a scheduled maintenance period when not found" do
236
- t = Time.now.to_i
237
- ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
238
- lambda {
239
- ec.update_scheduled_maintenance(t + (60 * 60), :end_time => t + (2 * (60 * 60)))
240
- }.should raise_error(ArgumentError)
190
+ ec.end_scheduled_maintenance(t + (60 * 60))
241
191
 
242
192
  smps = ec.maintenances(nil, nil, :scheduled => true)
243
193
  smps.should_not be_nil
@@ -245,61 +195,42 @@ describe Flapjack::Data::EntityCheck, :redis => true do
245
195
  smps.should be_empty
246
196
  end
247
197
 
248
- it "fails to update a scheduled maintenance period with invalid end time" do
198
+ # maint period starts an hour from now, goes for two hours -- at 30 minutes into
199
+ # it we stop it, and its duration should be 30 minutes
200
+ it "shortens a scheduled maintenance period covering a current time", :time => true do
249
201
  t = Time.now.to_i
250
202
  ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
251
203
  ec.create_scheduled_maintenance(:start_time => t + (60 * 60),
252
204
  :duration => 2 * (60 * 60), :summary => "2 hours")
253
205
 
254
- lambda {
255
- ec.update_scheduled_maintenance(t + (60 * 60), :end_time => t - (4 * (60 * 60)))
256
- }.should raise_error(ArgumentError)
257
- smps = ec.maintenances(nil, nil, :scheduled => true)
258
- smps.should_not be_nil
259
- smps.should be_an(Array)
260
- smps.should have(1).scheduled_maintenance_period
261
- smps[0].should be_a(Hash)
262
-
263
- start_time = smps[0][:start_time]
264
- start_time.should_not be_nil
265
- start_time.should be_an(Integer)
266
- start_time.should == (t + (60 * 60))
267
-
268
- duration = smps[0][:duration]
269
- duration.should_not be_nil
270
- duration.should be_a(Float)
271
- duration.should == 2 * (60 * 60)
272
- end
273
-
274
- it "removes a scheduled maintenance period for a future time" do
275
- t = Time.now.to_i
276
- ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
277
- ec.create_scheduled_maintenance(:start_time => t + (60 * 60),
278
- :duration => 2 * (60 * 60), :summary => "2 hours")
206
+ Delorean.time_travel_to( Time.at(t + (90 * 60)) )
279
207
 
280
- ec.delete_scheduled_maintenance(:start_time => t + (60 * 60))
208
+ ec.end_scheduled_maintenance(t + (60 * 60))
281
209
 
282
210
  smps = ec.maintenances(nil, nil, :scheduled => true)
283
211
  smps.should_not be_nil
284
212
  smps.should be_an(Array)
285
- smps.should be_empty
213
+ smps.should_not be_empty
214
+ smps.should have(1).item
215
+ smps.first[:duration].should == (30 * 60)
286
216
  end
287
217
 
288
- # TODO this should probably enforce that it starts in the future
289
- it "removes a scheduled maintenance period covering a current time", :time => true do
218
+ it "does not alter or remove a scheduled maintenance period covering a past time", :time => true do
290
219
  t = Time.now.to_i
291
220
  ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
292
221
  ec.create_scheduled_maintenance(:start_time => t + (60 * 60),
293
222
  :duration => 2 * (60 * 60), :summary => "2 hours")
294
223
 
295
- Delorean.time_travel_to( Time.at(t + (90 * 60)) )
224
+ Delorean.time_travel_to( Time.at(t + (6 * (60 * 60)) ))
296
225
 
297
- ec.delete_scheduled_maintenance(:start_time => t + (60 * 60))
226
+ ec.end_scheduled_maintenance(t + (60 * 60))
298
227
 
299
228
  smps = ec.maintenances(nil, nil, :scheduled => true)
300
229
  smps.should_not be_nil
301
230
  smps.should be_an(Array)
302
- smps.should be_empty
231
+ smps.should_not be_empty
232
+ smps.should have(1).item
233
+ smps.first[:duration].should == 2 * (60 * 60)
303
234
  end
304
235
 
305
236
  it "returns a list of scheduled maintenance periods" do
@@ -413,7 +413,7 @@ describe 'Flapjack::Gateways::API::EntityMethods', :sinatra => true, :logger =>
413
413
 
414
414
  it "deletes a scheduled maintenance period for an entity check" do
415
415
  start_time = Time.now + (60 * 60) # an hour from now
416
- entity_check.should_receive(:delete_scheduled_maintenance).with(:start_time => start_time.to_i)
416
+ entity_check.should_receive(:end_scheduled_maintenance).with(start_time.to_i)
417
417
 
418
418
  Flapjack::Data::EntityCheck.should_receive(:for_entity).
419
419
  with(entity, check, :redis => redis).and_return(entity_check)
@@ -426,7 +426,7 @@ describe 'Flapjack::Gateways::API::EntityMethods', :sinatra => true, :logger =>
426
426
  end
427
427
 
428
428
  it "doesn't delete a scheduled maintenance period if the start time isn't passed" do
429
- entity_check.should_not_receive(:delete_scheduled_maintenance)
429
+ entity_check.should_not_receive(:end_scheduled_maintenance)
430
430
 
431
431
  delete "/scheduled_maintenances", :check => {entity_name => check}
432
432
  last_response.status.should == 403
@@ -437,8 +437,8 @@ describe 'Flapjack::Gateways::API::EntityMethods', :sinatra => true, :logger =>
437
437
 
438
438
  entity_check_2 = mock(Flapjack::Data::EntityCheck)
439
439
 
440
- entity_check.should_receive(:delete_scheduled_maintenance).with(:start_time => start_time.to_i)
441
- entity_check_2.should_receive(:delete_scheduled_maintenance).with(:start_time => start_time.to_i)
440
+ entity_check.should_receive(:end_scheduled_maintenance).with(start_time.to_i)
441
+ entity_check_2.should_receive(:end_scheduled_maintenance).with(start_time.to_i)
442
442
 
443
443
  Flapjack::Data::EntityCheck.should_receive(:for_entity).
444
444
  with(entity, check, :redis => redis).and_return(entity_check)
@@ -112,7 +112,7 @@ describe Flapjack::Gateways::Web, :sinatra => true, :logger => true do
112
112
 
113
113
  it "shows the state of a check for an entity" do
114
114
  time = Time.now
115
- Time.should_receive(:now).exactly(4).times.and_return(time)
115
+ Time.should_receive(:now).exactly(5).times.and_return(time)
116
116
 
117
117
  last_notifications = {:problem => {:timestamp => time.to_i - ((3 * 60 * 60) + (5 * 60)), :summary => 'prob'},
118
118
  :recovery => {:timestamp => time.to_i - (3 * 60 * 60), :summary => nil},
@@ -202,27 +202,6 @@ describe Flapjack::Gateways::Web, :sinatra => true, :logger => true do
202
202
  last_response.status.should == 302
203
203
  end
204
204
 
205
- it "updates a scheduled maintenance period for an entity check" do
206
- t = Time.new.to_i
207
-
208
- start_time = t - (24 * 60 * 60)
209
-
210
- Flapjack::Data::Entity.should_receive(:find_by_name).
211
- with(entity_name, :redis => redis).and_return(entity)
212
-
213
- Flapjack::Data::EntityCheck.should_receive(:for_entity).
214
- with(entity, 'ping', :redis => redis).and_return(entity_check)
215
-
216
- Chronic.should_receive(:parse).with('now').and_return(t)
217
-
218
- entity_check.should_receive(:update_scheduled_maintenance).
219
- with(start_time, {:end_time => t})
220
-
221
- patch "/scheduled_maintenances/#{entity_name_esc}/ping",
222
- {"start_time" => start_time, "end_time" => 'now'}
223
- last_response.status.should == 302
224
- end
225
-
226
205
  it "deletes a scheduled maintenance period for an entity check" do
227
206
  t = Time.now.to_i
228
207
 
@@ -234,8 +213,7 @@ describe Flapjack::Gateways::Web, :sinatra => true, :logger => true do
234
213
  Flapjack::Data::EntityCheck.should_receive(:for_entity).
235
214
  with(entity, 'ping', :redis => redis).and_return(entity_check)
236
215
 
237
- entity_check.should_receive(:delete_scheduled_maintenance).
238
- with(:start_time => start_time)
216
+ entity_check.should_receive(:end_scheduled_maintenance).with(start_time)
239
217
 
240
218
  delete "/scheduled_maintenances/#{entity_name_esc}/ping?start_time=#{start_time}"
241
219
  last_response.status.should == 302
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.7.17
4
+ version: 0.7.18
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: 2013-07-04 00:00:00.000000000 Z
14
+ date: 2013-07-05 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: dante
@@ -557,7 +557,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
557
557
  version: '0'
558
558
  segments:
559
559
  - 0
560
- hash: 4104603407459161527
560
+ hash: -3760765416681204020
561
561
  required_rubygems_version: !ruby/object:Gem::Requirement
562
562
  none: false
563
563
  requirements:
@@ -566,7 +566,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
566
566
  version: '0'
567
567
  segments:
568
568
  - 0
569
- hash: 4104603407459161527
569
+ hash: -3760765416681204020
570
570
  requirements: []
571
571
  rubyforge_project:
572
572
  rubygems_version: 1.8.23