flapjack 0.6.29 → 0.6.30

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/README.md CHANGED
@@ -62,7 +62,7 @@ There's some rspec unit tests as well, run these like so:
62
62
 
63
63
  $ rspec spec
64
64
 
65
- NB, if the cucumber tests fail with a spurious lexing error on line 2 of events.feature, then try this:
65
+ NB, if the cucumber tests fail with a [spurious lexing error](https://github.com/cucumber/gherkin/issues/182) on line 2 of events.feature, then try this:
66
66
 
67
67
  $ cucumber -f fuubar features
68
68
 
@@ -1,11 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'yajl'
3
+ require 'yajl/json_gem'
4
4
  require 'redis'
5
- require 'yaml'
6
5
  require 'optparse'
7
6
  require 'ostruct'
8
- require 'flapjack/data/entity_check'
7
+
8
+ # add lib to the default include path
9
+ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
10
+ $: << File.dirname(__FILE__) + '/../lib'
11
+ end
12
+
13
+ require 'flapjack/configuration'
14
+ require 'flapjack/data/contact'
15
+ require 'flapjack/data/entity'
9
16
 
10
17
  options = OpenStruct.new
11
18
  options.config = File.join('etc', 'flapjack_config.yaml')
@@ -35,109 +42,58 @@ end.parse!(ARGV)
35
42
 
36
43
  FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
37
44
 
38
- # load the config hash for the current environment
39
-
40
- if File.file?(options.config)
41
- config = YAML::load(File.open(options.config))
42
- else
43
- puts "Could not find config file at '#{options.config}', you may want to specify one with the --config option"
44
- exit(false)
45
- end
46
-
47
- config_env = config[FLAPJACK_ENV]
48
-
49
- if config_env.nil? || config_env.empty?
50
- puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
51
- exit(false)
52
- end
45
+ config_env = Flapjack::Configuration.new.load(options.config)
53
46
 
54
47
  if options.from
55
48
  filename = options.from
56
49
  file = File.new(filename)
57
50
  end
58
51
 
59
- parser = Yajl::Parser.new
60
-
61
- @redis_host = config_env['redis']['host'] || 'localhost'
62
- @redis_port = config_env['redis']['port'] || '6379'
63
- @redis_path = config_env['redis']['path'] || nil
64
- @redis_db = config_env['redis']['db'] || 0
65
-
66
- # add lib to the default include path
67
- unless $:.include?(File.dirname(__FILE__) + '/../lib/')
68
- $: << File.dirname(__FILE__) + '/../lib'
69
- end
70
-
71
- def get_redis_connection
72
- if @redis_path
73
- redis = Redis.new(:db => @redis_db, :path => @redis_path)
74
- else
75
- redis = Redis.new(:db => @redis_db, :host => @redis_host, :port => @redis_port)
76
- end
77
- redis
52
+ def get_redis_connection(cfg)
53
+ opts = cfg['path'] ? {:path => cfg['path']} :
54
+ {:host => cfg['host'], :port => cfg['port']}
55
+ Redis.new(opts.merge(:db => cfg['db']))
78
56
  end
79
57
 
80
58
  case command
81
59
  when "import-contacts"
82
- @persistence = get_redis_connection
83
- contacts = parser.parse(file)
84
- contacts.each {|contact|
85
- if not contact['id']
86
- puts "Contact not imported as it has no id: " + contact.inspect
87
- next
88
- end
89
- @persistence.multi
90
- @persistence.del("contact:#{contact['id']}")
91
- @persistence.del("contact_media:#{contact['id']}")
92
- @persistence.del("contact_pagerduty:#{contact['id']}")
93
- @persistence.hset("contact:#{contact['id']}", 'first_name', contact['first_name'])
94
- @persistence.hset("contact:#{contact['id']}", 'last_name', contact['last_name'])
95
- @persistence.hset("contact:#{contact['id']}", 'email', contact['email'])
96
- contact['media'].each_pair {|medium, address|
97
- case medium
98
- when 'pagerduty'
99
- @persistence.hset("contact_media:#{contact['id']}", medium, address['service_key'])
100
- @persistence.hset("contact_pagerduty:#{contact['id']}", 'subdomain', address['subdomain'])
101
- @persistence.hset("contact_pagerduty:#{contact['id']}", 'username', address['username'])
102
- @persistence.hset("contact_pagerduty:#{contact['id']}", 'password', address['password'])
103
- else
104
- @persistence.hset("contact_media:#{contact['id']}", medium, address)
60
+ contacts = JSON.parse(file)
61
+
62
+ if contacts && contacts.is_a?(Enumerable) && contacts.any? {|e| !e['id'].nil?}
63
+ @persistence = get_redis_connection(config_env['redis'])
64
+ @persistence.multi do
65
+ contacts.each do |contact|
66
+ unless contact['id']
67
+ puts "Contact not imported as it has no id: " + contact.inspect
68
+ next
69
+ end
70
+ Flapjack::Data::Contact.add(contact, :redis => @persistence)
105
71
  end
106
- }
107
- @persistence.exec
108
- }
72
+ end
73
+ @persistence.quit
74
+ end
109
75
 
110
76
  when "import-entities"
111
- @persistence = get_redis_connection
112
- entities = parser.parse(file)
113
- entities.each {|entity|
114
- if not entity['id']
115
- puts "Entity not imported as it has no id: " + entity.inspect
116
- next
117
- end
77
+ entities = JSON.parse(file)
78
+
79
+ if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
80
+ @persistence = get_redis_connection(config_env['redis'])
118
81
  @persistence.multi
119
- existing_name = @persistence.hget("entity:#{entity['id']}", 'name')
120
- @persistence.del("entity_id:#{existing_name}") unless existing_name == entity['name']
121
- @persistence.set("entity_id:#{entity['name']}", entity['id'])
122
- @persistence.hset("entity:#{entity['id']}", 'name', entity['name'])
123
-
124
- @persistence.del("contacts_for:#{entity['id']}")
125
- entity['contacts'].each {|contact|
126
- @persistence.sadd("contacts_for:#{entity['id']}", contact)
127
- }
82
+ entities.each do |entity|
83
+ unless entity['id']
84
+ puts "Entity not imported as it has no id: " + entity.inspect
85
+ next
86
+ end
87
+ Flapjack::Data::Entity.add(entity, :redis => @persistence)
88
+ end
128
89
  @persistence.exec
129
-
130
- }
90
+ @persistence.quit
91
+ end
131
92
 
132
93
  when "purge-events"
133
- @persistence = get_redis_connection
134
- events_size = @persistence.llen('events')
135
- puts "purging #{events_size} events..."
136
- timestamp = Time.now.to_i
137
- puts "renaming events to events.#{timestamp}"
138
- @persistence.rename('events', "events.#{timestamp}")
139
- puts "setting expiry of events.#{timestamp} to 8 hours"
140
- @persistence.expire("events.#{timestamp}", (60 * 60 * 8))
94
+ @persistence = get_redis_connection(config_env['redis'])
95
+ Flapjack::Data.Event.purge_all(:redis => @persistence)
96
+ @persistence.quit
141
97
 
142
98
  else
143
99
  puts "you need to give me something to do, eg a command like 'import-entities' or 'import-clients' etc"
data/lib/flapjack/api.rb CHANGED
@@ -25,7 +25,9 @@ module Flapjack
25
25
  # doesn't work with Rack::Test for some reason
26
26
  unless 'test'.eql?(FLAPJACK_ENV)
27
27
  rescue_exception = Proc.new { |env, exception|
28
- [503, {}, exception.message]
28
+ logger.error exception.message
29
+ logger.error exception.backtrace.join("\n")
30
+ [503, {}, {:status => 503, :reason => exception.message}.to_json]
29
31
  }
30
32
 
31
33
  use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
@@ -38,17 +40,6 @@ module Flapjack
38
40
  Flapjack::API.bootstrap
39
41
  end
40
42
 
41
- helpers do
42
- def json_status(code, reason)
43
- status code
44
- {:status => code, :reason => reason}.to_json
45
- end
46
-
47
- def logger
48
- Flapjack::API.logger
49
- end
50
- end
51
-
52
43
  get '/entities' do
53
44
  content_type :json
54
45
  ret = Flapjack::Data::Entity.all(:redis => @@redis).sort_by(&:name).collect {|e|
@@ -211,7 +202,7 @@ module Flapjack
211
202
  params[:check], :redis => @@redis)
212
203
  entity_check.create_scheduled_maintenance(:start_time => params[:start_time],
213
204
  :duration => params[:duration], :summary => params[:summary])
214
- status 201
205
+ status 204
215
206
  end
216
207
 
217
208
  # create an acknowledgement for a service on an entity
@@ -232,15 +223,11 @@ module Flapjack
232
223
  params[:check], :redis => @@redis)
