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.
Files changed (53) hide show
  1. data/bin/flapjack +103 -19
  2. data/bin/flapjack-nagios-receiver +166 -52
  3. data/bin/flapper +107 -18
  4. data/etc/flapjack_config.yaml.example +16 -0
  5. data/features/events.feature +63 -0
  6. data/features/steps/events_steps.rb +5 -5
  7. data/features/steps/notifications_steps.rb +8 -6
  8. data/features/steps/time_travel_steps.rb +4 -4
  9. data/features/support/env.rb +1 -2
  10. data/flapjack.gemspec +1 -1
  11. data/lib/flapjack/configuration.rb +11 -13
  12. data/lib/flapjack/coordinator.rb +100 -220
  13. data/lib/flapjack/data/entity_check.rb +2 -2
  14. data/lib/flapjack/data/event.rb +3 -3
  15. data/lib/flapjack/executive.rb +30 -40
  16. data/lib/flapjack/filters/delays.rb +1 -1
  17. data/lib/flapjack/gateways/api.rb +6 -23
  18. data/lib/flapjack/gateways/email.rb +4 -10
  19. data/lib/flapjack/gateways/email/alert.html.haml +0 -5
  20. data/lib/flapjack/gateways/email/alert.text.erb +0 -1
  21. data/lib/flapjack/gateways/jabber.rb +80 -67
  22. data/lib/flapjack/gateways/oobetet.rb +29 -25
  23. data/lib/flapjack/gateways/pagerduty.rb +26 -45
  24. data/lib/flapjack/gateways/sms_messagenet.rb +10 -17
  25. data/lib/flapjack/gateways/web.rb +7 -21
  26. data/lib/flapjack/gateways/web/views/_css.haml +3 -0
  27. data/lib/flapjack/gateways/web/views/check.haml +1 -1
  28. data/lib/flapjack/logger.rb +57 -0
  29. data/lib/flapjack/patches.rb +0 -10
  30. data/lib/flapjack/pikelet.rb +214 -30
  31. data/lib/flapjack/redis_pool.rb +2 -17
  32. data/lib/flapjack/version.rb +1 -1
  33. data/spec/lib/flapjack/coordinator_spec.rb +116 -136
  34. data/spec/lib/flapjack/data/entity_check_spec.rb +3 -3
  35. data/spec/lib/flapjack/executive_spec.rb +33 -34
  36. data/spec/lib/flapjack/gateways/api_spec.rb +4 -2
  37. data/spec/lib/flapjack/gateways/jabber_spec.rb +39 -36
  38. data/spec/lib/flapjack/gateways/oobetet_spec.rb +14 -24
  39. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +43 -45
  40. data/spec/lib/flapjack/gateways/web_spec.rb +42 -35
  41. data/spec/lib/flapjack/logger_spec.rb +32 -0
  42. data/spec/lib/flapjack/pikelet_spec.rb +124 -15
  43. data/spec/lib/flapjack/redis_pool_spec.rb +1 -3
  44. data/spec/spec_helper.rb +34 -1
  45. data/tasks/events.rake +1 -0
  46. data/tmp/create_event_ok.rb +31 -0
  47. data/tmp/create_event_unknown.rb +31 -0
  48. data/tmp/create_events_ok.rb +1 -1
  49. metadata +10 -11
  50. data/bin/flapjack-nagios-receiver-control +0 -15
  51. data/bin/flapper-control +0 -15
  52. data/lib/flapjack/daemonizing.rb +0 -186
  53. data/lib/flapjack/gateways/base.rb +0 -38
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'ostruct'
5
-
6
3
  # add lib to the default include path
7
4
  unless $:.include?(File.dirname(__FILE__) + '/../lib/')
8
5
  $: << File.dirname(__FILE__) + '/../lib'
9
6
  end
10
7
 
8
+ require 'dante'
9
+ require 'optparse'
10
+ require 'ostruct'
11
+
11
12
  require 'flapjack/configuration'
12
13
 
13
14
  options = OpenStruct.new
