flapjack 0.6.53 → 0.6.54
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/bin/flapjack +103 -19
- data/bin/flapjack-nagios-receiver +166 -52
- data/bin/flapper +107 -18
- data/etc/flapjack_config.yaml.example +16 -0
- data/features/events.feature +63 -0
- data/features/steps/events_steps.rb +5 -5
- data/features/steps/notifications_steps.rb +8 -6
- data/features/steps/time_travel_steps.rb +4 -4
- data/features/support/env.rb +1 -2
- data/flapjack.gemspec +1 -1
- data/lib/flapjack/configuration.rb +11 -13
- data/lib/flapjack/coordinator.rb +100 -220
- data/lib/flapjack/data/entity_check.rb +2 -2
- data/lib/flapjack/data/event.rb +3 -3
- data/lib/flapjack/executive.rb +30 -40
- data/lib/flapjack/filters/delays.rb +1 -1
- data/lib/flapjack/gateways/api.rb +6 -23
- data/lib/flapjack/gateways/email.rb +4 -10
- data/lib/flapjack/gateways/email/alert.html.haml +0 -5
- data/lib/flapjack/gateways/email/alert.text.erb +0 -1
- data/lib/flapjack/gateways/jabber.rb +80 -67
- data/lib/flapjack/gateways/oobetet.rb +29 -25
- data/lib/flapjack/gateways/pagerduty.rb +26 -45
- data/lib/flapjack/gateways/sms_messagenet.rb +10 -17
- data/lib/flapjack/gateways/web.rb +7 -21
- data/lib/flapjack/gateways/web/views/_css.haml +3 -0
- data/lib/flapjack/gateways/web/views/check.haml +1 -1
- data/lib/flapjack/logger.rb +57 -0
- data/lib/flapjack/patches.rb +0 -10
- data/lib/flapjack/pikelet.rb +214 -30
- data/lib/flapjack/redis_pool.rb +2 -17
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +116 -136
- data/spec/lib/flapjack/data/entity_check_spec.rb +3 -3
- data/spec/lib/flapjack/executive_spec.rb +33 -34
- data/spec/lib/flapjack/gateways/api_spec.rb +4 -2
- data/spec/lib/flapjack/gateways/jabber_spec.rb +39 -36
- data/spec/lib/flapjack/gateways/oobetet_spec.rb +14 -24
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +43 -45
- data/spec/lib/flapjack/gateways/web_spec.rb +42 -35
- data/spec/lib/flapjack/logger_spec.rb +32 -0
- data/spec/lib/flapjack/pikelet_spec.rb +124 -15
- data/spec/lib/flapjack/redis_pool_spec.rb +1 -3
- data/spec/spec_helper.rb +34 -1
- data/tasks/events.rake +1 -0
- data/tmp/create_event_ok.rb +31 -0
- data/tmp/create_event_unknown.rb +31 -0
- data/tmp/create_events_ok.rb +1 -1
- metadata +10 -11
- data/bin/flapjack-nagios-receiver-control +0 -15
- data/bin/flapper-control +0 -15
- data/lib/flapjack/daemonizing.rb +0 -186
- data/lib/flapjack/gateways/base.rb +0 -38
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'log4r'
|
4
|
+
require 'log4r/formatter/patternformatter'
|
5
|
+
require 'log4r/outputter/consoleoutputters'
|
6
|
+
require 'log4r/outputter/syslogoutputter'
|
7
|
+
|
8
|
+
module Flapjack
|
9
|
+
|
10
|
+
class Logger
|
11
|
+
|
12
|
+
def initialize(name, config = {})
|
13
|
+
config ||= {}
|
14
|
+
|
15
|
+
# @name = name
|
16
|
+
|
17
|
+
@log4r_logger = Log4r::Logger.new(name)
|
18
|
+
|
19
|
+
formatter = Log4r::PatternFormatter.new(:pattern => "%d [%l] :: #{name} :: %m",
|
20
|
+
:date_pattern => "%Y-%m-%dT%H:%M:%S%z")
|
21
|
+
|
22
|
+
[Log4r::StdoutOutputter, Log4r::SyslogOutputter].each do |outp_klass|
|
23
|
+
outp = outp_klass.new(name)
|
24
|
+
outp.formatter = formatter
|
25
|
+
@log4r_logger.add(outp)
|
26
|
+
end
|
27
|
+
|
28
|
+
configure(config)
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure(config)
|
32
|
+
level = config['level']
|
33
|
+
|
34
|
+
# we'll let Log4r spit the dummy on invalid level values -- but will
|
35
|
+
# assume ALL if nothing is provided
|
36
|
+
if level.nil? || level.empty?
|
37
|
+
level = 'ALL'
|
38
|
+
end
|
39
|
+
|
40
|
+
new_level = Log4r.const_get(level.upcase)
|
41
|
+
return if @log4r_logger.level.eql?(new_level)
|
42
|
+
|
43
|
+
# puts "setting log level for '#{@name}' to '#{level.upcase}'"
|
44
|
+
@log4r_logger.level = new_level
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(method, *args, &block)
|
48
|
+
@log4r_logger.send(method.to_sym, *args, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def respond_to?(sym)
|
52
|
+
@log4r_logger.respond_to?(sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/lib/flapjack/patches.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'ostruct'
|
4
|
-
require 'daemons'
|
5
4
|
require 'thin'
|
6
5
|
require 'resque'
|
7
6
|
# require 'log4r'
|
@@ -12,15 +11,6 @@ class OpenStruct
|
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
|
-
module Daemons
|
16
|
-
class PidFile
|
17
|
-
# we override this method so creating pid files is fork-safe
|
18
|
-
def filename
|
19
|
-
File.join(@dir, "#{@progname}#{Process.pid}.pid")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
14
|
#module Log4r
|
25
15
|
# class Logger
|
26
16
|
# def error(args)
|
data/lib/flapjack/pikelet.rb
CHANGED
@@ -8,55 +8,239 @@
|
|
8
8
|
# with butter, at afternoon tea, but can also be served at morning tea."
|
9
9
|
# from http://en.wikipedia.org/wiki/Pancake
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
require '
|
11
|
+
# the redis/synchrony gems need to be required in this particular order, see
|
12
|
+
# the redis-rb README for details
|
13
|
+
require 'hiredis'
|
14
|
+
require 'redis/connection/synchrony'
|
15
|
+
require 'redis'
|
16
|
+
require 'em-resque'
|
17
|
+
require 'em-resque/worker'
|
18
|
+
require 'thin'
|
19
|
+
|
20
|
+
require 'flapjack/executive'
|
21
|
+
require 'flapjack/gateways/api'
|
22
|
+
require 'flapjack/gateways/jabber'
|
23
|
+
require 'flapjack/gateways/oobetet'
|
24
|
+
require 'flapjack/gateways/pagerduty'
|
25
|
+
require 'flapjack/gateways/email'
|
26
|
+
require 'flapjack/gateways/sms_messagenet'
|
27
|
+
require 'flapjack/gateways/web'
|
28
|
+
require 'flapjack/logger'
|
14
29
|
|
15
30
|
module Flapjack
|
31
|
+
|
16
32
|
module Pikelet
|
17
|
-
attr_accessor :logger, :config
|
18
33
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
return if @bootstrapped
|
34
|
+
# TODO find a better way of expressing these two methods
|
35
|
+
def self.is_pikelet?(type)
|
36
|
+
type_klass = [Flapjack::Pikelet::Generic, Flapjack::Pikelet::Resque,
|
37
|
+
Flapjack::Pikelet::Thin].detect do |kl|
|
24
38
|
|
25
|
-
|
26
|
-
@logger = Log4r::Logger.new("#{self.class.to_s.downcase.gsub('::', '-')}")
|
27
|
-
@logger.add(Log4r::StdoutOutputter.new("flapjack"))
|
28
|
-
@logger.add(Log4r::SyslogOutputter.new("flapjack"))
|
29
|
-
end
|
39
|
+
kl::PIKELET_TYPES[type]
|
30
40
|
|
31
|
-
|
41
|
+
end
|
42
|
+
!type_klass.nil?
|
43
|
+
end
|
32
44
|
|
33
|
-
|
45
|
+
def self.create(type, config = {})
|
46
|
+
pikelet = nil
|
47
|
+
[Flapjack::Pikelet::Generic,
|
48
|
+
Flapjack::Pikelet::Resque,
|
49
|
+
Flapjack::Pikelet::Thin].each do |kl|
|
50
|
+
break if pikelet = kl.create(type, config)
|
51
|
+
end
|
52
|
+
pikelet
|
34
53
|
end
|
35
54
|
|
36
|
-
|
37
|
-
|
38
|
-
|
55
|
+
class Base
|
56
|
+
attr_reader :type, :status
|
57
|
+
|
58
|
+
def initialize(type, pikelet_class, opts = {})
|
59
|
+
@type = type
|
60
|
+
@klass = pikelet_class
|
61
|
+
|
62
|
+
@config = opts[:config] || {}
|
63
|
+
@redis_config = opts[:redis_config] || {}
|
64
|
+
|
65
|
+
@logger = Flapjack::Logger.new("flapjack-#{type}", @config['logger'])
|
66
|
+
|
67
|
+
@status = 'initialized'
|
68
|
+
end
|
69
|
+
|
70
|
+
def start
|
71
|
+
@status = 'started'
|
72
|
+
end
|
73
|
+
|
74
|
+
def reload(cfg)
|
75
|
+
@logger.configure(cfg['logger'])
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
79
|
+
def stop
|
80
|
+
@status = 'stopping'
|
81
|
+
end
|
39
82
|
end
|
40
83
|
|
41
|
-
|
84
|
+
class Generic < Flapjack::Pikelet::Base
|
85
|
+
|
86
|
+
PIKELET_TYPES = {'executive' => Flapjack::Executive,
|
87
|
+
'jabber' => Flapjack::Gateways::Jabber,
|
88
|
+
'pagerduty' => Flapjack::Gateways::Pagerduty,
|
89
|
+
'oobetet' => Flapjack::Gateways::Oobetet}
|
90
|
+
|
91
|
+
def self.create(type, config = {})
|
92
|
+
return unless pikelet_klass = PIKELET_TYPES[type]
|
93
|
+
self.new(type, pikelet_klass, config)
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize(type, pikelet_klass, opts = {})
|
97
|
+
super(type, pikelet_klass, opts)
|
98
|
+
@pikelet = @klass.new(opts.merge(:logger => @logger))
|
99
|
+
end
|
42
100
|
|
43
|
-
|
44
|
-
|
101
|
+
def start
|
102
|
+
@fiber = Fiber.new {
|
103
|
+
begin
|
104
|
+
@pikelet.start
|
105
|
+
rescue Exception => e
|
106
|
+
trace = e.backtrace.join("\n")
|
107
|
+
@logger.fatal "#{e.message}\n#{trace}"
|
108
|
+
stop
|
109
|
+
end
|
110
|
+
}
|
111
|
+
super
|
112
|
+
@fiber.resume
|
113
|
+
end
|
114
|
+
|
115
|
+
# this should only reload if all changes can be applied -- will
|
116
|
+
# return false to log warning otherwise
|
117
|
+
def reload(cfg)
|
118
|
+
@pikelet.respond_to?(:reload) ?
|
119
|
+
(@pikelet.reload(cfg) && super(cfg)) : super(cfg)
|
120
|
+
end
|
45
121
|
|
46
|
-
|
47
|
-
|
122
|
+
def stop
|
123
|
+
@pikelet.stop
|
124
|
+
super
|
125
|
+
end
|
126
|
+
|
127
|
+
def update_status
|
128
|
+
return @status unless 'stopping'.eql?(@status)
|
129
|
+
@status = 'stopped' if @fiber && !@fiber.alive?
|
130
|
+
end
|
48
131
|
end
|
49
132
|
|
50
|
-
|
51
|
-
|
133
|
+
class Resque < Flapjack::Pikelet::Base
|
134
|
+
|
135
|
+
PIKELET_TYPES = {'email' => Flapjack::Gateways::Email,
|
136
|
+
'sms' => Flapjack::Gateways::SmsMessagenet}
|
137
|
+
|
138
|
+
def self.create(type, opts = {})
|
139
|
+
return unless pikelet_klass = PIKELET_TYPES[type]
|
140
|
+
self.new(type, pikelet_klass, opts)
|
141
|
+
end
|
142
|
+
|
143
|
+
def initialize(type, pikelet_klass, opts = {})
|
144
|
+
super(type, pikelet_klass, opts)
|
145
|
+
|
146
|
+
pikelet_klass.instance_variable_set('@config', @config)
|
147
|
+
pikelet_klass.instance_variable_set('@redis_config', @redis_config)
|
148
|
+
pikelet_klass.instance_variable_set('@logger', @logger)
|
149
|
+
|
150
|
+
# TODO error if config['queue'].nil?
|
151
|
+
|
152
|
+
@worker = EM::Resque::Worker.new(@config['queue'])
|
153
|
+
# # Use these to debug the resque workers
|
154
|
+
# worker.verbose = true
|
155
|
+
# worker.very_verbose = true
|
156
|
+
end
|
157
|
+
|
158
|
+
def start
|
159
|
+
@fiber = Fiber.new {
|
160
|
+
begin
|
161
|
+
@worker.work(0.1)
|
162
|
+
rescue Exception => e
|
163
|
+
trace = e.backtrace.join("\n")
|
164
|
+
@logger.fatal "#{e.message}\n#{trace}"
|
165
|
+
stop
|
166
|
+
end
|
167
|
+
}
|
168
|
+
super
|
169
|
+
@klass.start if @klass.respond_to?(:start)
|
170
|
+
@fiber.resume
|
171
|
+
end
|
172
|
+
|
173
|
+
# this should only reload if all changes can be applied -- will
|
174
|
+
# return false to log warning otherwise
|
175
|
+
def reload(cfg)
|
176
|
+
@klass.respond_to?(:reload) ?
|
177
|
+
(@klass.reload(cfg) && super(cfg)) : super(cfg)
|
178
|
+
end
|
179
|
+
|
180
|
+
def stop
|
181
|
+
@worker.shutdown if @worker && @fiber && @fiber.alive?
|
182
|
+
@klass.stop if @klass.respond_to?(:stop)
|
183
|
+
super
|
184
|
+
end
|
185
|
+
|
186
|
+
def update_status
|
187
|
+
return @status unless 'stopping'.eql?(@status)
|
188
|
+
@status = 'stopped' if @fiber && !@fiber.alive?
|
189
|
+
end
|
52
190
|
end
|
53
191
|
|
54
|
-
|
192
|
+
class Thin < Flapjack::Pikelet::Base
|
55
193
|
|
56
|
-
|
57
|
-
|
194
|
+
PIKELET_TYPES = {'web' => Flapjack::Gateways::Web,
|
195
|
+
'api' => Flapjack::Gateways::API}
|
58
196
|
|
59
|
-
|
197
|
+
def self.create(type, opts = {})
|
198
|
+
return unless pikelet_klass = PIKELET_TYPES[type]
|
199
|
+
::Thin::Logging.silent = true
|
200
|
+
self.new(type, pikelet_klass, :config => opts[:config], :redis_config => opts[:redis_config])
|
201
|
+
end
|
202
|
+
|
203
|
+
def initialize(type, pikelet_klass, opts = {})
|
204
|
+
super(type, pikelet_klass, opts)
|
205
|
+
|
206
|
+
pikelet_klass.instance_variable_set('@config', @config)
|
207
|
+
pikelet_klass.instance_variable_set('@redis_config', @redis_config)
|
208
|
+
pikelet_klass.instance_variable_set('@logger', @logger)
|
209
|
+
|
210
|
+
if @config
|
211
|
+
@port = @config['port']
|
212
|
+
@port = @port.nil? ? nil : @port.to_i
|
213
|
+
end
|
214
|
+
@port = 3001 if (@port.nil? || @port <= 0 || @port > 65535)
|
215
|
+
|
216
|
+
@server = ::Thin::Server.new('0.0.0.0', @port,
|
217
|
+
@klass, :signals => false)
|
218
|
+
end
|
219
|
+
|
220
|
+
def start
|
221
|
+
super
|
222
|
+
@klass.start if @klass.respond_to?(:start)
|
223
|
+
@server.start
|
224
|
+
end
|
225
|
+
|
226
|
+
# this should only reload if all changes can be applied -- will
|
227
|
+
# return false to log warning otherwise
|
228
|
+
def reload(cfg)
|
229
|
+
# TODO fail if port changes
|
230
|
+
@klass.respond_to?(:reload) ?
|
231
|
+
(@klass.reload(cfg) && super(cfg)) : super(cfg)
|
232
|
+
end
|
233
|
+
|
234
|
+
def stop
|
235
|
+
@server.stop!
|
236
|
+
@klass.stop if @klass.respond_to?(:stop)
|
237
|
+
super
|
238
|
+
end
|
239
|
+
|
240
|
+
def update_status
|
241
|
+
return @status unless 'stopping'.eql?(@status)
|
242
|
+
@status = 'stopped' if (@server.backend.size <= 0)
|
243
|
+
end
|
60
244
|
end
|
61
245
|
|
62
246
|
end
|
data/lib/flapjack/redis_pool.rb
CHANGED
@@ -15,26 +15,11 @@ module Flapjack
|
|
15
15
|
|
16
16
|
def initialize(opts = {})
|
17
17
|
config = opts.delete(:config)
|
18
|
-
|
18
|
+
@size = opts[:size] || 5
|
19
|
+
super(:size => @size) {
|
19
20
|
::Redis.new(config)
|
20
21
|
}
|
21
22
|
end
|
22
23
|
|
23
|
-
def empty!
|
24
|
-
f = Fiber.current
|
25
|
-
|
26
|
-
until @available.empty? && @pending.empty?
|
27
|
-
begin
|
28
|
-
conn = acquire(f)
|
29
|
-
conn.quit
|
30
|
-
@available.delete(conn)
|
31
|
-
ensure
|
32
|
-
if pending = @pending.shift
|
33
|
-
pending.resume
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
24
|
end
|
40
25
|
end
|
data/lib/flapjack/version.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
require 'flapjack/configuration'
|
4
|
-
require 'flapjack/executive'
|
5
|
-
|
6
|
-
require 'flapjack/gateways/web'
|
7
|
-
require 'flapjack/gateways/jabber'
|
8
|
-
require 'flapjack/gateways/email'
|
9
|
-
|
10
3
|
require 'flapjack/coordinator'
|
11
4
|
|
12
5
|
describe Flapjack::Coordinator do
|
@@ -14,57 +7,80 @@ describe Flapjack::Coordinator do
|
|
14
7
|
let(:fiber) { mock(Fiber) }
|
15
8
|
let(:config) { mock(Flapjack::Configuration) }
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
let(:logger) { mock(Logger) }
|
11
|
+
let(:stdout_out) { mock('stdout_out') }
|
12
|
+
let(:syslog_out) { mock('syslog_out') }
|
13
|
+
|
14
|
+
def setup_logger
|
15
|
+
formatter = mock('Formatter')
|
16
|
+
Log4r::PatternFormatter.should_receive(:new).with(
|
17
|
+
:pattern => "%d [%l] :: flapjack-coordinator :: %m",
|
18
|
+
:date_pattern => "%Y-%m-%dT%H:%M:%S%z").and_return(formatter)
|
19
|
+
|
20
|
+
stdout_out.should_receive(:formatter=).with(formatter)
|
21
|
+
syslog_out.should_receive(:formatter=).with(formatter)
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
Log4r::StdoutOutputter.should_receive(:new).and_return(stdout_out)
|
24
|
+
Log4r::SyslogOutputter.should_receive(:new).and_return(syslog_out)
|
25
|
+
logger.should_receive(:add).with(stdout_out)
|
26
|
+
logger.should_receive(:add).with(syslog_out)
|
27
|
+
Log4r::Logger.should_receive(:new).and_return(logger)
|
25
28
|
end
|
26
29
|
|
27
|
-
it "
|
30
|
+
it "starts and stops a pikelet" do
|
31
|
+
setup_logger
|
32
|
+
|
33
|
+
cfg = {'executive' => {'enabled' => 'yes'}}
|
28
34
|
EM.should_receive(:synchrony).and_yield
|
29
35
|
config.should_receive(:for_redis).and_return({})
|
30
|
-
config.should_receive(:all).and_return(
|
36
|
+
config.should_receive(:all).and_return(cfg)
|
37
|
+
|
38
|
+
executive = mock('executive')
|
39
|
+
executive.should_receive(:start)
|
40
|
+
executive.should_receive(:stop)
|
41
|
+
executive.should_receive(:update_status)
|
42
|
+
executive.should_receive(:status).exactly(3).times.and_return('stopped')
|
31
43
|
|
32
44
|
fc = Flapjack::Coordinator.new(config)
|
33
|
-
|
34
|
-
|
35
|
-
end
|
45
|
+
Flapjack::Pikelet.should_receive(:create).with('executive',
|
46
|
+
:config => cfg['executive'], :redis_config => {}).and_return(executive)
|
36
47
|
|
37
|
-
|
38
|
-
|
48
|
+
fiber.should_receive(:resume)
|
49
|
+
Fiber.should_receive(:new).and_yield.and_return(fiber)
|
39
50
|
|
40
|
-
|
41
|
-
config.should_receive(:all).and_return('executive' => {'enabled' => 'yes'})
|
51
|
+
EM.should_receive(:stop)
|
42
52
|
|
43
|
-
fc
|
44
|
-
fc.
|
45
|
-
fc.after_daemonize
|
53
|
+
fc.start(:signals => false)
|
54
|
+
fc.stop
|
46
55
|
end
|
47
56
|
|
48
57
|
it "traps system signals and shuts down" do
|
58
|
+
setup_logger
|
59
|
+
|
49
60
|
RbConfig::CONFIG.should_receive(:[]).with('host_os').and_return('darwin12.0.0')
|
50
61
|
|
51
62
|
Kernel.should_receive(:trap).with('INT').and_yield
|
52
63
|
Kernel.should_receive(:trap).with('TERM').and_yield
|
53
64
|
Kernel.should_receive(:trap).with('QUIT').and_yield
|
65
|
+
Kernel.should_receive(:trap).with('HUP').and_yield
|
54
66
|
|
55
67
|
config.should_receive(:for_redis).and_return({})
|
56
68
|
fc = Flapjack::Coordinator.new(config)
|
57
69
|
fc.should_receive(:stop).exactly(3).times
|
70
|
+
fc.should_receive(:reload)
|
58
71
|
|
59
72
|
fc.send(:setup_signals)
|
60
73
|
end
|
61
74
|
|
62
75
|
it "only traps two system signals on Windows" do
|
76
|
+
setup_logger
|
77
|
+
|
63
78
|
RbConfig::CONFIG.should_receive(:[]).with('host_os').and_return('mswin')
|
64
79
|
|
65
80
|
Kernel.should_receive(:trap).with('INT').and_yield
|
66
81
|
Kernel.should_receive(:trap).with('TERM').and_yield
|
67
82
|
Kernel.should_not_receive(:trap).with('QUIT')
|
83
|
+
Kernel.should_not_receive(:trap).with('HUP')
|
68
84
|
|
69
85
|
config.should_receive(:for_redis).and_return({})
|
70
86
|
fc = Flapjack::Coordinator.new(config)
|
@@ -73,145 +89,109 @@ describe Flapjack::Coordinator do
|
|
73
89
|
fc.send(:setup_signals)
|
74
90
|
end
|
75
91
|
|
76
|
-
it "stops
|
77
|
-
|
78
|
-
fiber_rsq = mock('fiber_rsq')
|
79
|
-
|
80
|
-
exec = mock('executive')
|
81
|
-
exec.should_receive(:is_a?).with(Flapjack::GenericPikelet).twice.and_return(true)
|
82
|
-
exec.should_receive(:stop)
|
83
|
-
exec.should_receive(:add_shutdown_event)
|
84
|
-
exec.should_receive(:cleanup)
|
85
|
-
|
86
|
-
email = mock('worker')
|
87
|
-
email.should_receive(:is_a?).with(Flapjack::GenericPikelet).twice.and_return(false)
|
88
|
-
email.should_receive(:shutdown)
|
89
|
-
Flapjack::Gateways::Email.should_receive(:cleanup)
|
90
|
-
|
91
|
-
backend = mock('backend')
|
92
|
-
backend.should_receive(:size).twice.and_return(1, 0)
|
93
|
-
web = mock('web')
|
94
|
-
web.should_receive(:is_a?).with(Flapjack::GenericPikelet).twice.and_return(false)
|
95
|
-
web.should_receive(:backend).twice.and_return(backend)
|
96
|
-
web.should_receive(:stop!)
|
97
|
-
Flapjack::Gateways::Web.should_receive(:cleanup)
|
98
|
-
|
99
|
-
redis = mock('redis')
|
100
|
-
redis.should_receive(:quit)
|
101
|
-
Redis.should_receive(:new).and_return(redis)
|
92
|
+
it "stops one pikelet and starts another on reload" do
|
93
|
+
setup_logger
|
102
94
|
|
103
|
-
|
104
|
-
|
105
|
-
fiber_stop.should_receive(:resume)
|
106
|
-
Fiber.should_receive(:new).twice.and_yield.and_return(fiber, fiber_stop)
|
95
|
+
old_cfg = {'executive' => {'enabled' => 'yes'}}
|
96
|
+
new_cfg = {'gateways' => {'jabber' => {'enabled' => 'yes'}}}
|
107
97
|
|
108
|
-
|
109
|
-
|
98
|
+
new_config = mock('new_config')
|
99
|
+
filename = mock('filename')
|
110
100
|
|
111
|
-
|
112
|
-
|
101
|
+
config.should_receive(:all).and_return(old_cfg)
|
102
|
+
config.should_receive(:filename).and_return(filename)
|
113
103
|
|
114
|
-
|
115
|
-
|
116
|
-
|
104
|
+
Flapjack::Configuration.should_receive(:new).and_return(new_config)
|
105
|
+
new_config.should_receive(:load).with(filename)
|
106
|
+
new_config.should_receive(:all).and_return(new_cfg)
|
117
107
|
|
118
|
-
|
108
|
+
executive = mock('executive')
|
109
|
+
executive.should_receive(:type).twice.and_return('executive')
|
110
|
+
executive.should_receive(:stop)
|
111
|
+
executive.should_receive(:update_status)
|
112
|
+
executive.should_receive(:status).exactly(3).times.and_return('stopped')
|
119
113
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
|
126
|
-
it "creates an executive pikelet" do
|
127
|
-
exec = mock('executive')
|
128
|
-
exec.should_receive(:bootstrap)
|
129
|
-
Flapjack::Executive.should_receive(:new).and_return(exec)
|
130
|
-
exec.should_receive(:is_a?).with(Flapjack::GenericPikelet).and_return(true)
|
131
|
-
exec.should_receive(:main)
|
114
|
+
jabber = mock('jabber')
|
115
|
+
Flapjack::Pikelet.should_receive(:create).with('jabber',
|
116
|
+
:config => {"enabled" => "yes"}, :redis_config => {}).and_return(jabber)
|
117
|
+
jabber.should_receive(:start)
|
132
118
|
|
133
119
|
fiber.should_receive(:resume)
|
134
120
|
Fiber.should_receive(:new).and_yield.and_return(fiber)
|
135
121
|
|
136
122
|
config.should_receive(:for_redis).and_return({})
|
137
|
-
|
138
123
|
fc = Flapjack::Coordinator.new(config)
|
139
|
-
fc.
|
140
|
-
|
141
|
-
pikelets.
|
142
|
-
pikelets.should be_an(Array)
|
143
|
-
pikelets.should have(1).pikelet
|
144
|
-
pikelets.first.should == {:fiber => fiber, :class => Flapjack::Executive, :instance => exec}
|
124
|
+
fc.instance_variable_set('@pikelets', [executive])
|
125
|
+
fc.reload
|
126
|
+
fc.instance_variable_get('@pikelets').should == [jabber]
|
145
127
|
end
|
146
128
|
|
147
|
-
it "
|
148
|
-
|
149
|
-
jabber.should_receive(:bootstrap)
|
150
|
-
Flapjack::Gateways::Jabber.should_receive(:new).and_return(jabber)
|
151
|
-
jabber.should_receive(:is_a?).with(Flapjack::GenericPikelet).and_return(true)
|
152
|
-
jabber.should_receive(:main).and_raise(RuntimeError)
|
129
|
+
it "reloads a pikelet config without restarting it" do
|
130
|
+
setup_logger
|
153
131
|
|
154
|
-
|
155
|
-
|
132
|
+
old_cfg = {'executive' => {'enabled' => 'yes', 'foo' => 'bar'}}
|
133
|
+
new_cfg = {'executive' => {'enabled' => 'yes', 'foo' => 'baz'}}
|
156
134
|
|
157
|
-
|
135
|
+
new_config = mock('new_config')
|
136
|
+
filename = mock('filename')
|
137
|
+
|
138
|
+
config.should_receive(:all).and_return(old_cfg)
|
139
|
+
config.should_receive(:filename).and_return(filename)
|
140
|
+
|
141
|
+
Flapjack::Configuration.should_receive(:new).and_return(new_config)
|
142
|
+
new_config.should_receive(:load).with(filename)
|
143
|
+
new_config.should_receive(:all).and_return(new_cfg)
|
144
|
+
|
145
|
+
executive = mock('executive')
|
146
|
+
executive.should_receive(:type).exactly(3).times.and_return('executive')
|
147
|
+
executive.should_receive(:reload).with(new_cfg['executive']).and_return(true)
|
148
|
+
executive.should_not_receive(:stop)
|
158
149
|
|
150
|
+
config.should_receive(:for_redis).and_return({})
|
159
151
|
fc = Flapjack::Coordinator.new(config)
|
160
|
-
fc.
|
161
|
-
fc.
|
162
|
-
|
163
|
-
pikelets.should_not be_nil
|
164
|
-
pikelets.should be_an(Array)
|
165
|
-
pikelets.should have(1).pikelet
|
166
|
-
pikelets.first.should == {:fiber => fiber, :class => Flapjack::Gateways::Jabber, :instance => jabber}
|
152
|
+
fc.instance_variable_set('@pikelets', [executive])
|
153
|
+
fc.reload
|
154
|
+
fc.instance_variable_get('@pikelets').should == [executive]
|
167
155
|
end
|
168
156
|
|
169
|
-
it "
|
170
|
-
|
171
|
-
Flapjack::RedisPool.should_receive(:new).and_return(redis)
|
172
|
-
Resque.should_receive(:redis=).with(redis)
|
157
|
+
it "reloads a pikelet config while restarting it" do
|
158
|
+
setup_logger
|
173
159
|
|
174
|
-
|
175
|
-
|
176
|
-
worker.should_receive(:work)
|
160
|
+
old_cfg = {'executive' => {'enabled' => 'yes', 'foo' => 'bar'}}
|
161
|
+
new_cfg = {'executive' => {'enabled' => 'yes', 'baz' => 'qux'}}
|
177
162
|
|
178
|
-
|
179
|
-
|
163
|
+
new_config = mock('new_config')
|
164
|
+
filename = mock('filename')
|
180
165
|
|
181
|
-
config.should_receive(:
|
166
|
+
config.should_receive(:all).and_return(old_cfg)
|
167
|
+
config.should_receive(:filename).and_return(filename)
|
182
168
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
pikelets.should_not be_nil
|
187
|
-
pikelets.should be_an(Array)
|
188
|
-
pikelets.should have(1).pikelet
|
189
|
-
pikelets.first.should == {:fiber => fiber, :class => Flapjack::Gateways::Email,
|
190
|
-
:instance => worker}
|
191
|
-
end
|
169
|
+
Flapjack::Configuration.should_receive(:new).and_return(new_config)
|
170
|
+
new_config.should_receive(:load).with(filename)
|
171
|
+
new_config.should_receive(:all).and_return(new_cfg)
|
192
172
|
|
193
|
-
|
194
|
-
|
173
|
+
executive = mock('executive')
|
174
|
+
executive.should_receive(:type).exactly(5).times.and_return('executive')
|
175
|
+
executive.should_receive(:reload).with(new_cfg['executive']).and_return(false)
|
176
|
+
executive.should_receive(:stop)
|
177
|
+
executive.should_receive(:update_status)
|
178
|
+
executive.should_receive(:status).exactly(3).times.and_return('stopped')
|
195
179
|
|
196
|
-
|
197
|
-
|
198
|
-
Thin::Server.should_receive(:new).
|
199
|
-
with(/^(?:\d{1,3}\.){3}\d{1,3}$/, an_instance_of(Fixnum), Flapjack::Gateways::Web, :signals => false).
|
200
|
-
and_return(server)
|
180
|
+
fiber.should_receive(:resume)
|
181
|
+
Fiber.should_receive(:new).and_yield.and_return(fiber)
|
201
182
|
|
202
|
-
|
183
|
+
new_exec = mock('new_executive')
|
184
|
+
new_exec.should_receive(:start)
|
203
185
|
|
204
|
-
|
186
|
+
Flapjack::Pikelet.should_receive(:create).
|
187
|
+
with('executive', :config => new_cfg['executive'], :redis_config => {}).
|
188
|
+
and_return(new_exec)
|
205
189
|
|
190
|
+
config.should_receive(:for_redis).and_return({})
|
206
191
|
fc = Flapjack::Coordinator.new(config)
|
207
|
-
fc.
|
208
|
-
|
209
|
-
pikelets.
|
210
|
-
pikelets.should be_an(Array)
|
211
|
-
pikelets.should have(1).pikelet
|
212
|
-
pikelets.first.should == {:class => Flapjack::Gateways::Web, :instance => server}
|
192
|
+
fc.instance_variable_set('@pikelets', [executive])
|
193
|
+
fc.reload
|
194
|
+
fc.instance_variable_get('@pikelets').should == [new_exec]
|
213
195
|
end
|
214
196
|
|
215
|
-
|
216
|
-
|
217
|
-
end
|
197
|
+
end
|