233
224
  entity_check.create_acknowledgement('summary' => params[:summary],
234
225
  'duration' => duration)
235
- status 201
226
+ status 204
236
227
  end
237
228
 
238
229
  not_found do
239
- json_status 404, "Not found"
240
- end
241
-
242
- error do
243
- json_status 500, env['sinatra.error'].message
230
+ [404, {}, {:status => 404, :reason => "Not found"}.to_json]
244
231
  end
245
232
 
246
233
  private
@@ -265,7 +252,7 @@ module Flapjack
265
252
  return unless value
266
253
  Time.iso8601(value).getutc.to_i
267
254
  rescue ArgumentError => e
268
- # FIXME log error
255
+ logger.error "Couldn't parse time from '#{value}'"
269
256
  nil
270
257
  end
271
258
 
@@ -16,56 +16,34 @@ module Flapjack
16
16
  @entity_check = entity_check
17
17
  end
18
18
 
19
- # if options[:chop] is true, overlapping outages at start and end
20
- # times will be sliced to fit.
21
19
  def outages(start_time, end_time, options = {})
22
- # states is an array of hashes, with [state, timestamp, summary] keys
23
- states = @entity_check.historical_states(start_time, end_time)
24
- return states if states.empty?
25
-
26
- # if it started failed, prepend the earlier event
27
- initial = @entity_check.historical_state_before(states.first[:timestamp])
28
- if (initial && (initial[:state] == Flapjack::Data::EntityCheck::STATE_CRITICAL))
29
- states.unshift(initial)
30
- end
31
-
32
- # if it ended failed, append the event when it recovered
33
- if states.last[:state] == Flapjack::Data::EntityCheck::STATE_CRITICAL
34
- # TODO ensure this event is not CRITICAL, get first non-CRITICAL if so
35
- last = @entity_check.historical_state_after(states.last[:timestamp])
36
- states.push(last) if last
37
- end
38
-
39
- last_state = nil
40
-
41
- # returns an array of hashes, with [:start_time, :end_time, :summary]
42
- time_periods = states.inject([]) do |ret, obj|
43
- if (obj[:state] == Flapjack::Data::EntityCheck::STATE_CRITICAL) &&
44
- (last_state.nil? || (last_state != Flapjack::Data::EntityCheck::STATE_CRITICAL))
45
-
46
- # flipped to failed, mark next outage
47
- last_state = obj[:state]
48
- ret << {:start_time => obj[:timestamp], :end_time => nil, :summary => obj[:summary]}
49
- elsif (obj[:state] != Flapjack::Data::EntityCheck::STATE_CRITICAL) &&
50
- (last_state == Flapjack::Data::EntityCheck::STATE_CRITICAL)
51
-
52
- # flipped to not failed, mark end time for the current outage
53
- last_state = obj[:state]
54
- ret.last[:end_time] = obj[:timestamp]
20
+ # hist_states is an array of hashes, with [state, timestamp, summary] keys
21
+ hist_states = @entity_check.historical_states(start_time, end_time)
22
+ return hist_states if hist_states.empty?
23
+
24
+ initial = @entity_check.historical_state_before(hist_states.first[:timestamp])
25
+ hist_states.unshift(initial) if initial
26
+
27
+ num_states = hist_states.size
28
+
29
+ hist_states.each_with_index do |obj, index|
30
+ if (index == 0)
31
+ # initial
32
+ obj[:start_time] = [obj.delete(:timestamp), start_time].max
33
+ obj[:end_time] = hist_states[index + 1][:timestamp]
34
+ elsif index == (num_states - 1)
35
+ # last
36
+ obj[:start_time] = obj.delete(:timestamp)
37
+ obj[:end_time] = end_time
38
+ else
39
+ # except for first and last
40
+ obj[:start_time] = obj.delete(:timestamp)
41
+ obj[:end_time] = hist_states[index + 1][:timestamp]
55
42
  end