@@ -15,7 +16,16 @@ options.config = File.join('etc', 'flapjack_config.yaml')
15
16
  options.daemonize = nil
16
17
 
17
18
  OptionParser.new do |opts|
18
- opts.banner = "Usage: flapjack [options]"
19
+ opts.banner = "Usage: flapjack COMMAND [OPTIONS]"
20
+
21
+ opts.separator ""
22
+ opts.separator "Commands"
23
+ opts.separator " start #{" " * 25} start flapjack"
24
+ opts.separator " stop #{" " * 26} stop flapjack"
25
+ opts.separator " restart #{" " * 23} (re)start flapjack"
26
+ opts.separator " reload #{" " * 24} reload flapjack configuration"
27
+ opts.separator ""
28
+ opts.separator "Options"
19
29
 
20
30
  opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
21
31
  options.config = c
@@ -29,6 +39,10 @@ OptionParser.new do |opts|
29
39
  options.pidfile = p
30
40
  end
31
41
 
42
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
43
+ options.log_path = l
44
+ end
45
+
32
46
  end.parse!(ARGV)
33
47
 
34
48
  FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
@@ -42,25 +56,95 @@ if config_env.nil? || config_env.empty?
42
56
  exit(false)
43
57
  end
44
58
 
45
- if options.pidfile.nil?
46
- pid_file = (config_env['pid_file'] || 'tmp/pids/flapjack.pid')
47
- else
48
- pid_file = options.pidfile
49
- end
59
+ pidfile = options.pidfile.nil? ?
60
+ (config_env['pid_file'] || 'tmp/pids/flapjack.pid') :
61
+ options.pidfile
62
+
63
+ logfile = options.logfile.nil? ?
64
+ (config_env['log_file'] || 'log/flapjack.log') :
65
+ options.logfile
50
66
 
51
- # TODO Flapjack falls over when Redis restarted -- trap errors and attempt reconnect
67
+ daemonize = options.daemonize.nil? ?
68
+ !!config_env['daemonize'] :
69
+ options.daemonize
52
70
 
53
71
  require 'flapjack/coordinator'
54
72
 
55
- coordinator = Flapjack::Coordinator.new(config)
56
- coordinator.log_file = (config_env['log_file'] || 'log/flapjack.log')
57
- coordinator.pid_file = pid_file
73
+ flapjack_coord = Proc.new {
74
+ coordinator = Flapjack::Coordinator.new(config)
75
+ coordinator.start(:signals => true)
76
+ }
77
+
78
+ case ARGV[0]
79
+ when "start"
80
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
81
+ :log_path => logfile)
82
+
83
+ if runner.daemon_running?
84
+ puts "Flapjack is already running."
85
+ else
86
+ print "Flapjack starting..."
87
+ runner.execute(:daemonize => daemonize) {
88
+ flapjack_coord.call
89
+ }
90
+ puts " done."
91
+ end
92
+
93
+ when "stop"
94
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
95
+ :log_path => logfile)
96
+
97
+ if runner.daemon_running?
98
+ print "Flapjack stopping..."
99
+ runner.execute(:kill => true)
100
+ puts " done."
101
+ else
102
+ puts "Flapjack is not running."
103
+ end
104
+
105
+ when "restart"
106
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
107
+ :log_path => logfile)
108
+
109
+ print "Flapjack restarting..."
110
+ runner.execute(:daemonize => true, :restart => true) {
111
+ sleep 1 # get connection errors without this... -- might move this to
112
+ # be default behaviour when starting jabber gateway
113
+ flapjack_coord.call
114
+ }
115
+ puts " done."
116
+
117
+ when "reload"
118
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile, :log_path => logfile)
119
+
120
+ if runner.daemon_running?
121
+ print "Reloading Flapjack configuration..."
122
+ begin
123
+ pid = IO.read(pidfile).chomp.to_i
124
+ Process.kill('HUP', pid)
125
+ puts " sent HUP to pid #{pid}."
126
+ rescue => e
127
+ puts " couldn't send HUP to pid '#{pid}'."
128
+ end
129
+ else
130
+ puts "Flapjack is not running daemonized."
131
+ end
132
+
133
+ when "status"
134
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile, :log_path => logfile)
135
+
136
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
137
+ if runner.daemon_running?
138
+ puts "Flapjack is running: #{uptime}"
139
+ else
140
+ puts "Flapjack is not runninng"
141
+ end
58
142
 
