flapjack 1.0.0rc3 → 1.0.0rc5
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.ruby-version +1 -0
- data/CHANGELOG.md +20 -0
- data/CONTRIBUTING.md +2 -2
- data/Gemfile +1 -1
- data/README.md +6 -16
- data/build.sh +13 -1
- data/etc/flapjack_config.yaml.example +98 -12
- data/features/cli.feature +8 -8
- data/features/cli_flapjack-nagios-receiver.feature +29 -37
- data/features/cli_flapper.feature +24 -12
- data/features/cli_simulate-failed-check.feature +2 -2
- data/features/notifications.feature +18 -1
- data/features/steps/cli_steps.rb +2 -2
- data/features/steps/notifications_steps.rb +71 -0
- data/features/support/env.rb +7 -6
- data/flapjack.gemspec +3 -1
- data/lib/flapjack/cli/flapper.rb +74 -25
- data/lib/flapjack/cli/import.rb +3 -4
- data/lib/flapjack/cli/maintenance.rb +182 -0
- data/lib/flapjack/cli/receiver.rb +110 -121
- data/lib/flapjack/cli/server.rb +30 -26
- data/lib/flapjack/cli/simulate.rb +2 -3
- data/lib/flapjack/data/contact.rb +1 -1
- data/lib/flapjack/data/entity.rb +425 -32
- data/lib/flapjack/data/entity_check.rb +212 -14
- data/lib/flapjack/data/event.rb +1 -1
- data/lib/flapjack/gateways/aws_sns.rb +134 -0
- data/lib/flapjack/gateways/aws_sns/alert.text.erb +5 -0
- data/lib/flapjack/gateways/aws_sns/rollup.text.erb +2 -0
- data/lib/flapjack/gateways/jabber.rb +2 -2
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +15 -1
- data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +4 -3
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +1 -1
- data/lib/flapjack/gateways/web.rb +35 -16
- data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -16
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
- data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -45
- 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 +10 -10
- data/lib/flapjack/gateways/web/views/checks.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/contact.html.erb +5 -1
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +3 -4
- data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/layout.erb +3 -3
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +5 -6
- data/lib/flapjack/notifier.rb +4 -1
- data/lib/flapjack/patches.rb +8 -2
- data/lib/flapjack/pikelet.rb +3 -1
- data/lib/flapjack/version.rb +1 -1
- data/libexec/httpbroker.go +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +3 -3
- data/spec/lib/flapjack/data/contact_spec.rb +2 -2
- data/spec/lib/flapjack/data/entity_check_spec.rb +805 -53
- data/spec/lib/flapjack/data/entity_spec.rb +661 -0
- data/spec/lib/flapjack/gateways/aws_sns_spec.rb +123 -0
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +2 -2
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web_spec.rb +11 -11
- data/spec/support/profile_all_formatter.rb +10 -10
- data/spec/support/uncolored_doc_formatter.rb +66 -4
- data/src/flapjack/event.go +1 -1
- data/tasks/benchmarks.rake +24 -20
- data/tasks/entities.rake +148 -0
- data/tmp/dummy_contacts.json +43 -0
- data/tmp/dummy_entities.json +37 -1
- metadata +43 -7
- data/tmp/test_entities.json +0 -1
data/lib/flapjack/cli/flapper.rb
CHANGED
@@ -23,14 +23,40 @@ module Flapjack
|
|
23
23
|
def initialize(global_options, options)
|
24
24
|
@global_options = global_options
|
25
25
|
@options = options
|
26
|
+
|
27
|
+
@config = Flapjack::Configuration.new
|
28
|
+
@config.load(global_options[:config])
|
29
|
+
@config_env = @config.all
|
30
|
+
|
31
|
+
if @config_env.nil? || @config_env.empty?
|
32
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
33
|
+
end
|
34
|
+
|
35
|
+
@pidfile = case
|
36
|
+
when !@options[:pidfile].nil?
|
37
|
+
@options[:pidfile]
|
38
|
+
when !@config_env['pid_dir'].nil?
|
39
|
+
@config_env['pid_dir'] + 'flapper.pid'
|
40
|
+
else
|
41
|
+
"/var/run/flapjack/flapper.pid"
|
42
|
+
end
|
43
|
+
|
44
|
+
@logfile = case
|
45
|
+
when !@options[:logfile].nil?
|
46
|
+
@options[:logfile]
|
47
|
+
when !@config_env['log_dir'].nil?
|
48
|
+
@config_env['log_dir'] + 'flapper.log'
|
49
|
+
else
|
50
|
+
"/var/run/flapjack/flapper.log"
|
51
|
+
end
|
26
52
|
end
|
27
53
|
|
28
54
|
def start
|
29
55
|
if runner.daemon_running?
|
30
56
|
puts "flapper is already running."
|
31
|
-
exit 1
|
32
57
|
else
|
33
58
|
print "flapper starting..."
|
59
|
+
print "\n" unless @options[:daemonize]
|
34
60
|
runner.execute(:daemonize => @options[:daemonize]) do
|
35
61
|
main(@options['bind-ip'], @options['bind-port'].to_i, @options[:frequency])
|
36
62
|
end
|
@@ -39,14 +65,15 @@ module Flapjack
|
|
39
65
|
end
|
40
66
|
|
41
67
|
def stop
|
68
|
+
pid = get_pid
|
42
69
|
if runner.daemon_running?
|
43
70
|
print "flapper stopping..."
|
44
71
|
runner.execute(:kill => true)
|
45
72
|
puts " done."
|
46
73
|
else
|
47
74
|
puts "flapper is not running."
|
48
|
-
exit 1
|
49
75
|
end
|
76
|
+
exit_now! unless wait_pid_gone(pid)
|
50
77
|
end
|
51
78
|
|
52
79
|
def restart
|
@@ -58,12 +85,12 @@ module Flapjack
|
|
58
85
|
end
|
59
86
|
|
60
87
|
def status
|
61
|
-
uptime = (runner.daemon_running?) ? (Time.now - File.stat(@options[:pidfile]).ctime) : 0
|
62
88
|
if runner.daemon_running?
|
63
|
-
|
89
|
+
pid = get_pid
|
90
|
+
uptime = Time.now - File.stat(@pidfile).ctime
|
91
|
+
puts "flapper is running: pid #{pid}, uptime #{uptime}"
|
64
92
|
else
|
65
|
-
|
66
|
-
exit 3
|
93
|
+
exit_now! "flapper is not running"
|
67
94
|
end
|
68
95
|
end
|
69
96
|
|
@@ -79,8 +106,8 @@ module Flapjack
|
|
79
106
|
def runner
|
80
107
|
return @runner if @runner
|
81
108
|
|
82
|
-
@runner = Dante::Runner.new('flapper', :pid_path => @
|
83
|
-
:log_path => @
|
109
|
+
@runner = Dante::Runner.new('flapper', :pid_path => @pidfile,
|
110
|
+
:log_path => @logfile)
|
84
111
|
@runner
|
85
112
|
end
|
86
113
|
|
@@ -109,12 +136,42 @@ module Flapjack
|
|
109
136
|
end
|
110
137
|
end
|
111
138
|
|
139
|
+
def process_exists(pid)
|
140
|
+
return unless pid
|
141
|
+
begin
|
142
|
+
Process.kill(0, pid)
|
143
|
+
return true
|
144
|
+
rescue Errno::ESRCH
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# wait until the specified pid no longer exists, or until a timeout is reached
|
150
|
+
def wait_pid_gone(pid, timeout = 30)
|
151
|
+
print "waiting for a max of #{timeout} seconds for process #{pid} to exit" if process_exists(pid)
|
152
|
+
started_at = Time.now.to_i
|
153
|
+
while process_exists(pid)
|
154
|
+
break unless (Time.now.to_i - started_at < timeout)
|
155
|
+
print '.'
|
156
|
+
sleep 1
|
157
|
+
end
|
158
|
+
puts ''
|
159
|
+
!process_exists(pid)
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_pid
|
163
|
+
IO.read(@pidfile).chomp.to_i
|
164
|
+
rescue StandardError
|
165
|
+
pid = nil
|
166
|
+
end
|
167
|
+
|
168
|
+
|
112
169
|
end
|
113
170
|
end
|
114
171
|
end
|
115
172
|
|
116
173
|
|
117
|
-
desc 'Artificial service that oscillates up and down'
|
174
|
+
desc 'Artificial service that oscillates up and down, for use in http://flapjack.io/docs/1.0/usage/oobetet'
|
118
175
|
command :flapper do |flapper|
|
119
176
|
|
120
177
|
flapper.desc 'start flapper'
|
@@ -123,11 +180,9 @@ command :flapper do |flapper|
|
|
123
180
|
start.switch [:d, 'daemonize'], :desc => 'Daemonize',
|
124
181
|
:default_value => true
|
125
182
|
|
126
|
-
start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
127
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
183
|
+
start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
128
184
|
|
129
|
-
start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
130
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
185
|
+
start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
131
186
|
|
132
187
|
start.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
|
133
188
|
:default_value => Flapjack::CLI::Flapper.local_ip
|
@@ -147,11 +202,9 @@ command :flapper do |flapper|
|
|
147
202
|
flapper.desc 'stop flapper'
|
148
203
|
flapper.command :stop do |stop|
|
149
204
|
|
150
|
-
stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
151
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
205
|
+
stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
152
206
|
|
153
|
-
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
154
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
207
|
+
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
155
208
|
|
156
209
|
stop.action do |global_options, options, args|
|
157
210
|
cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
|
@@ -162,11 +215,9 @@ command :flapper do |flapper|
|
|
162
215
|
flapper.desc 'restart flapper'
|
163
216
|
flapper.command :restart do |restart|
|
164
217
|
|
165
|
-
restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
166
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
218
|
+
restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
167
219
|
|
168
|
-
restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
169
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
220
|
+
restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
170
221
|
|
171
222
|
restart.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
|
172
223
|
:default_value => Flapjack::CLI::Flapper.local_ip
|
@@ -186,11 +237,9 @@ command :flapper do |flapper|
|
|
186
237
|
flapper.desc 'flapper status'
|
187
238
|
flapper.command :status do |status|
|
188
239
|
|
189
|
-
status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
190
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
240
|
+
status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
191
241
|
|
192
|
-
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
193
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
242
|
+
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
194
243
|
|
195
244
|
status.action do |global_options, options, args|
|
196
245
|
cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
|
data/lib/flapjack/cli/import.rb
CHANGED
@@ -22,8 +22,7 @@ module Flapjack
|
|
22
22
|
@config_env = config.all
|
23
23
|
|
24
24
|
if @config_env.nil? || @config_env.empty?
|
25
|
-
|
26
|
-
exit 1
|
25
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
27
26
|
end
|
28
27
|
|
29
28
|
@redis_options = config.for_redis
|
@@ -65,14 +64,14 @@ module Flapjack
|
|
65
64
|
private
|
66
65
|
|
67
66
|
def redis
|
68
|
-
@redis ||= Redis.new(@redis_options)
|
67
|
+
@redis ||= Redis.new(@redis_options.merge(:driver => :ruby))
|
69
68
|
end
|
70
69
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
75
|
-
desc 'Bulk import data from an external source'
|
74
|
+
desc 'Bulk import data from an external source, reading from JSON formatted data files'
|
76
75
|
command :import do |import|
|
77
76
|
|
78
77
|
import.desc 'Import contacts'
|
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'em-synchrony'
|
5
|
+
require 'redis'
|
6
|
+
require 'redis/connection/synchrony'
|
7
|
+
|
8
|
+
require 'flapjack/configuration'
|
9
|
+
require 'flapjack/data/event'
|
10
|
+
require 'flapjack/data/entity_check'
|
11
|
+
require 'terminal-table'
|
12
|
+
|
13
|
+
module Flapjack
|
14
|
+
module CLI
|
15
|
+
class Maintenance
|
16
|
+
|
17
|
+
def initialize(global_options, options)
|
18
|
+
@global_options = global_options
|
19
|
+
@options = options
|
20
|
+
|
21
|
+
config = Flapjack::Configuration.new
|
22
|
+
config.load(global_options[:config])
|
23
|
+
@config_env = config.all
|
24
|
+
|
25
|
+
if @config_env.nil? || @config_env.empty?
|
26
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
27
|
+
end
|
28
|
+
|
29
|
+
@redis_options = config.for_redis.merge(:driver => :ruby)
|
30
|
+
@options[:redis] = redis
|
31
|
+
end
|
32
|
+
|
33
|
+
def show
|
34
|
+
exit_now!("state must be one of 'ok', 'warning', 'critical', 'unknown'") unless @options[:state].nil? || %w(ok warning critical unknown).include?(@options[:state].downcase)
|
35
|
+
exit_now!("type must be one of 'scheduled', 'unscheduled'") unless %w(scheduled unscheduled).include?(@options[:type].downcase)
|
36
|
+
%w(started finishing).each do |time|
|
37
|
+
exit_now!("#{time.capitalize} time must start with 'more than', 'less than', 'on', 'before', 'after' or between") if @options[time] && !@options[time].downcase.start_with?('more than', 'less than', 'on', 'before', 'after', 'between')
|
38
|
+
end
|
39
|
+
@options[:finishing] ||= 'after now'
|
40
|
+
maintenances = Flapjack::Data::EntityCheck.find_maintenance(@options)
|
41
|
+
rows = []
|
42
|
+
maintenances.each do |m|
|
43
|
+
row = []
|
44
|
+
# Convert the unix timestamps of the start and end time back into readable times
|
45
|
+
m.each { |k, v| row.push(k.to_s.end_with?('time') ? Time.at(v) : v) }
|
46
|
+
rows.push(row)
|
47
|
+
end
|
48
|
+
puts Terminal::Table.new :headings => ['Entity', 'Check', 'State', 'Start', 'Duration (s)', 'Reason', 'End'], :rows => rows
|
49
|
+
maintenances
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete
|
53
|
+
maintenances = show
|
54
|
+
exit_now!('The following maintenances would be deleted. Run this command again with --apply true to remove them.') unless @options[:apply]
|
55
|
+
errors = Flapjack::Data::EntityCheck.delete_maintenance(@options)
|
56
|
+
(errors.each { |k, v| puts "#{k}: #{v}" }; exit_now!('Failed to delete maintenances')) if errors.length > 0
|
57
|
+
puts "The maintenances above have been deleted"
|
58
|
+
end
|
59
|
+
|
60
|
+
def create
|
61
|
+
exit_now!("Entity & check must be supplied to create a maintenance period") if @options[:entity].nil? || @options[:check].nil?
|
62
|
+
errors = Flapjack::Data::EntityCheck.create_maintenance(@options)
|
63
|
+
(errors.each { |k, v| puts "#{k}: #{v}" }; exit_now!('Failed to create maintenances')) if errors.length > 0
|
64
|
+
puts "The maintenances specified have been created"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def redis
|
70
|
+
@redis ||= Redis.new(@redis_options)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Show, create and delete maintenance windows'
|
78
|
+
command :maintenance do |maintenance|
|
79
|
+
|
80
|
+
|
81
|
+
maintenance.desc 'Show maintenance windows according to criteria (default: all ongoing maintenance)'
|
82
|
+
maintenance.command :show do |show|
|
83
|
+
|
84
|
+
show.flag [:e, 'entity'],
|
85
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\''
|
86
|
+
|
87
|
+
show.flag [:c, 'check'],
|
88
|
+
:desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\''
|
89
|
+
|
90
|
+
show.flag [:r, 'reason'],
|
91
|
+
:desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\''
|
92
|
+
|
93
|
+
show.flag [:s, 'start', 'started', 'starting'],
|
94
|
+
:desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"'
|
95
|
+
|
96
|
+
show.flag [:d, 'duration'],
|
97
|
+
:desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval'
|
98
|
+
|
99
|
+
show.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'],
|
100
|
+
:desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"'
|
101
|
+
|
102
|
+
show.flag [:st, 'state'],
|
103
|
+
:desc => 'The state that the check is currently in'
|
104
|
+
|
105
|
+
show.flag [:t, 'type'],
|
106
|
+
:desc => 'The type of maintenance scheduled',
|
107
|
+
:default_value => 'scheduled'
|
108
|
+
|
109
|
+
show.action do |global_options,options,args|
|
110
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
111
|
+
maintenance.show
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
maintenance.desc 'Delete maintenance windows according to criteria (default: all ongoing maintenance)'
|
116
|
+
maintenance.command :delete do |delete|
|
117
|
+
|
118
|
+
delete.flag [:a, 'apply'],
|
119
|
+
:desc => 'Whether this deletion should occur',
|
120
|
+
:default_value => false
|
121
|
+
|
122
|
+
delete.flag [:e, 'entity'],
|
123
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\''
|
124
|
+
|
125
|
+
delete.flag [:c, 'check'],
|
126
|
+
:desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\''
|
127
|
+
|
128
|
+
delete.flag [:r, 'reason'],
|
129
|
+
:desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\''
|
130
|
+
|
131
|
+
delete.flag [:s, 'start', 'started', 'starting'],
|
132
|
+
:desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"'
|
133
|
+
|
134
|
+
delete.flag [:d, 'duration'],
|
135
|
+
:desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval'
|
136
|
+
|
137
|
+
delete.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'],
|
138
|
+
:desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"'
|
139
|
+
|
140
|
+
delete.flag [:st, 'state'],
|
141
|
+
:desc => 'The state that the check is currently in'
|
142
|
+
|
143
|
+
delete.flag [:t, 'type'],
|
144
|
+
:desc => 'The type of maintenance scheduled',
|
145
|
+
:default_value => 'scheduled'
|
146
|
+
|
147
|
+
delete.action do |global_options,options,args|
|
148
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
149
|
+
maintenance.delete
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
maintenance.desc 'Create a maintenance window'
|
154
|
+
maintenance.command :create do |create|
|
155
|
+
|
156
|
+
create.flag [:e, 'entity'],
|
157
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a comma separated list',
|
158
|
+
:type => Array
|
159
|
+
|
160
|
+
create.flag [:c, 'check'],
|
161
|
+
:desc => 'The check for the maintenance window to occur on. This can be a comma separated list',
|
162
|
+
:type => Array
|
163
|
+
|
164
|
+
create.flag [:r, 'reason'],
|
165
|
+
:desc => 'The reason for the maintenance window to occur'
|
166
|
+
|
167
|
+
create.flag [:s, 'start', 'started', 'starting'],
|
168
|
+
:desc => 'The start time for the maintenance window'
|
169
|
+
|
170
|
+
create.flag [:d, 'duration'],
|
171
|
+
:desc => 'The total duration of the maintenance window. This should be an interval'
|
172
|
+
|
173
|
+
create.flag [:t, 'type'],
|
174
|
+
:desc => 'The type of maintenance scheduled ("scheduled")',
|
175
|
+
:default_value => 'scheduled'
|
176
|
+
|
177
|
+
create.action do |global_options,options,args|
|
178
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
179
|
+
maintenance.create
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -20,123 +20,87 @@ module Flapjack
|
|
20
20
|
@global_options = global_options
|
21
21
|
@options = options
|
22
22
|
|
23
|
-
config = Flapjack::Configuration.new
|
24
|
-
config.load(global_options[:config])
|
25
|
-
@config_env = config.all
|
23
|
+
@config = Flapjack::Configuration.new
|
24
|
+
@config.load(global_options[:config])
|
25
|
+
@config_env = @config.all
|
26
26
|
|
27
27
|
if @config_env.nil? || @config_env.empty?
|
28
|
-
|
29
|
-
exit 1
|
28
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
30
29
|
end
|
31
30
|
|
32
|
-
@
|
33
|
-
end
|
31
|
+
@config_runner = @config_env["#{@options[:type]}-receiver"] || {}
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
# host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
|
42
|
-
#
|
43
|
-
# service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
|
44
|
-
#
|
45
|
-
|
46
|
-
def nagios_start
|
47
|
-
if runner('nagios').daemon_running?
|
48
|
-
puts "nagios-receiver is already running."
|
49
|
-
exit 1
|
33
|
+
@pidfile = case
|
34
|
+
when !@options[:pidfile].nil?
|
35
|
+
@options[:pidfile]
|
36
|
+
when !@config_env['pid_dir'].nil?
|
37
|
+
@config_env['pid_dir'] + "#{@options[:type]}-receiver.pid"
|
50
38
|
else
|
51
|
-
|
52
|
-
runner('nagios').execute(:daemonize => @options[:daemonize]) do
|
53
|
-
begin
|
54
|
-
main(:fifo => @options[:fifo], :nagios => true)
|
55
|
-
rescue Exception => e
|
56
|
-
p e.message
|
57
|
-
puts e.backtrace.join("\n")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
puts " done."
|
39
|
+
"/var/run/flapjack/#{@options[:type]}-receiver.pid"
|
61
40
|
end
|
62
|
-
end
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
42
|
+
@logfile = case
|
43
|
+
when !@options[:logfile].nil?
|
44
|
+
@options[:logfile]
|
45
|
+
when !@config_env['log_dir'].nil?
|
46
|
+
@config_env['log_dir'] + "#{@options[:type]}-receiver.log"
|
69
47
|
else
|
70
|
-
|
71
|
-
exit 1
|
48
|
+
"/var/run/flapjack/#{@options[:type]}-receiver.log"
|
72
49
|
end
|
73
|
-
end
|
74
50
|
|
75
|
-
|
76
|
-
print "nagios-receiver restarting..."
|
77
|
-
runner('nagios').execute(:daemonize => true, :restart => true) do
|
78
|
-
main(:fifo => @options[:fifo], :nagios => true)
|
79
|
-
end
|
80
|
-
puts " done."
|
51
|
+
@redis_options = @config.for_redis
|
81
52
|
end
|
82
53
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
"/var/run/flapjack/nagios-receiver.pid"
|
87
|
-
uptime = (runner('nagios').daemon_running?) ? (Time.now - File.stat(pidfile).ctime) : 0
|
88
|
-
if runner('nagios').daemon_running?
|
89
|
-
puts "nagios-receiver is running: #{uptime}"
|
54
|
+
def start
|
55
|
+
if runner(@options[:type]).daemon_running?
|
56
|
+
puts "#{@options[:type]}-receiver is already running."
|
90
57
|
else
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
print "nsca-receiver starting..."
|
102
|
-
runner('nsca').execute(:daemonize => @options[:daemonize]) do
|
103
|
-
main(:fifo => @options[:fifo], :nsca => true)
|
58
|
+
print "#{@options[:type]}-receiver starting..."
|
59
|
+
print "\n" unless @options[:daemonize]
|
60
|
+
runner(@options[:type]).execute(:daemonize => @options[:daemonize]) do
|
61
|
+
begin
|
62
|
+
main(:fifo => @options[:fifo], :type => @options[:type])
|
63
|
+
rescue Exception => e
|
64
|
+
p e.message
|
65
|
+
puts e.backtrace.join("\n")
|
66
|
+
end
|
104
67
|
end
|
105
68
|
puts " done."
|
106
69
|
end
|
107
70
|
end
|
108
71
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
72
|
+
def stop
|
73
|
+
pid = get_pid
|
74
|
+
if runner(@options[:type]).daemon_running?
|
75
|
+
print "#{@options[:type]}-receiver stopping..."
|
76
|
+
runner(@options[:type]).execute(:kill => true)
|
113
77
|
puts " done."
|
114
78
|
else
|
115
|
-
puts "
|
116
|
-
exit 1
|
79
|
+
puts "#{@options[:type]}-receiver is not running."
|
117
80
|
end
|
81
|
+
exit_now! unless wait_pid_gone(pid)
|
118
82
|
end
|
119
83
|
|
120
|
-
def
|
121
|
-
print "
|
122
|
-
runner(
|
123
|
-
|
84
|
+
def restart
|
85
|
+
print "#{@options[:type]}-receiver restarting..."
|
86
|
+
runner(@options[:type]).execute(:daemonize => true, :restart => true) do
|
87
|
+
begin
|
88
|
+
main(:fifo => @options[:fifo], :type => @options[:type])
|
89
|
+
rescue Exception => e
|
90
|
+
p e.message
|
91
|
+
puts e.backtrace.join("\n")
|
92
|
+
end
|
124
93
|
end
|
125
94
|
puts " done."
|
126
95
|
end
|
127
96
|
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
"
|
133
|
-
|
134
|
-
uptime = (runner('nsca').daemon_running?) ? (Time.now - File.stat(pidfile).ctime) : 0
|
135
|
-
if runner('nsca').daemon_running?
|
136
|
-
puts "nsca-receiver is running: #{uptime}"
|
97
|
+
def status
|
98
|
+
if runner(@options[:type]).daemon_running?
|
99
|
+
pid = get_pid
|
100
|
+
uptime = Time.now - File.stat(@pidfile).ctime
|
101
|
+
puts "#{@options[:type]}-receiver is running: pid #{pid}, uptime #{uptime}"
|
137
102
|
else
|
138
|
-
|
139
|
-
exit 3
|
103
|
+
exit_now! "#{@options[:type]}-receiver is not running"
|
140
104
|
end
|
141
105
|
end
|
142
106
|
|
@@ -159,25 +123,16 @@ module Flapjack
|
|
159
123
|
def runner(type)
|
160
124
|
return @runner if @runner
|
161
125
|
|
162
|
-
|
163
|
-
|
164
|
-
pidfile = @options[:pidfile].nil? ?
|
165
|
-
(config_runner['pid_file'] || "/var/run/flapjack/#{type}-receiver.pid") :
|
166
|
-
@options[:pidfile]
|
167
|
-
|
168
|
-
logfile = @options[:logfile].nil? ?
|
169
|
-
(config_runner['log_file'] || "/var/log/flapjack/#{type}-receiver.log") :
|
170
|
-
@options[:logfile]
|
171
|
-
|
172
|
-
@runner = Dante::Runner.new("#{type}-receiver", :pid_path => pidfile,
|
173
|
-
:log_path => logfile)
|
126
|
+
@runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => @pidfile,
|
127
|
+
:log_path => @logfile)
|
174
128
|
@runner
|
175
129
|
end
|
176
130
|
|
177
131
|
def process_input(opts)
|
178
|
-
config_rec =
|
132
|
+
config_rec = case opts[:type]
|
133
|
+
when /nagios/
|
179
134
|
@config_env['nagios-receiver'] || {}
|
180
|
-
|
135
|
+
when /nsca/
|
181
136
|
@config_env['nsca-receiver'] || {}
|
182
137
|
else
|
183
138
|
raise "Unknown receiver type"
|
@@ -204,8 +159,8 @@ module Flapjack
|
|
204
159
|
check_latency, check_output, check_perfdata, check_long_output =
|
205
160
|
[nil] * 10
|
206
161
|
|
207
|
-
|
208
|
-
|
162
|
+
case opts[:type]
|
163
|
+
when /nagios/
|
209
164
|
object_type, timestamp, entity, check, state, check_time,
|
210
165
|
check_latency, check_output, check_perfdata, check_long_output = split_line
|
211
166
|
|
@@ -221,7 +176,7 @@ module Flapjack
|
|
221
176
|
next
|
222
177
|
end
|
223
178
|
|
224
|
-
|
179
|
+
when /nsca/
|
225
180
|
|
226
181
|
timestamp, passivecheck = split_line
|
227
182
|
split_passive = passivecheck.split(";")
|
@@ -269,12 +224,40 @@ module Flapjack
|
|
269
224
|
def main(opts)
|
270
225
|
fifo = opts[:fifo]
|
271
226
|
while true
|
272
|
-
process_input(:fifo => fifo, :
|
227
|
+
process_input(:fifo => fifo, :type => opts[:type])
|
273
228
|
puts "Whoops with the fifo, restarting main loop in 10 seconds"
|
274
229
|
sleep 10
|
275
230
|
end
|
276
231
|
end
|
277
232
|
|
233
|
+
def process_exists(pid)
|
234
|
+
return unless pid
|
235
|
+
begin
|
236
|
+
Process.kill(0, pid)
|
237
|
+
return true
|
238
|
+
rescue Errno::ESRCH
|
239
|
+
return false
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# wait until the specified pid no longer exists, or until a timeout is reached
|
244
|
+
def wait_pid_gone(pid, timeout = 30)
|
245
|
+
print "waiting for a max of #{timeout} seconds for process #{pid} to exit" if process_exists(pid)
|
246
|
+
started_at = Time.now.to_i
|
247
|
+
while process_exists(pid)
|
248
|
+
break unless (Time.now.to_i - started_at < timeout)
|
249
|
+
print '.'
|
250
|
+
sleep 1
|
251
|
+
end
|
252
|
+
puts ''
|
253
|
+
!process_exists(pid)
|
254
|
+
end
|
255
|
+
|
256
|
+
def get_pid
|
257
|
+
IO.read(@pidfile).chomp.to_i
|
258
|
+
rescue StandardError
|
259
|
+
pid = nil
|
260
|
+
end
|
278
261
|
|
279
262
|
class EventFeedHandler < Oj::ScHandler
|
280
263
|
|
@@ -319,8 +302,7 @@ module Flapjack
|
|
319
302
|
input = if opts[:from]
|
320
303
|
File.open(opts[:from]) # Explodes if file does not exist.
|
321
304
|
elsif $stdin.tty?
|
322
|
-
|
323
|
-
exit(1)
|
305
|
+
exit_now! "No file provided, and STDIN is from terminal! Exiting..."
|
324
306
|
else
|
325
307
|
$stdin
|
326
308
|
end
|
@@ -349,8 +331,7 @@ module Flapjack
|
|
349
331
|
|
350
332
|
def mirror_receive(opts)
|
351
333
|
unless opts[:follow] || opts[:all]
|
352
|
-
|
353
|
-
exit 1
|
334
|
+
exit_now! "one or both of --follow or --all is required"
|
354
335
|
end
|
355
336
|
|
356
337
|
source_redis = Redis.new(:url => opts[:source])
|
@@ -422,7 +403,7 @@ module Flapjack
|
|
422
403
|
end
|
423
404
|
end
|
424
405
|
|
425
|
-
desc 'Receive events from external systems and
|
406
|
+
desc 'Receive events from external systems and sends them to Flapjack'
|
426
407
|
arg_name 'receiver'
|
427
408
|
command :receiver do |receiver|
|
428
409
|
|
@@ -453,7 +434,7 @@ command :receiver do |receiver|
|
|
453
434
|
# host_perfdata_file_mode=p
|
454
435
|
# service_perfdata_file_mode=p
|
455
436
|
|
456
|
-
# Details on the wiki:
|
437
|
+
# Details on the wiki: http://flapjack.io/docs/1.0/usage/USING#configuring-nagios
|
457
438
|
# '
|
458
439
|
|
459
440
|
nagios.command :start do |start|
|
@@ -468,8 +449,9 @@ command :receiver do |receiver|
|
|
468
449
|
start.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
469
450
|
|
470
451
|
start.action do |global_options,options,args|
|
452
|
+
options.merge!(:type => 'nagios')
|
471
453
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
472
|
-
receiver.
|
454
|
+
receiver.start
|
473
455
|
end
|
474
456
|
end
|
475
457
|
|
@@ -480,8 +462,9 @@ command :receiver do |receiver|
|
|
480
462
|
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
481
463
|
|
482
464
|
stop.action do |global_options,options,args|
|
465
|
+
options.merge!(:type => 'nagios')
|
483
466
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
484
|
-
receiver.
|
467
|
+
receiver.stop
|
485
468
|
end
|
486
469
|
end
|
487
470
|
|
@@ -494,8 +477,9 @@ command :receiver do |receiver|
|
|
494
477
|
restart.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
495
478
|
|
496
479
|
restart.action do |global_options,options,args|
|
480
|
+
options.merge!(:type => 'nagios')
|
497
481
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
498
|
-
receiver.
|
482
|
+
receiver.restart
|
499
483
|
end
|
500
484
|
end
|
501
485
|
|
@@ -506,8 +490,9 @@ command :receiver do |receiver|
|
|
506
490
|
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
507
491
|
|
508
492
|
status.action do |global_options,options,args|
|
493
|
+
options.merge!(:type => 'nagios')
|
509
494
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
510
|
-
receiver.
|
495
|
+
receiver.status
|
511
496
|
end
|
512
497
|
end
|
513
498
|
|
@@ -535,7 +520,7 @@ command :receiver do |receiver|
|
|
535
520
|
# The Nsca daemon is optionally writing to a tempfile if the named pipe does
|
536
521
|
# not exist.
|
537
522
|
|
538
|
-
# Details on the wiki:
|
523
|
+
# Details on the wiki: http://flapjack.io/docs/1.0/usage/USING#XXX
|
539
524
|
# '
|
540
525
|
|
541
526
|
start.switch [:d, 'daemonize'], :desc => 'Daemonize',
|
@@ -548,8 +533,9 @@ command :receiver do |receiver|
|
|
548
533
|
start.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
549
534
|
|
550
535
|
start.action do |global_options,options,args|
|
536
|
+
options.merge!(:type => 'nsca')
|
551
537
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
552
|
-
receiver.
|
538
|
+
receiver.start
|
553
539
|
end
|
554
540
|
end
|
555
541
|
|
@@ -560,8 +546,9 @@ command :receiver do |receiver|
|
|
560
546
|
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
561
547
|
|
562
548
|
stop.action do |global_options,options,args|
|
549
|
+
options.merge!(:type => 'nsca')
|
563
550
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
564
|
-
receiver.
|
551
|
+
receiver.stop
|
565
552
|
end
|
566
553
|
end
|
567
554
|
|
@@ -574,8 +561,9 @@ command :receiver do |receiver|
|
|
574
561
|
restart.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
575
562
|
|
576
563
|
restart.action do |global_options,options,args|
|
564
|
+
options.merge!(:type => 'nsca')
|
577
565
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
578
|
-
receiver.
|
566
|
+
receiver.restart
|
579
567
|
end
|
580
568
|
end
|
581
569
|
|
@@ -586,8 +574,9 @@ command :receiver do |receiver|
|
|
586
574
|
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
587
575
|
|
588
576
|
status.action do |global_options,options,args|
|
577
|
+
options.merge!(:type => 'nsca')
|
589
578
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
590
|
-
receiver.
|
579
|
+
receiver.status
|
591
580
|
end
|
592
581
|
end
|
593
582
|
|