56
- ret
43
+ obj[:duration] = obj[:end_time] - obj[:start_time]
57
44
  end
58
45
 
59
- if options[:chop]
60
- if start_time && (time_periods.first[:start_time] < start_time)
61
- time_periods.first[:start_time] = start_time
62
- end
63
- if time_periods.last[:end_time].nil? || (end_time && (time_periods.last[:end_time] > end_time))
64
- time_periods.last[:end_time] = (end_time || Time.now.to_i)
65
- end
66
- end
67
-
68
- time_periods
46
+ hist_states.reject {|obj| obj[:state] == 'ok'}
69
47
  end
70
48
 
71
49
  def unscheduled_maintenance(start_time, end_time)
@@ -106,10 +84,15 @@ module Flapjack
106
84
  def downtime(start_time, end_time)
107
85
  sched_maintenances = scheduled_maintenance(start_time, end_time)
108
86
 
109
- outs = outages(start_time, end_time, :chop => true)
87
+ outs = outages(start_time, end_time)
110
88
 
111
- total_secs = 0
112
- percentage = 0
89
+ total_secs = {}
90
+ percentages = {}
91
+
92
+ outs.collect {|obj| obj[:state]}.uniq.each do |st|
93
+ total_secs[st] = 0
94
+ percentages[st] = (start_time.nil? || end_time.nil?) ? nil : 0
95
+ end
113
96
 
