flapjack 0.9.6 → 1.0.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +6 -0
- data/.travis.yml +20 -16
- data/CHANGELOG.md +11 -25
- data/Dockerfile +8 -0
- data/Gemfile +2 -5
- data/bin/flapjack +24 -213
- data/etc/flapjack_config.yaml.example +6 -30
- data/features/cli.feature +16 -14
- data/features/cli_flapjack-feed-events.feature +12 -13
- data/features/cli_flapjack-nagios-receiver.feature +14 -15
- data/features/cli_flapjack-populator.feature +16 -15
- data/features/cli_flapper.feature +12 -12
- data/features/cli_receive-events.feature +6 -5
- data/features/cli_simulate-failed-check.feature +7 -6
- data/features/steps/cli_steps.rb +2 -2
- data/features/support/env.rb +1 -0
- data/flapjack.gemspec +1 -0
- data/lib/flapjack/cli/flapper.rb +200 -0
- data/lib/flapjack/cli/import.rb +102 -0
- data/lib/flapjack/cli/receiver.rb +656 -0
- data/lib/flapjack/cli/server.rb +256 -0
- data/lib/flapjack/cli/simulate.rb +180 -0
- data/lib/flapjack/configuration.rb +2 -0
- data/lib/flapjack/data/entity_check.rb +5 -22
- data/lib/flapjack/data/event.rb +7 -12
- data/lib/flapjack/gateways/email.rb +4 -1
- data/lib/flapjack/gateways/jabber.rb +12 -36
- data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +5 -3
- data/lib/flapjack/gateways/pagerduty.rb +1 -1
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
- data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
- data/lib/flapjack/gateways/web/views/check.html.erb +7 -7
- data/lib/flapjack/gateways/web/views/checks.html.erb +2 -3
- data/lib/flapjack/gateways/web/views/contact.html.erb +4 -4
- data/lib/flapjack/gateways/web/views/contacts.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/entity.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/layout.erb +10 -10
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +1 -1
- data/lib/flapjack/gateways/web.rb +36 -7
- data/lib/flapjack/pikelet.rb +0 -2
- data/lib/flapjack/processor.rb +3 -1
- data/lib/flapjack/redis_pool.rb +2 -6
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +3 -3
- data/spec/lib/flapjack/data/entity_check_spec.rb +2 -6
- data/spec/lib/flapjack/data/event_spec.rb +0 -31
- data/spec/lib/flapjack/gateways/email_spec.rb +109 -0
- data/spec/lib/flapjack/gateways/jabber_spec.rb +18 -16
- data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +12 -24
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web_spec.rb +194 -145
- data/spec/lib/flapjack/redis_pool_spec.rb +0 -1
- data/spec/support/profile_all_formatter.rb +44 -0
- data/spec/support/uncolored_doc_formatter.rb +9 -0
- data/tasks/benchmarks.rake +0 -4
- metadata +28 -38
- data/.ruby-version +0 -1
- data/Gemfile-ruby1.9 +0 -28
- data/Gemfile-ruby1.9.lock +0 -227
- data/bin/flapjack-feed-events +0 -124
- data/bin/flapjack-nagios-receiver +0 -246
- data/bin/flapjack-nsca-receiver +0 -246
- data/bin/flapjack-populator +0 -132
- data/bin/flapper +0 -152
- data/bin/receive-events +0 -179
- data/bin/simulate-failed-check +0 -151
- data/lib/flapjack/data/migration.rb +0 -36
- data/lib/flapjack/gateways/api/contact_methods.rb +0 -369
- data/lib/flapjack/gateways/api/entity_check_presenter.rb +0 -218
- data/lib/flapjack/gateways/api/entity_methods.rb +0 -361
- data/lib/flapjack/gateways/api/entity_presenter.rb +0 -75
- data/lib/flapjack/gateways/api/rack/json_params_parser.rb +0 -26
- data/lib/flapjack/gateways/api.rb +0 -124
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +0 -772
- data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +0 -211
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +0 -863
- data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +0 -108
- data/spec/lib/flapjack/gateways/api_spec.rb +0 -30
data/bin/flapjack-nsca-receiver
DELETED
@@ -1,246 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# Nagios.cfg should be enabled with a command_file:
|
4
|
-
#
|
5
|
-
# command_file=/var/lib/nagios3/rw/nagios.cmd
|
6
|
-
#
|
7
|
-
# The format this script expects looks like:
|
8
|
-
# [$TIMET] PROCESS_SERVICE_CHECK_RESULT;$HOSTNAME$;$SERVICEDESC$;$SERVICESTATE$;$SERVICEOUTPUT$;$SERVICEPERFDATA$
|
9
|
-
#
|
10
|
-
|
11
|
-
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
12
|
-
$: << File.dirname(__FILE__) + '/../lib'
|
13
|
-
end
|
14
|
-
|
15
|
-
require 'optparse'
|
16
|
-
require 'ostruct'
|
17
|
-
require 'redis'
|
18
|
-
|
19
|
-
require 'oj'
|
20
|
-
Oj.default_options = { :indent => 0, :mode => :strict }
|
21
|
-
|
22
|
-
require 'dante'
|
23
|
-
|
24
|
-
require 'flapjack/configuration'
|
25
|
-
require 'flapjack/data/event'
|
26
|
-
|
27
|
-
# Nsca example line for a storage-device check:
|
28
|
-
#[1393410685] PROCESS_SERVICE_CHECK_RESULT;db1.dev;STORAGE;0;Raid Set # 000 (800.0GB) is Normal.
|
29
|
-
|
30
|
-
def process_input(opts)
|
31
|
-
redis = opts[:redis]
|
32
|
-
fifo = File.new(opts[:fifo])
|
33
|
-
begin
|
34
|
-
while line = fifo.gets
|
35
|
-
skip unless line
|
36
|
-
split_line = line.split(" ")
|
37
|
-
|
38
|
-
timestamp, passivecheck = split_line
|
39
|
-
split_passive = passivecheck.split(";")
|
40
|
-
timestamp = timestamp.delete('[]')
|
41
|
-
|
42
|
-
check_long_output = ''
|
43
|
-
object_type, entity, check, state, check_output = split_passive
|
44
|
-
|
45
|
-
case
|
46
|
-
when (split_line.length < 2 || split_passive.length < 5)
|
47
|
-
puts "ERROR - rejecting this line; illegal format: [#{line}]"
|
48
|
-
next
|
49
|
-
when (timestamp !~ /^\d+$/)
|
50
|
-
puts "ERROR - rejecting this line; timestamp look like a timestamp: [#{line}]"
|
51
|
-
next
|
52
|
-
when (object_type != 'PROCESS_SERVICE_CHECK_RESULT')
|
53
|
-
puts "ERROR - rejecting this line; identifier 'PROCESS_SERVICE_CHECK_RESULT' is missing: [#{line}]"
|
54
|
-
next
|
55
|
-
end
|
56
|
-
|
57
|
-
puts "#{object_type}, #{timestamp}, #{entity}, #{check}, #{state}, #{check_output}"
|
58
|
-
|
59
|
-
state = {'0' => 'ok', '1' => 'warning', '2' => 'critical'}[state.downcase] || 'unknown'
|
60
|
-
event = {
|
61
|
-
'entity' => entity,
|
62
|
-
'check' => check,
|
63
|
-
'type' => 'service',
|
64
|
-
'state' => state,
|
65
|
-
'summary' => check_output,
|
66
|
-
'details' => nil,
|
67
|
-
'time' => timestamp,
|
68
|
-
}
|
69
|
-
Flapjack::Data::Event.add(event, :redis => redis)
|
70
|
-
end
|
71
|
-
rescue Redis::CannotConnectError
|
72
|
-
puts "Error, unable to to connect to the redis server (#{$!})"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def main(opts)
|
77
|
-
fifo = opts[:fifo]
|
78
|
-
redis = Redis.new(opts[:redis_options])
|
79
|
-
while true
|
80
|
-
process_input(:redis => redis, :fifo => fifo)
|
81
|
-
puts "Whoops with the fifo, restarting main loop in 10 seconds"
|
82
|
-
sleep 10
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
options = OpenStruct.new
|
87
|
-
options.config = Flapjack::Configuration::DEFAULT_CONFIG_PATH
|
88
|
-
options.daemonize = nil
|
89
|
-
|
90
|
-
exe = File.basename(__FILE__)
|
91
|
-
|
92
|
-
optparse = OptionParser.new do |opts|
|
93
|
-
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
94
|
-
|
95
|
-
opts.separator ""
|
96
|
-
opts.separator "Commands"
|
97
|
-
opts.separator " start #{" " * 25} start #{exe}"
|
98
|
-
opts.separator " stop #{" " * 26} stop #{exe}"
|
99
|
-
opts.separator " restart #{" " * 23} (re)start #{exe}"
|
100
|
-
opts.separator " status #{" " * 24} see if #{exe} is running"
|
101
|
-
opts.separator ""
|
102
|
-
opts.separator "Options"
|
103
|
-
|
104
|
-
opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
|
105
|
-
options.config = c
|
106
|
-
end
|
107
|
-
|
108
|
-
opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f|
|
109
|
-
options.fifo = f
|
110
|
-
end
|
111
|
-
|
112
|
-
opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
|
113
|
-
options.daemonize = d
|
114
|
-
end
|
115
|
-
|
116
|
-
opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |pid|
|
117
|
-
options.pidfile = pid
|
118
|
-
end
|
119
|
-
|
120
|
-
opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
|
121
|
-
options.logfile = l
|
122
|
-
end
|
123
|
-
|
124
|
-
opts.on_tail("-h", "--help", "Show this usage message") do
|
125
|
-
puts opts
|
126
|
-
puts '
|
127
|
-
Required Nagios Configuration Changes
|
128
|
-
-------------------------------------
|
129
|
-
|
130
|
-
flapjack-nsca-receiver reads events from the nagios "command file" read from by Nagios, written to by the Nsca-daemon.
|
131
|
-
|
132
|
-
The named pipe is automatically created by _nagios_ if it is enabled
|
133
|
-
in the configfile:
|
134
|
-
|
135
|
-
# modified lines:
|
136
|
-
command_file=/var/lib/nagios3/rw/nagios.cmd
|
137
|
-
|
138
|
-
The Nsca daemon is optionally writing to a tempfile if the named pipe does
|
139
|
-
not exist.
|
140
|
-
|
141
|
-
Details on the wiki: https://github.com/flapjack/flapjack/wiki/USING#XXX
|
142
|
-
'
|
143
|
-
|
144
|
-
exit
|
145
|
-
end
|
146
|
-
|
147
|
-
end
|
148
|
-
optparse.parse!(ARGV)
|
149
|
-
|
150
|
-
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'production'
|
151
|
-
|
152
|
-
config = Flapjack::Configuration.new
|
153
|
-
config.load(options.config)
|
154
|
-
config_env = config.all
|
155
|
-
redis_options = config.for_redis
|
156
|
-
|
157
|
-
if config_env.nil? || config_env.empty?
|
158
|
-
puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
|
159
|
-
puts optparse
|
160
|
-
exit 1
|
161
|
-
end
|
162
|
-
|
163
|
-
config_nr = config_env['nsca-receiver'] || {}
|
164
|
-
|
165
|
-
pidfile = options.pidfile.nil? ?
|
166
|
-
(config_nr['pid_file'] || "/var/run/flapjack/#{exe}.pid") :
|
167
|
-
options.pidfile
|
168
|
-
|
169
|
-
logfile = options.logfile.nil? ?
|
170
|
-
(config_nr['log_file'] || "/var/log/flapjack/#{exe}.log") :
|
171
|
-
options.logfile
|
172
|
-
|
173
|
-
fifo = options.fifo.nil? ?
|
174
|
-
(config_nr['fifo'] || '/var/lib/nagios3/rw/nagios.cmd') :
|
175
|
-
options.fifo
|
176
|
-
|
177
|
-
daemonize = options.daemonize.nil? ?
|
178
|
-
!!config_nr['daemonize'] :
|
179
|
-
options.daemonize
|
180
|
-
|
181
|
-
|
182
|
-
runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
|
183
|
-
case ARGV[0]
|
184
|
-
when "start", "restart"
|
185
|
-
unless File.exist?(fifo)
|
186
|
-
raise "No fifo (named pipe) file found at #{fifo}"
|
187
|
-
end
|
188
|
-
unless File.pipe?(fifo)
|
189
|
-
raise "The file at #{fifo} is not a named pipe, try using mkfifo to make one"
|
190
|
-
end
|
191
|
-
unless File.readable?(fifo)
|
192
|
-
raise "The fifo (named pipe) at #{fifo} is unreadable"
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
case ARGV[0]
|
197
|
-
when "start"
|
198
|
-
if runner.daemon_running?
|
199
|
-
puts "#{exe} is already running."
|
200
|
-
exit 1
|
201
|
-
else
|
202
|
-
print "#{exe} starting..."
|
203
|
-
runner.execute(:daemonize => daemonize) {
|
204
|
-
main(:redis_options => redis_options, :fifo => fifo)
|
205
|
-
}
|
206
|
-
puts " done."
|
207
|
-
end
|
208
|
-
|
209
|
-
when "stop"
|
210
|
-
if runner.daemon_running?
|
211
|
-
print "#{exe} stopping..."
|
212
|
-
runner.execute(:kill => true)
|
213
|
-
puts " done."
|
214
|
-
else
|
215
|
-
puts "#{exe} is not running."
|
216
|
-
exit 1
|
217
|
-
end
|
218
|
-
|
219
|
-
when "restart"
|
220
|
-
print "#{exe} restarting..."
|
221
|
-
runner.execute(:daemonize => true, :restart => true) {
|
222
|
-
main(:redis_options => redis_options, :fifo => fifo)
|
223
|
-
}
|
224
|
-
puts " done."
|
225
|
-
|
226
|
-
when "status"
|
227
|
-
uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
|
228
|
-
if runner.daemon_running?
|
229
|
-
puts "#{exe} is running: #{uptime}"
|
230
|
-
else
|
231
|
-
puts "#{exe} is not running"
|
232
|
-
exit 3
|
233
|
-
end
|
234
|
-
|
235
|
-
else
|
236
|
-
if ARGV.nil? || ARGV.empty?
|
237
|
-
puts "No command provided"
|
238
|
-
else
|
239
|
-
puts "Unknown command provided: '#{ARGV[0]}'"
|
240
|
-
end
|
241
|
-
puts "\n#{optparse}"
|
242
|
-
exit 1
|
243
|
-
|
244
|
-
end
|
245
|
-
|
246
|
-
|
data/bin/flapjack-populator
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
require 'ostruct'
|
5
|
-
|
6
|
-
require 'oj'
|
7
|
-
Oj.default_options = { :indent => 0, :mode => :strict }
|
8
|
-
|
9
|
-
require 'redis'
|
10
|
-
|
11
|
-
# add lib to the default include path
|
12
|
-
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
13
|
-
$: << File.dirname(__FILE__) + '/../lib'
|
14
|
-
end
|
15
|
-
|
16
|
-
require 'flapjack/configuration'
|
17
|
-
require 'flapjack/data/contact'
|
18
|
-
require 'flapjack/data/entity'
|
19
|
-
require 'flapjack/data/event'
|
20
|
-
|
21
|
-
options = OpenStruct.new
|
22
|
-
options.config = Flapjack::Configuration::DEFAULT_CONFIG_PATH
|
23
|
-
|
24
|
-
exe = File.basename(__FILE__)
|
25
|
-
|
26
|
-
optparse = OptionParser.new do |opts|
|
27
|
-
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
28
|
-
|
29
|
-
opts.separator ""
|
30
|
-
opts.separator "Commands:"
|
31
|
-
opts.separator " import-entities"
|
32
|
-
opts.separator " import-contacts"
|
33
|
-
opts.separator " purge-events purge queued monitoring events"
|
34
|
-
opts.separator ""
|
35
|
-
opts.separator "Options"
|
36
|
-
|
37
|
-
opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
|
38
|
-
options.config = c
|
39
|
-
end
|
40
|
-
|
41
|
-
opts.on("-f", "--from [FILE]", String, "path to the FILE to import") do |f|
|
42
|
-
options.from = f
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
optparse.parse!(ARGV)
|
47
|
-
|
48
|
-
bail_with_usage = proc do |message|
|
49
|
-
puts message
|
50
|
-
puts "\n#{optparse}"
|
51
|
-
exit(false)
|
52
|
-
end
|
53
|
-
|
54
|
-
if options.help
|
55
|
-
puts optparse
|
56
|
-
exit
|
57
|
-
elsif options.version
|
58
|
-
puts Flapjack::VERSION
|
59
|
-
exit
|
60
|
-
elsif !["import-contacts", "import-entities", "purge-events"].include?(ARGV[0])
|
61
|
-
message = if ARGV.nil? || ARGV.empty?
|
62
|
-
"No command provided"
|
63
|
-
else
|
64
|
-
"Unknown command provided: '#{ARGV[0]}'"
|
65
|
-
end
|
66
|
-
bail_with_usage.call message
|
67
|
-
end
|
68
|
-
|
69
|
-
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'production'
|
70
|
-
|
71
|
-
config = Flapjack::Configuration.new
|
72
|
-
config.load(options.config)
|
73
|
-
config_env = config.all
|
74
|
-
redis_options = config.for_redis
|
75
|
-
|
76
|
-
if config_env.nil? || config_env.empty?
|
77
|
-
puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
|
78
|
-
exit(false)
|
79
|
-
end
|
80
|
-
|
81
|
-
case ARGV[0]
|
82
|
-
when "import-contacts"
|
83
|
-
unless options.from
|
84
|
-
bail_with_usage.call "No import file provided with --from, eg. --from contacts.json"
|
85
|
-
end
|
86
|
-
contacts = Oj.load(File.new(options.from))
|
87
|
-
|
88
|
-
if contacts && contacts.is_a?(Enumerable) && contacts.any? {|e| !e['id'].nil?}
|
89
|
-
@persistence = Redis.new(redis_options)
|
90
|
-
contacts.each do |contact|
|
91
|
-
unless contact['id']
|
92
|
-
puts "Contact not imported as it has no id: " + contact.inspect
|
93
|
-
next
|
94
|
-
end
|
95
|
-
Flapjack::Data::Contact.add(contact, :redis => @persistence)
|
96
|
-
end
|
97
|
-
@persistence.quit
|
98
|
-
end
|
99
|
-
|
100
|
-
when "import-entities"
|
101
|
-
unless options.from
|
102
|
-
bail_with_usage.call "No import file provided with --from, eg. --from contacts.json"
|
103
|
-
end
|
104
|
-
entities = Oj.load(File.new(options.from))
|
105
|
-
|
106
|
-
if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
|
107
|
-
@persistence = Redis.new(redis_options)
|
108
|
-
entities.each do |entity|
|
109
|
-
unless entity['id']
|
110
|
-
puts "Entity not imported as it has no id: " + entity.inspect
|
111
|
-
next
|
112
|
-
end
|
113
|
-
Flapjack::Data::Entity.add(entity, :redis => @persistence)
|
114
|
-
end
|
115
|
-
@persistence.quit
|
116
|
-
end
|
117
|
-
|
118
|
-
when "purge-events"
|
119
|
-
@persistence = Redis.new(redis_options)
|
120
|
-
events_size = @persistence.llen('events')
|
121
|
-
puts "purging #{events_size} events..."
|
122
|
-
etq = "events.#{Time.now.to_i}"
|
123
|
-
puts "renaming 'events' to '#{etq}'"
|
124
|
-
@persistence.rename('events', etq)
|
125
|
-
puts "setting expiry of '#{etq}' to 8 hours"
|
126
|
-
@persistence.expire(etq, (60 * 60 * 8))
|
127
|
-
@persistence.quit
|
128
|
-
|
129
|
-
else
|
130
|
-
bail_with_usage.call "You need to give me something to do, eg. a command like 'import-entities', 'import-clients', etc."
|
131
|
-
end
|
132
|
-
|
data/bin/flapper
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
require 'ostruct'
|
5
|
-
require 'eventmachine'
|
6
|
-
require 'socket'
|
7
|
-
require 'dante'
|
8
|
-
|
9
|
-
module Flapper
|
10
|
-
def receive_data data
|
11
|
-
send_data ">>>you sent: #{data}"
|
12
|
-
close_connection if data =~ /quit/i
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def local_ip
|
17
|
-
# turn off reverse DNS resolution temporarily
|
18
|
-
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
19
|
-
|
20
|
-
UDPSocket.open do |s|
|
21
|
-
s.connect '64.233.187.99', 1
|
22
|
-
s.addr.last
|
23
|
-
end
|
24
|
-
ensure
|
25
|
-
Socket.do_not_reverse_lookup = orig
|
26
|
-
end
|
27
|
-
|
28
|
-
def main(bind_ip, bind_port, frequency)
|
29
|
-
raise "bind_port must be an integer" unless bind_port.is_a?(Integer)
|
30
|
-
start_every = frequency
|
31
|
-
stop_after = frequency.to_f / 2
|
32
|
-
|
33
|
-
EM.run {
|
34
|
-
|
35
|
-
puts "#{Time.now}: starting server on #{bind_ip}:#{bind_port}"
|
36
|
-
server_init = EM.start_server bind_ip, bind_port, Flapper
|
37
|
-
EM.add_timer(stop_after) do
|
38
|
-
puts "#{Time.now}: stopping server"
|
39
|
-
EM.stop_server(server_init)
|
40
|
-
end
|
41
|
-
|
42
|
-
EM.add_periodic_timer(start_every) do
|
43
|
-
puts "#{Time.now}: starting server on #{bind_ip}:#{bind_port}"
|
44
|
-
server = EM.start_server bind_ip, bind_port, Flapper
|
45
|
-
EM.add_timer(stop_after) do
|
46
|
-
puts "#{Time.now}: stopping server"
|
47
|
-
EM.stop_server(server)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
options = OpenStruct.new
|
54
|
-
options.daemonize = nil
|
55
|
-
|
56
|
-
exe = File.basename(__FILE__)
|
57
|
-
|
58
|
-
OptionParser.new do |opts|
|
59
|
-
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
60
|
-
|
61
|
-
opts.separator ""
|
62
|
-
opts.separator "Commands"
|
63
|
-
opts.separator " start #{" " * 25} start #{exe}"
|
64
|
-
opts.separator " stop #{" " * 26} stop #{exe}"
|
65
|
-
opts.separator " restart #{" " * 23} (re)start #{exe}"
|
66
|
-
opts.separator " status #{" " * 24} see if #{exe} is running"
|
67
|
-
opts.separator ""
|
68
|
-
opts.separator "Options"
|
69
|
-
|
70
|
-
opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
|
71
|
-
options.daemonize = d
|
72
|
-
end
|
73
|
-
|
74
|
-
opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |pid|
|
75
|
-
options.pidfile = pid
|
76
|
-
end
|
77
|
-
|
78
|
-
opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
|
79
|
-
options.log_path = l
|
80
|
-
end
|
81
|
-
|
82
|
-
opts.on("-b", "--bind-ip [ADDRESS]", String, "ADDRESS (IPv4 or IPv6) for flapper to bind to") do |b|
|
83
|
-
options.bind_ip = b
|
84
|
-
end
|
85
|
-
|
86
|
-
opts.on("-P", "--bind-port [PORT]", String, "PORT for flapper to bind to (default: 12345)") do |p|
|
87
|
-
options.bind_port = p.to_i
|
88
|
-
end
|
89
|
-
|
90
|
-
opts.on("-f", "--frequency [SECONDS]", String, "oscillate with a frequency of SECONDS [120]") do |f|
|
91
|
-
options.frequency = f.to_f
|
92
|
-
end
|
93
|
-
|
94
|
-
end.parse!(ARGV)
|
95
|
-
|
96
|
-
daemonize = options.daemonize.nil? ? true : options.daemonize
|
97
|
-
pidfile = options.pidfile || "/var/run/flapjack/#{exe}.pid"
|
98
|
-
logfile = options.log_path || "/var/log/flapjack/#{exe}.log"
|
99
|
-
bind_ip = options.bind_ip || local_ip
|
100
|
-
bind_port = options.bind_port || 12345
|
101
|
-
frequency = options.frequency || 120.0
|
102
|
-
|
103
|
-
runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
|
104
|
-
|
105
|
-
case ARGV[0]
|
106
|
-
when "start"
|
107
|
-
if runner.daemon_running?
|
108
|
-
puts "#{exe} is already running."
|
109
|
-
exit 1
|
110
|
-
else
|
111
|
-
print "#{exe} starting..."
|
112
|
-
runner.execute(:daemonize => daemonize) {
|
113
|
-
main(bind_ip, bind_port, frequency)
|
114
|
-
}
|
115
|
-
puts " done."
|
116
|
-
end
|
117
|
-
|
118
|
-
when "stop"
|
119
|
-
if runner.daemon_running?
|
120
|
-
print "#{exe} stopping..."
|
121
|
-
runner.execute(:kill => true)
|
122
|
-
puts " done."
|
123
|
-
else
|
124
|
-
puts "#{exe} is not running."
|
125
|
-
exit 1
|
126
|
-
end
|
127
|
-
|
128
|
-
when "restart"
|
129
|
-
print "#{exe} restarting..."
|
130
|
-
runner.execute(:daemonize => true, :restart => true) {
|
131
|
-
main(bind_ip, bind_port, frequency)
|
132
|
-
}
|
133
|
-
puts " done."
|
134
|
-
|
135
|
-
when "status"
|
136
|
-
uptime = (runner.daemon_running?) ? (Time.now - File.stat(pidfile).ctime) : 0
|
137
|
-
if runner.daemon_running?
|
138
|
-
puts "#{exe} is running: #{uptime}"
|
139
|
-
else
|
140
|
-
puts "#{exe} is not running"
|
141
|
-
exit 3
|
142
|
-
end
|
143
|
-
|
144
|
-
else
|
145
|
-
if ARGV.nil? || ARGV.empty?
|
146
|
-
puts "No command provided"
|
147
|
-
else
|
148
|
-
puts "Unknown command provided: '#{ARGV[0]}'"
|
149
|
-
end
|
150
|
-
exit 1
|
151
|
-
|
152
|
-
end
|
data/bin/receive-events
DELETED
@@ -1,179 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
-
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'optparse'
|
8
|
-
require 'ostruct'
|
9
|
-
require 'redis'
|
10
|
-
|
11
|
-
require 'oj'
|
12
|
-
Oj.default_options = { :indent => 0, :mode => :strict }
|
13
|
-
|
14
|
-
require 'flapjack/configuration'
|
15
|
-
require 'flapjack/data/event'
|
16
|
-
|
17
|
-
def pike(message)
|
18
|
-
puts "piking out: #{message}"
|
19
|
-
exit 1
|
20
|
-
end
|
21
|
-
|
22
|
-
def send_event(event, opts)
|
23
|
-
Flapjack::Data::Event.add(event, :redis => opts[:redis])
|
24
|
-
end
|
25
|
-
|
26
|
-
def receive(opts)
|
27
|
-
redis = Redis.new(opts[:redis_options])
|
28
|
-
source_redis = Redis.new(:url => opts[:source])
|
29
|
-
|
30
|
-
archives = get_archive_keys_stats(source_redis)
|
31
|
-
raise "found no archives!" unless archives && archives.length > 0
|
32
|
-
|
33
|
-
puts "found archives: #{archives.inspect}"
|
34
|
-
|
35
|
-
# each archive bucket is a redis list that is written
|
36
|
-
# with brpoplpush, that is newest items are added to the left (head)
|
37
|
-
# of the list, so oldest events are to be found at the tail of the list.
|
38
|
-
#
|
39
|
-
# the index of these archives, in the 'archives' array, also stores the
|
40
|
-
# redis key names for each bucket in oldest to newest
|
41
|
-
events_sent = 0
|
42
|
-
case
|
43
|
-
when opts[:all]
|
44
|
-
archive_key = archives[0][:name]
|
45
|
-
cursor = -1
|
46
|
-
when opts[:last], opts[:time]
|
47
|
-
raise "Sorry, unimplemented"
|
48
|
-
else
|
49
|
-
# wait for the next event to be archived, so point the cursor at a non-existant
|
50
|
-
# slot in the list, the one before the 0'th
|
51
|
-
archive_key = archives[-1][:name]
|
52
|
-
cursor = -1 - archives[-1][:size]
|
53
|
-
end
|
54
|
-
|
55
|
-
puts archive_key
|
56
|
-
|
57
|
-
loop do
|
58
|
-
new_archive_key = false
|
59
|
-
# something to read at cursor?
|
60
|
-
event = source_redis.lindex(archive_key, cursor)
|
61
|
-
if event
|
62
|
-
send_event(event, :redis => redis)
|
63
|
-
events_sent += 1
|
64
|
-
print "#{events_sent} " if events_sent % 1000 == 0
|
65
|
-
cursor -= 1
|
66
|
-
else
|
67
|
-
puts "\narchive key: #{archive_key}, cursor: #{cursor}"
|
68
|
-
# do we need to look at the next archive bucket?
|
69
|
-
archives = get_archive_keys_stats(source_redis)
|
70
|
-
i = archives.index {|a| a[:name] == archive_key }
|
71
|
-
if archives[i][:size] = (cursor.abs + 1)
|
72
|
-
if archives[i + 1]
|
73
|
-
archive_key = archives[i + 1][:name]
|
74
|
-
puts archive_key
|
75
|
-
cursor = -1
|
76
|
-
new_archive_key = true
|
77
|
-
else
|
78
|
-
return unless opts[:follow]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
sleep 1 unless new_archive_key
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def get_archive_keys_stats(source_redis)
|
87
|
-
source_redis.keys("events_archive:*").sort.map {|a|
|
88
|
-
{ :name => a,
|
89
|
-
:size => source_redis.llen(a) }
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
options = OpenStruct.new
|
94
|
-
options.config = Flapjack::Configuration::DEFAULT_CONFIG_PATH
|
95
|
-
options.daemonize = nil
|
96
|
-
|
97
|
-
exe = File.basename(__FILE__)
|
98
|
-
|
99
|
-
optparse = OptionParser.new do |opts|
|
100
|
-
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
101
|
-
|
102
|
-
opts.separator ""
|
103
|
-
opts.separator "Commands"
|
104
|
-
opts.separator " help"
|
105
|
-
opts.separator ""
|
106
|
-
opts.separator "Options"
|
107
|
-
|
108
|
-
opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
|
109
|
-
options.config = c
|
110
|
-
end
|
111
|
-
|
112
|
-
opts.on("-s", "--source URL", String, "URL of source redis database, eg redis://localhost:6379/0") do |s|
|
113
|
-
options.source = s
|
114
|
-
end
|
115
|
-
|
116
|
-
opts.on("-f", "--follow", String, "keep reading events as they are archived on the source") do |f|
|
117
|
-
options.follow = true
|
118
|
-
end
|
119
|
-
|
120
|
-
opts.on("-a", "--all", String, "replay all archived events from the source") do |a|
|
121
|
-
options.all = true
|
122
|
-
end
|
123
|
-
|
124
|
-
opts.on("-l", "--last COUNT", String, "replay the last COUNT events from the source") do |l|
|
125
|
-
options.count = l
|
126
|
-
end
|
127
|
-
|
128
|
-
opts.on("-t", "--time TIME", String, "replay all events archived on the source since TIME") do |t|
|
129
|
-
options.since = t
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
optparse.parse!(ARGV)
|
134
|
-
|
135
|
-
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'production'
|
136
|
-
|
137
|
-
config = Flapjack::Configuration.new
|
138
|
-
config.load(options.config)
|
139
|
-
config_env = config.all
|
140
|
-
redis_options = config.for_redis
|
141
|
-
|
142
|
-
if config_env.nil? || config_env.empty?
|
143
|
-
puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
|
144
|
-
puts "\n#{optparse}"
|
145
|
-
exit 1
|
146
|
-
end
|
147
|
-
|
148
|
-
case ARGV[0]
|
149
|
-
when "help"
|
150
|
-
puts optparse
|
151
|
-
exit
|
152
|
-
else
|
153
|
-
unless ARGV.nil? || ARGV.empty?
|
154
|
-
puts "Unknown command provided: '#{ARGV[0]}'"
|
155
|
-
puts "\n#{optparse}"
|
156
|
-
exit 1
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
unless options.source
|
161
|
-
puts "--source URL is required"
|
162
|
-
puts "\n#{optparse}"
|
163
|
-
exit 1
|
164
|
-
end
|
165
|
-
|
166
|
-
unless options.follow || options.all
|
167
|
-
puts "one or both of --follow or --all is required"
|
168
|
-
puts "\n#{optparse}"
|
169
|
-
exit 1
|
170
|
-
end
|
171
|
-
|
172
|
-
receive(:follow => options.follow,
|
173
|
-
:all => options.all,
|
174
|
-
:source => options.source,
|
175
|
-
:last => options.last,
|
176
|
-
:time => options.time,
|
177
|
-
:redis_options => redis_options)
|
178
|
-
|
179
|
-
|