59
- if options.daemonize.nil?
60
- daemonize = !!config_env['daemonize']
61
143
  else
62
- daemonize = options.daemonize
63
- end
144
+ if ARGV.nil? || ARGV.empty?
145
+ puts "No command provided"
146
+ else
147
+ puts "Unknown command provided: '#{ARGV[0]}'"
148
+ end
64
149
 
65
- puts "Daemonising ... " if daemonize
66
- coordinator.start(:daemonize => daemonize, :signals => true)
150
+ end
@@ -1,62 +1,27 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
4
+ $: << File.dirname(__FILE__) + '/../lib'
5
+ end
6
+
3
7
  require 'optparse'
4
8
  require 'ostruct'
5
9
  require 'redis'
6
10
  require 'yajl/json_gem'
7
-
8
- # add lib to the default include path
9
- unless $:.include?(File.dirname(__FILE__) + '/../lib/')
10
- $: << File.dirname(__FILE__) + '/../lib'
11
- end
11
+ require 'dante'
12
12
 
13
13
  require 'flapjack/configuration'
14
14
 
15
- options = OpenStruct.new
16
- options.config = File.join('etc', 'flapjack_config.yaml')
17
- options.daemonize = nil
18
-
19
- OptionParser.new do |opts|
20
- opts.banner = "Usage: flapjack-nagios-receiver [options]"
21
-
22
- opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
23
- options.config = c
24
- end
25
-
26
- opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f|
27
- options.fifo = f
28
- end
29
-
30
- end.parse!(ARGV)
31
-
32
- FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
33
-
34
- config = Flapjack::Configuration.new
35
- config.load(options.config)
36
- @config_env = config.all
37
- @redis_options = config.for_redis
38
-
39
- if @config_env.nil? || @config_env.empty?
40
- puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
41
- exit(false)
15
+ def pike(message)
16
+ puts "piking out: #{message}"
17
+ exit 1
42
18
  end
43
19
 
44
- if !options.fifo
45
- puts "You must specify a path to the nagios perfdata named pipe using the --fifo option"
46
- exit(false)
47
- end
48
-
49
- @fifo = File.new(options.fifo)
50
-
51
- # nagios.cfg contains the following templates for host and service data (modified from the default
52
- # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the
53
- # fields match up
54
- # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
55
- # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
56
-
57
- def process_input(redis)
20
+ def process_input(opts)
21
+ redis = opts[:redis]
22
+ fifo = File.new(opts[:fifo])
58
23
  begin
59
- while line = @fifo.gets
24
+ while line = fifo.gets
60
25
  skip unless line
61
26
  split_line = line.split("\t")
62
27
 
@@ -93,15 +58,164 @@ def process_input(redis)
93
58
  end
94
59
  end
95
60
 
96
- def main
97
- redis = Redis.new(@redis_options)
98
-
61
+ def main(opts)
62
+ fifo = opts[:fifo]
63
+ redis = Redis.new(opts[:redis_options])
99
64
  while true
100
- process_input(redis)
65
+ process_input(:redis => redis, :fifo => fifo)
101
66
  puts "Whoops, restarting main loop in 10 seconds"
102
67
  sleep 10
103
68
  end
104
69
  end
105
70
 