114
97
  unless outs.empty?
115
98
 
@@ -126,10 +109,12 @@ module Flapjack
126
109
  next unless o[:start_time] < sm[:start_time] &&
127
110
  o[:end_time] > sm[:end_time]
128
111
  o[:delete] = true
129
- split_outs += [{:start_time => o[:start_time],
112
+ split_outs += [{:state => o[:state],
113
+ :start_time => o[:start_time],
130
114
  :end_time => sm[:start_time],
131
115
  :summary => "#{o[:summary]} [split start]"},
132
- {:start_time => sm[:end_time],
116
+ {:state => o[:state],
117
+ :start_time => sm[:end_time],
133
118
  :end_time => o[:end_time],
134
119
  :summary => "#{o[:summary]} [split finish]"}]
135
120
  }
@@ -165,16 +150,21 @@ module Flapjack
165
150
  outs.reject! {|o| o[:delete]}
166
151
  end
167
152
 
168
- # sum outage times
169
- total_secs = outs.inject(0) {|sum, o|
170
- sum += (o[:end_time] - o[:start_time])
153
+ total_secs = outs.inject(total_secs) {|ret, o|
154
+ ret[o[:state]] += (o[:end_time] - o[:start_time])
155
+ ret
171
156
  }
172
157
 
173
- percentage = (start_time.nil? || end_time.nil?) ? nil :
174
- (total_secs * 100) / (end_time - start_time)
158
+ unless (start_time.nil? || end_time.nil?)
159
+ total_secs.each_pair do |st, ts|
160
+ percentages[st] = (total_secs[st] * 100.0) / (end_time.to_f - start_time.to_f)
161
+ end
162
+ end
175
163
  end
176
164
 
177
- {:total_seconds => total_secs, :percentage => percentage, :downtime => outs}
165
+ total_secs['ok'] = (end_time - start_time) - total_secs.values.reduce(:+)
166
+ percentages['ok'] = 100 - percentages.values.reduce(:+)
167
+ {:total_seconds => total_secs, :percentages => percentages, :downtime => outs}
178
168
  end
179
169
 
180
170
  end
@@ -1,10 +1,62 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'yaml'
4
+
3
5
  module Flapjack
4
6
 
5
7
  class Configuration
6
8
 
7
- # TODO consolidate configuration code
9
+ def initialize(opts = {})
10
+ @logger = opts[:logger]
11
+ unless @logger
12
+ @logger = Logger.new(STDOUT)
13
+ @logger.level = Logger::ERROR
14
+ end
15
+ end
16
+
17
+ def logger
18
+ @logger
19
+ end
20
+
21
+ def load(filename)
22
+ unless File.file?(filename)
23
+ logger.error "Could not find file '#{filename}'"
24
+ return
25
+ end
26
+
27
+ unless defined?(FLAPJACK_ENV)
28
+ logger.error "Environment variable 'FLAPJACK_ENV' is not set"
29
+ return
30
+ end
31
+
32
+ config = YAML::load_file(filename)
33
+
34
+ if config.nil?
35
+ logger.error "Could not load config file '#{filename}'"
36
+ return
37
+ end
38
+
39
+ config_env = config[FLAPJACK_ENV]
40
+
41
+ if config_env.nil?
42
+ logger.error "No config data for environment '#{FLAPJACK_ENV}' found in '#{filename}'"
43
+ return
44
+ end
45
+
46
+ redis_defaults = {'host' => 'localhost',
47
+ 'port' => 6379,
48
+ 'path' => nil,
49
+ 'db' => 0}
50
+
51
+ config_env['redis'] = {} unless config_env.has_key?('redis')
52
+ redis_defaults.each_pair do |k,v|
53
+ next if config_env['redis'].has_key?(k) && (config_env['redis'][k] &&
54
+ !(config_env['redis'][k].is_a?(String) && config_env['redis'][k].empty?))
55
+ config_env['redis'][k] = v
56
+ end
57
+
58
+ config_env
59
+ end
8
60
 
9
61
  end
10
62
 
@@ -9,9 +9,8 @@ module Flapjack
9
9
  # takes a check, looks up contacts that are interested in this check (or in the check's entity)
10
10
  # and returns an array of contact ids
11
11
  def self.find_all_for_entity_check(entity_check, options = {})
12
- logger = options[:logger]
13
- logger = nil
14
12
  raise "Redis connection not set" unless redis = options[:redis]
13
+ logger = options[:logger]
15
14
 
16
15
  entity = entity_check.entity
17
16
  check = entity_check.check
@@ -26,16 +25,38 @@ module Flapjack
26
25
  union
27
26
  end
28
27
 
29
- def self.pagerduty_credentials_for_contact(contact, options = {})
30
- logger = options[:logger]
28
+ # NB: should probably be called in the context of a Redis multi block; not doing so
29
+ # here as calling classes may well be adding/updating multiple records in the one
30
+ # operation
31
+ def self.add(contact, options = {})
31
32
  raise "Redis connection not set" unless redis = options[:redis]
32
33
 
33
- service_key = redis.hget("contact_media:#{contact}", 'pagerduty')
34
- return nil unless service_key
34
+ redis.del("contact:#{contact['id']}")
35
+ redis.del("contact_media:#{contact['id']}")
36
+ 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'])
40
+ contact['media'].each_pair {|medium, address|
41
+ case medium
42
+ when 'pagerduty'
43
+ redis.hset("contact_media:#{contact['id']}", medium, address['service_key'])
44
+ redis.hset("contact_pagerduty:#{contact['id']}", 'subdomain', address['subdomain'])
45
+ redis.hset("contact_pagerduty:#{contact['id']}", 'username', address['username'])
46
+ redis.hset("contact_pagerduty:#{contact['id']}", 'password', address['password'])
47
+ else
48
+ redis.hset("contact_media:#{contact['id']}", medium, address)
49
+ end
50
+ }
51
+ end
52
+
53
+ def self.pagerduty_credentials_for_contact(contact, options = {})
54
+ raise "Redis connection not set" unless redis = options[:redis]
35
55
 
36
- deets = redis.hgetall("contact_pagerduty:#{contact}")
37
- return deets.merge('service_key' => service_key)
56
+ return unless service_key = redis.hget("contact_media:#{contact}", 'pagerduty')
38
57
 
58
+ redis.hgetall("contact_pagerduty:#{contact}").
59
+ merge('service_key' => service_key)
39
60
  end
40
61
 
41
62
  end
@@ -16,12 +16,14 @@ module Flapjack
16
16
  }
17
17
  end
18
18
 
19
+ # NB: should probably be called in the context of a Redis multi block; not doing so
20
+ # here as calling classes may well be adding/updating multiple records in the one
21
+ # operation
19
22
  def self.add(entity, options = {})
20
23
  raise "Redis connection not set" unless redis = options[:redis]
21
24
  raise "Entity name not provided" unless entity['name'] && !entity['name'].empty?
22
25
 
23
26
  if entity['id']
24
- redis.multi
25
27
  existing_name = redis.hget("entity:#{entity['id']}", 'name')
26
28
  redis.del("entity_id:#{existing_name}") unless existing_name == entity['name']
27
29
  redis.set("entity_id:#{entity['name']}", entity['id'])
@@ -33,7 +35,6 @@ module Flapjack
33
35
  redis.sadd("contacts_for:#{entity['id']}", contact)
34
36
  }
35
37
  end
36
- redis.exec
37
38
  else
38
39
  # empty string is the redis equivalent of a Ruby nil, i.e. key with
39
40
  # no value
@@ -45,6 +45,17 @@ module Flapjack
45
45
  opts[:persistence].llen('events')
46
46
  end
47
47
 
48
+ # FIXME make this use a logger taken from the opts
49
+ def self.purge_all(opts = {})
50
+ events_size = opts[:redis].llen('events')
51
+ puts "purging #{events_size} events..."
52
+ timestamp = Time.now.to_i
53
+ puts "renaming events to events.#{timestamp}"
54
+ opts[:redis].rename('events', "events.#{timestamp}")
55
+ puts "setting expiry of events.#{timestamp} to 8 hours"
56
+ opts[:redis].expire("events.#{timestamp}", (60 * 60 * 8))
57
+ end
58
+
48
59
  def initialize(attrs={})
49
60
  @attrs = attrs
50
61
  @attrs['time'] = Time.now.to_i unless @attrs.has_key?('time')
@@ -283,9 +283,6 @@ module Flapjack
283
283
  close # Blather::Client.close
284
284
  end
285
285
  end
286
- # FIXME: should we also set something so should_quit? returns true
287
- # to prevent retrieving more notifications from the queue while closing?
288
- # or does close only return once the connection is really and truely closed?
289
286
  else
290
287
  entity, check = event['event_id'].split(':')
291
288
  state = event['state']
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.6.29"
4
+ VERSION = "0.6.30"
5
5
  end
data/lib/flapjack/web.rb CHANGED
@@ -18,8 +18,8 @@ module Flapjack
18
18
  # doesn't work with Rack::Test for some reason
19
19
  unless 'test'.eql?(FLAPJACK_ENV)
20
20
  rescue_exception = Proc.new { |env, exception|
21
- p exception.message
22
- puts exception.backtrace.join("\n")
21
+ logger.error exception.message
22
+ logger.error exception.backtrace.join("\n")
23
23
  [503, {}, exception.message]
24
24
  }
25
25
 
@@ -104,10 +104,13 @@ describe 'Flapjack::API::EntityCheck::Presenter' do
104
104
  ecp = Flapjack::API::EntityCheckPresenter.new(entity_check)
105
105
  downtimes = ecp.downtime(time - (12 * 60 * 60), time)
106
106
 
107
+
107
108
  # 22 minutes, 3 + 8 + 11
108
109
  downtimes.should be_a(Hash)
109
- downtimes[:total_seconds].should == (22 * 60)
110
- downtimes[:percentage].should == (((22 * 60) * 100) / (12 * 60 * 60))
110
+ downtimes[:total_seconds].should == {'critical' => (22 * 60),
111
+ 'ok' => ((12 * 60 * 60) - (22 * 60))}
112
+ downtimes[:percentages].should == {'critical' => (((22 * 60) * 100.0) / (12 * 60 * 60)),
113
+ 'ok' => ((((12 * 60 * 60) - (22 * 60)) * 100.0) / (12 * 60 *60))}
111
114
  downtimes[:downtime].should be_an(Array)
112
115
  # the last outage gets split by the intervening maintenance period,
113
116
  # but the fully covered one gets removed.
@@ -34,10 +34,9 @@ describe Flapjack::Executive, :redis => true do
34
34
  shutdown_evt.should_receive(:time).and_return(Time.now)
35
35
  Flapjack::Data::Event.should_receive(:next).and_return(shutdown_evt)
36
36
 
37
- EventMachine::Synchrony::ConnectionPool.should_receive(:new).and_return(@redis)
38
-
39
37
  executive = Flapjack::Executive.new
40
38
  executive.bootstrap(:config => {})
39
+ executive.should_receive(:build_redis_connection_pool).and_return(@redis)
41
40
 
42
41
  # hacky, but the behaviour it's mimicking (shutdown from another thread) isn't
43
42
  # conducive to nice tests
@@ -139,7 +139,7 @@ describe Flapjack::Jabber do
139
139
 
140
140
  fj.should_receive(:connect)
141
141
  fj.should_receive(:connected?).exactly(3).times.and_return(true)
142
- fj.should_receive(:should_quit?).exactly(3).times.and_return(false, false, true)
142
+ fj.should_receive(:should_quit?).exactly(4).times.and_return(false, false, true)
143
143
  redis.should_receive(:blpop).twice.and_return(
144
144
  ["jabber_notifications", %q{{"notification_type":"problem","event_id":"main-example.com:ping","state":"critical","summary":"!!!"}}],
145
145
  ["jabber_notifications", %q{{"notification_type":"shutdown"}}]
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.29
4
+ version: 0.6.30
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-21 00:00:00.000000000 Z
14
+ date: 2012-09-24 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: daemons