106
- main
71
+ options = OpenStruct.new
72
+ options.config = nil
73
+ options.daemonize = nil
74
+
75
+ exe = File.basename(__FILE__)
76
+
77
+ OptionParser.new do |opts|
78
+ opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
79
+
80
+ opts.separator ""
81
+ opts.separator "Commands"
82
+ opts.separator " start #{" " * 25} start #{exe}"
83
+ opts.separator " stop #{" " * 26} stop #{exe}"
84
+ opts.separator " restart #{" " * 23} (re)start #{exe}"
85
+ opts.separator ""
86
+ opts.separator "Options"
87
+
88
+ opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
89
+ options.config = c
90
+ end
91
+
92
+ opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f|
93
+ options.fifo = f
94
+ end
95
+
96
+ opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
97
+ options.daemonize = d
98
+ end
99
+
100
+ opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |p|
101
+ options.pidfile = p
102
+ end
103
+
104
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
105
+ options.log_path = l
106
+ end
107
+
108
+ end.parse!(ARGV)
109
+
110
+ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
111
+
112
+ #runner = Dante::Runner.new('flapjack-nagios-receiver',
113
+ # :pid_path => '/var/run/flapjack/flapjack-nagios-receiver.pid',
114
+ # :log_path => '/var/log/flapjack/flapjack-nagios-receiver.log')
115
+
116
+
117
+ if options.config
118
+ config_file = options.config
119
+ pike "specified config file cannot be read" unless File.readable?(config_file)
120
+ else
121
+ [ 'etc/flapjack_config.yaml',
122
+ File.dirname(__FILE__) + 'etc/flapjack_config.yaml',
123
+ '/etc/flapjack/flapjack_config.yaml' ].each do |candidate|
124
+ if File.readable?(candidate)
125
+ config_file = candidate
126
+ break
127
+ else
128
+ puts "not found and/or not readable: #{candidate}"
129
+ end
130
+ end
131
+ pike "no config file specified and none found in default locations" unless config_file
132
+ end
133
+
134
+ config = Flapjack::Configuration.new
135
+ config.load(config_file)
136
+ config_env = config.all
137
+ redis_options = config.for_redis
138
+
139
+ if config_env.nil? || config_env.empty?
140
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
141
+ exit(false)
142
+ end
143
+
144
+ config_nr = config_env['nagios-receiver'] || {}
145
+
146
+ pidfile = options.pidfile.nil? ?
147
+ (config_nr['pid_file'] || "/var/run/flapjack/#{exe}.pid") :
148
+ options.pidfile
149
+
150
+ logfile = options.logfile.nil? ?
151
+ (config_nr['log_file'] || "/var/log/flapjack/#{exe}.log") :
152
+ options.logfile
153
+
154
+ fifo = options.fifo.nil? ?
155
+ (config_nr['fifo'] || '/var/cache/nagios3/event_stream.fifo') :
156
+ options.fifo
157
+
158
+ daemonize = options.daemonize.nil? ?
159
+ !!config_nr['daemonize'] :
160
+ options.daemonize
161
+
162
+
163
+ # nagios.cfg contains the following templates for host and service data (modified from the default
164
+ # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the
165
+ # fields match up
166
+ # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
167
+ # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
168
+
169
+
170
+ runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
171
+ case ARGV[0]
172
+ when "start", "restart"
173
+ pike "You must specify a path to the nagios perfdata named pipe using the --fifo option" unless fifo
174
+ end
175
+
176
+ case ARGV[0]
177
+ when "start"
178
+ if runner.daemon_running?
179
+ puts "#{exe} is already running."
180
+ else
181
+ print "#{exe} starting..."
182
+ runner.execute(:daemonize => daemonize) {
183
+ main(:redis_options => redis_options, :fifo => fifo)
184
+ }
185
+ puts " done."
186
+ end
187
+
188
+ when "stop"
189
+ if runner.daemon_running?
190
+ print "#{exe} stopping..."
191
+ runner.execute(:kill => true)
192
+ puts " done."
193
+ else
194
+ puts "#{exe} is not running."
195
+ end
196
+
197
+ when "restart"
198
+ print "#{exe} restarting..."
199
+ runner.execute(:daemonize => true, :restart => true) {
200
+ main(:redis_options => redis_options, :fifo => fifo)
201
+ }
202
+ puts " done."
203
+
204
+ when "status"
205
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
206
+ if runner.daemon_running?
207
+ puts "#{exe} is running: #{uptime}"
208
+ else
209
+ puts "#{exe} is not runninng"
210
+ end
211
+
212
+ else
213
+ if ARGV.nil? || ARGV.empty?
214
+ puts "No command provided"
215
+ else
216
+ puts "Unknown command provided: '#{ARGV[0]}'"
217
+ end
218
+
219
+ end
220
+
107
221
 
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
4
+ require 'ostruct'
3
5
  require 'eventmachine'
4
6
  require 'socket'
7
+ require 'dante'
5
8
 
6
9
  module Flapper
7
-
8
10
  def receive_data data
9
11
  send_data ">>>you sent: #{data}"
10
12
  close_connection if data =~ /quit/i
11
13
  end
12
-
13
14
  end
14
15
 
15
16
  def local_ip
@@ -24,25 +25,113 @@ ensure
24
25
  Socket.do_not_reverse_lookup = orig
25
26
  end
26
27
 
27
- start_every = 120
28
- stop_after = 60
29
- bind_ip = local_ip
30
- bind_port = 12345
31
- EM.run {
32
-
33
- puts "#{Time.now}: starting server"
34
- server_init = EM.start_server bind_ip, bind_port, Flapper
35
- EM.add_timer(stop_after) do
36
- puts "#{Time.now}: stopping server"
37
- EM.stop_server(server_init)
38
- end
28
+ def main
29
+ start_every = 120
30
+ stop_after = 60
31
+ bind_ip = local_ip
32
+ bind_port = 12345
33
+ EM.run {
39
34
 
40
- EM.add_periodic_timer(start_every) do
41
35
  puts "#{Time.now}: starting server"
42
- server = EM.start_server bind_ip, bind_port, Flapper
36
+ server_init = EM.start_server bind_ip, bind_port, Flapper
43
37
  EM.add_timer(stop_after) do
44
38
  puts "#{Time.now}: stopping server"
45
- EM.stop_server(server)
39
+ EM.stop_server(server_init)
46
40
  end
41
+
42
+ EM.add_periodic_timer(start_every) do
43
+ puts "#{Time.now}: starting server"
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 ""
67
+ opts.separator "Options"
68
+
69
+ opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
70
+ options.daemonize = d
71
+ end
72
+
73
+ opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |p|
74
+ options.pidfile = p
75
+ end
76
+
77
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
78
+ options.log_path = l
47
79
  end
48
- }
80
+ end.parse!(ARGV)
81
+
82
+ pidfile = options.pidfile.nil? ?
83
+ "/var/run/flapjack/#{exe}.pid" :
84
+ options.pidfile
85
+
86
+ logfile = options.logfile.nil? ?
87
+ "/var/log/flapjack/#{exe}.log" :
88
+ options.logfile
89
+
90
+ daemonize = options.daemonize.nil? ? true : options.daemonize
91
+
92
+ runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
93
+
94
+ case ARGV[0]
95
+ when "start"
96
+ if runner.daemon_running?
97
+ puts "#{exe} is already running."
98
+ else
99
+ print "#{exe} starting..."
100
+ runner.execute(:daemonize => daemonize) {
101
+ main
102
+ }
103
+ puts " done."
104
+ end
105
+
106
+ when "stop"
107
+ if runner.daemon_running?
108
+ print "#{exe} stopping..."
109
+ runner.execute(:kill => true)
110
+ puts " done."
111
+ else
112
+ puts "#{exe} is not running."
113
+ end
114
+
115
+ when "restart"
116
+ print "#{exe} restarting..."
117
+ runner.execute(:daemonize => true, :restart => true) {
118
+ main
119
+ }
120
+ puts " done."
121
+
122
+ when "status"
123
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
124
+ if runner.daemon_running?
125
+ puts "#{exe} is running: #{uptime}"
126
+ else
127
+ puts "#{exe} is not runninng"
128
+ end
129
+
130
+ else
131
+ if ARGV.nil? || ARGV.empty?
132
+ puts "No command provided"
133
+ else
134
+ puts "Unknown command provided: '#{ARGV[0]}'"
135
+ end
136
+
137
+ end