flapjack 0.9.6 → 1.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +6 -0
  4. data/.travis.yml +20 -16
  5. data/CHANGELOG.md +11 -25
  6. data/Dockerfile +8 -0
  7. data/Gemfile +2 -5
  8. data/bin/flapjack +24 -213
  9. data/etc/flapjack_config.yaml.example +6 -30
  10. data/features/cli.feature +16 -14
  11. data/features/cli_flapjack-feed-events.feature +12 -13
  12. data/features/cli_flapjack-nagios-receiver.feature +14 -15
  13. data/features/cli_flapjack-populator.feature +16 -15
  14. data/features/cli_flapper.feature +12 -12
  15. data/features/cli_receive-events.feature +6 -5
  16. data/features/cli_simulate-failed-check.feature +7 -6
  17. data/features/steps/cli_steps.rb +2 -2
  18. data/features/support/env.rb +1 -0
  19. data/flapjack.gemspec +1 -0
  20. data/lib/flapjack/cli/flapper.rb +200 -0
  21. data/lib/flapjack/cli/import.rb +102 -0
  22. data/lib/flapjack/cli/receiver.rb +656 -0
  23. data/lib/flapjack/cli/server.rb +256 -0
  24. data/lib/flapjack/cli/simulate.rb +180 -0
  25. data/lib/flapjack/configuration.rb +2 -0
  26. data/lib/flapjack/data/entity_check.rb +5 -22
  27. data/lib/flapjack/data/event.rb +7 -12
  28. data/lib/flapjack/gateways/email.rb +4 -1
  29. data/lib/flapjack/gateways/jabber.rb +12 -36
  30. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
  31. data/lib/flapjack/gateways/jsonapi/report_methods.rb +5 -3
  32. data/lib/flapjack/gateways/pagerduty.rb +1 -1
  33. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
  34. data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
  35. data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
  36. data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
  37. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
  38. data/lib/flapjack/gateways/web/views/check.html.erb +7 -7
  39. data/lib/flapjack/gateways/web/views/checks.html.erb +2 -3
  40. data/lib/flapjack/gateways/web/views/contact.html.erb +4 -4
  41. data/lib/flapjack/gateways/web/views/contacts.html.erb +2 -2
  42. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +1 -1
  43. data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
  44. data/lib/flapjack/gateways/web/views/entity.html.erb +1 -1
  45. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  46. data/lib/flapjack/gateways/web/views/layout.erb +10 -10
  47. data/lib/flapjack/gateways/web/views/self_stats.html.erb +1 -1
  48. data/lib/flapjack/gateways/web.rb +36 -7
  49. data/lib/flapjack/pikelet.rb +0 -2
  50. data/lib/flapjack/processor.rb +3 -1
  51. data/lib/flapjack/redis_pool.rb +2 -6
  52. data/lib/flapjack/version.rb +1 -1
  53. data/spec/lib/flapjack/coordinator_spec.rb +3 -3
  54. data/spec/lib/flapjack/data/entity_check_spec.rb +2 -6
  55. data/spec/lib/flapjack/data/event_spec.rb +0 -31
  56. data/spec/lib/flapjack/gateways/email_spec.rb +109 -0
  57. data/spec/lib/flapjack/gateways/jabber_spec.rb +18 -16
  58. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +12 -24
  59. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
  60. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +2 -0
  61. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -0
  62. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +2 -0
  63. data/spec/lib/flapjack/gateways/web_spec.rb +194 -145
  64. data/spec/lib/flapjack/redis_pool_spec.rb +0 -1
  65. data/spec/support/profile_all_formatter.rb +44 -0
  66. data/spec/support/uncolored_doc_formatter.rb +9 -0
  67. data/tasks/benchmarks.rake +0 -4
  68. metadata +28 -38
  69. data/.ruby-version +0 -1
  70. data/Gemfile-ruby1.9 +0 -28
  71. data/Gemfile-ruby1.9.lock +0 -227
  72. data/bin/flapjack-feed-events +0 -124
  73. data/bin/flapjack-nagios-receiver +0 -246
  74. data/bin/flapjack-nsca-receiver +0 -246
  75. data/bin/flapjack-populator +0 -132
  76. data/bin/flapper +0 -152
  77. data/bin/receive-events +0 -179
  78. data/bin/simulate-failed-check +0 -151
  79. data/lib/flapjack/data/migration.rb +0 -36
  80. data/lib/flapjack/gateways/api/contact_methods.rb +0 -369
  81. data/lib/flapjack/gateways/api/entity_check_presenter.rb +0 -218
  82. data/lib/flapjack/gateways/api/entity_methods.rb +0 -361
  83. data/lib/flapjack/gateways/api/entity_presenter.rb +0 -75
  84. data/lib/flapjack/gateways/api/rack/json_params_parser.rb +0 -26
  85. data/lib/flapjack/gateways/api.rb +0 -124
  86. data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +0 -772
  87. data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +0 -211
  88. data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +0 -863
  89. data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +0 -108
  90. data/spec/lib/flapjack/gateways/api_spec.rb +0 -30
@@ -0,0 +1,256 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dante'
4
+
5
+ require 'oj'
6
+ Oj.mimic_JSON
7
+ Oj.default_options = { :indent => 0, :mode => :strict }
8
+ require 'active_support/json'
9
+
10
+ require 'flapjack/coordinator'
11
+
12
+ module Flapjack
13
+ module CLI
14
+ class Server
15
+
16
+ def initialize(global_options, options)
17
+ @global_options = global_options
18
+ @options = options
19
+
20
+ @config = Flapjack::Configuration.new
21
+ @config.load(global_options[:config])
22
+ @config_env = @config.all
23
+
24
+ if @config_env.nil? || @config_env.empty?
25
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
26
+ exit 1
27
+ end
28
+
29
+ if options[:rbtrace]
30
+ require 'rbtrace'
31
+ end
32
+ end
33
+
34
+ def start
35
+ if runner.daemon_running?
36
+ puts "Flapjack is already running."
37
+ else
38
+ print "Flapjack starting..."
39
+ print "\n" unless @options[:daemonize]
40
+ return_value = nil
41
+ runner.execute(:daemonize => @options[:daemonize]) {
42
+ return_value = start_server
43
+ }
44
+ puts " done."
45
+ exit(return_value) unless return_value.nil?
46
+ end
47
+ end
48
+
49
+ def stop
50
+ if runner.daemon_running?
51
+ print "Flapjack stopping..."
52
+ runner.execute(:kill => true)
53
+ puts " done."
54
+ else
55
+ puts "Flapjack is not running."
56
+ end
57
+ exit 1 unless wait_pid_gone(get_pid)
58
+ end
59
+
60
+ def restart
61
+ if runner.daemon_running?
62
+ print "Flapjack stopping..."
63
+ runner.execute(:kill => true)
64
+ puts " done."
65
+ end
66
+ exit 1 unless wait_pid_gone(get_pid)
67
+
68
+ @runner = nil
69
+
70
+ print "Flapjack starting..."
71
+ runner.execute(:daemonize => true) {
72
+ start_server
73
+ }
74
+ puts " done."
75
+ end
76
+
77
+ def reload
78
+ if runner.daemon_running?
79
+ pid = get_pid
80
+ print "Reloading Flapjack configuration..."
81
+ begin
82
+ Process.kill('HUP', pid)
83
+ puts " sent HUP to pid #{pid}."
84
+ rescue => e
85
+ puts " couldn't send HUP to pid '#{pid}'."
86
+ end
87
+ else
88
+ puts "Flapjack is not running daemonized."
89
+ exit 1
90
+ end
91
+ end
92
+
93
+ def status
94
+ pidfile = @options[:pidfile] || @config_env['pid_file'] ||
95
+ "/var/run/flapjack/flapjack.pid"
96
+
97
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
98
+ if runner.daemon_running?
99
+ pid = get_pid
100
+ puts "Flapjack is running: pid #{pid}, uptime #{uptime}"
101
+ else
102
+ puts "Flapjack is not running"
103
+ exit 3
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def runner
110
+ return @runner if @runner
111
+
112
+ self.class.skip_dante_traps
113
+
114
+ pidfile = @options[:pidfile].nil? ?
115
+ (@config_env['pid_file'] || "/var/run/flapjack/flapjack.pid") :
116
+ @options[:pidfile]
117
+
118
+ logfile = @options[:logfile].nil? ?
119
+ (@config_env['log_file'] || "/var/log/flapjack/flapjack.log") :
120
+ @options[:logfile]
121
+
122
+ @runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
123
+ :log_path => logfile)
124
+ @runner
125
+ end
126
+
127
+ def self.skip_dante_traps
128
+ return if Dante::Runner.respond_to?(:orig_start)
129
+ Dante::Runner.send(:alias_method, :orig_start, :start)
130
+ Dante::Runner.send(:define_method, :start) do
131
+ if log_path = options[:log_path] && options[:daemonize].nil?
132
+ redirect_output!
133
+ end
134
+
135
+ # skip signal traps
136
+ @startup_command.call(self.options) if @startup_command
137
+ end
138
+ end
139
+
140
+ def start_server
141
+ @coordinator = Flapjack::Coordinator.new(@config)
142
+ @coordinator.start(:signals => true)
143
+ end
144
+
145
+ def process_exists(pid)
146
+ return unless pid
147
+ begin
148
+ Process.kill(0, pid)
149
+ return true
150
+ rescue Errno::ESRCH
151
+ return false
152
+ end
153
+ end
154
+
155
+ # wait until the specified pid no longer exists, or until a timeout is reached
156
+ def wait_pid_gone(pid, timeout = 30)
157
+ print "waiting for a max of #{timeout} seconds for process #{pid} to exit" if process_exists(pid)
158
+ started_at = Time.now.to_i
159
+ while process_exists(pid)
160
+ break unless (Time.now.to_i - started_at < timeout)
161
+ print '.'
162
+ sleep 1
163
+ end
164
+ puts ''
165
+ !process_exists(pid)
166
+ end
167
+
168
+ def get_pid
169
+ IO.read(pidfile).chomp.to_i
170
+ rescue StandardError
171
+ pid = nil
172
+ end
173
+
174
+ end
175
+ end
176
+ end
177
+
178
+ desc 'Server for running components (e.g. processor, notifier, gateways)'
179
+ command :server do |server|
180
+
181
+ server.desc 'Start the server'
182
+
183
+ server.command :start do |start|
184
+
185
+ start.switch [:d, 'daemonize'], :desc => 'Daemonize',
186
+ :default_value => true
187
+
188
+ start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
189
+
190
+ start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
191
+
192
+ start.flag [:r, 'rbtrace'], :desc => 'Enable rbtrace profiling'
193
+
194
+ start.action do |global_options,options,args|
195
+ server = Flapjack::CLI::Server.new(global_options, options)
196
+ server.start
197
+ end
198
+ end
199
+
200
+ server.desc 'Stop the server'
201
+ server.command :stop do |stop|
202
+
203
+ stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
204
+
205
+ stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
206
+
207
+ stop.action do |global_options,options,args|
208
+ server = Flapjack::CLI::Server.new(global_options, options)
209
+ server.stop
210
+ end
211
+ end
212
+
213
+ server.desc 'Restart the server'
214
+ server.command :restart do |restart|
215
+
216
+ restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
217
+
218
+ restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
219
+
220
+ restart.flag [:r, 'rbtrace'], :desc => 'Enable rbtrace profiling'
221
+
222
+ restart.action do |global_options,options,args|
223
+ server = Flapjack::CLI::Server.new(global_options, options)
224
+ server.restart
225
+ end
226
+ end
227
+
228
+ server.desc 'Reload the server configuration'
229
+ server.command :reload do |reload|
230
+
231
+ reload.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
232
+
233
+ reload.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
234
+
235
+ reload.action do |global_options,options,args|
236
+ server = Flapjack::CLI::Server.new(global_options, options)
237
+ server.reload
238
+ end
239
+ end
240
+
241
+ server.desc 'Get server status'
242
+ server.command :status do |status|
243
+
244
+ status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
245
+
246
+ status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
247
+
248
+ status.action do |global_options,options,args|
249
+ server = Flapjack::CLI::Server.new(global_options, options)
250
+ server.status
251
+ end
252
+ end
253
+
254
+ end
255
+
256
+
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redis'
4
+
5
+ require 'flapjack/configuration'
6
+ require 'flapjack/data/event'
7
+
8
+ module Flapjack
9
+ module CLI
10
+ class Simulate
11
+
12
+ def initialize(global_options, options)
13
+ @global_options = global_options
14
+ @options = options
15
+
16
+ config = Flapjack::Configuration.new
17
+ config.load(global_options[:config])
18
+ @config_env = config.all
19
+
20
+ if @config_env.nil? || @config_env.empty?
21
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
22
+ exit 1
23
+ end
24
+
25
+ @redis_options = config.for_redis
26
+ end
27
+
28
+ def _fail
29
+ events(:state => @options[:state], :recover => false,
30
+ :entity => @options[:entity], :check => @options[:check],
31
+ :tags => @options[:tags],
32
+ :minutes => @options[:time].to_f, :interval => @options[:interval].to_f)
33
+ end
34
+
35
+ def fail_and_recover
36
+ events(:state => @options[:state], :recover => true,
37
+ :entity => @options[:entity], :check => @options[:check],
38
+ :tags => @options[:tags],
39
+ :minutes => @options[:time].to_f, :interval => @options[:interval].to_f)
40
+ end
41
+
42
+ def ok
43
+ events(:state => 'ok', :recover => false,
44
+ :entity => @options[:entity], :check => @options[:check],
45
+ :tags => @options[:tags],
46
+ :minutes => @options[:time].to_f, :interval => @options[:interval].to_f)
47
+ end
48
+
49
+ private
50
+
51
+ def redis
52
+ @redis ||= Redis.new(@redis_options)
53
+ end
54
+
55
+ def events(opts = {})
56
+ stop_after = (opts[:minutes] * 60).to_i
57
+ recover = opts[:recover]
58
+ state = opts[:state] || 'critical'
59
+ event = {
60
+ 'entity' => opts[:entity] || 'foo-app-01',
61
+ 'check' => opts[:check] || 'HTTP',
62
+ 'tags' => opts[:tags] || [],
63
+ 'type' => 'service'
64
+ }
65
+ failure = event.merge('state' => state, 'summary' => 'Simulated check output (test by operator)')
66
+ recovery = event.merge('state' => 'ok', 'summary' => 'Simulated check output (test by operator)')
67
+ key = "#{event['entity']}:#{event['check']}"
68
+
69
+ puts "#{Time.now}: sending failure event (#{state}) for #{key}"
70
+ Flapjack::Data::Event.add(failure, :redis => redis)
71
+
72
+ EM.run do
73
+
74
+ EM.add_timer(stop_after) do
75
+ puts "#{Time.now}: stopping"
76
+ if recover
77
+ puts "#{Time.now}: sending recovery event for #{key}"
78
+ Flapjack::Data::Event.add(recovery.merge('time' => Time.now.to_i),
79
+ :redis => redis)
80
+ end
81
+ EM.stop
82
+ end
83
+
84
+ EM.add_periodic_timer(opts[:interval]) do
85
+ puts "#{Time.now}: sending failure event (#{state}) for #{key}"
86
+ Flapjack::Data::Event.add(failure.merge('time' => Time.now.to_i),
87
+ :redis => redis)
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
96
+
97
+ desc 'Generate streams of events in various states'
98
+ command :simulate do |simulate|
99
+
100
+ simulate.desc 'Generate a stream of failure events'
101
+ simulate.command :fail do |_fail|
102
+ # Because `fail` is a keyword (that you can actually override in a block,
103
+ # but we want to be good Ruby citizens).
104
+
105
+ _fail.flag [:t, 'time'], :desc => "MINUTES to generate failure events for (0.75)",
106
+ :default_value => 0.75
107
+
108
+ _fail.flag [:i, 'interval'], :desc => "SECONDS between events, can be decimal eg 0.1 (10)",
109
+ :default_value => 10
110
+
111
+ _fail.flag [:e, 'entity'], :desc => "ENTITY to generate failure events for ('foo-app-01')",
112
+ :default_value => 'foo-app-01'
113
+
114
+ _fail.flag [:k, 'check'], :desc => "CHECK to generate failure events for ('HTTP')",
115
+ :default_value => 'HTTP'
116
+
117
+ _fail.flag [:s, 'state'], :desc => "STATE to generate failure events with ('critical')",
118
+ :default_value => 'critical'
119
+
120
+ _fail.flag [:T, 'tags'], :desc => "optional comma-separated list of TAGS to include as part of the event",
121
+ :type => Array, :default_value => []
122
+
123
+ _fail.action do |global_options,options,args|
124
+ simulate = Flapjack::CLI::Simulate.new(global_options, options)
125
+ simulate._fail
126
+ end
127
+ end
128
+
129
+ simulate.desc 'Generate a stream of failure events, and one final recovery'
130
+ simulate.command :fail_and_recover do |fail_and_recover|
131
+
132
+ fail_and_recover.flag [:t, 'time'], :desc => "MINUTES to generate failure events for (0.75)",
133
+ :default_value => 0.75
134
+
135
+ fail_and_recover.flag [:i, 'interval'], :desc => "SECONDS between events, can be decimal eg 0.1 (10)",
136
+ :default_value => 10
137
+
138
+ fail_and_recover.flag [:e, 'entity'], :desc => "ENTITY to generate failure events for ('foo-app-01')",
139
+ :default_value => 'foo-app-01'
140
+
141
+ fail_and_recover.flag [:k, 'check'], :desc => "CHECK to generate failure events for ('HTTP')",
142
+ :default_value => 'HTTP'
143
+
144
+ fail_and_recover.flag [:s, 'state'], :desc => "STATE to generate failure events with ('critical')",
145
+ :default_value => 'critical'
146
+
147
+ fail_and_recover.flag [:T, 'tags'], :desc => "optional comma-separated list of TAGS to include as part of the event",
148
+ :type => Array, :default_value => []
149
+
150
+ fail_and_recover.action do |global_options,options,args|
151
+ simulate = Flapjack::CLI::Simulate.new(global_options, options)
152
+ simulate.fail_and_recover
153
+ end
154
+ end
155
+
156
+ simulate.desc 'Generate a stream of ok events'
157
+ simulate.command :ok do |ok|
158
+
159
+ ok.flag [:t, 'time'], :desc => "MINUTES to generate ok events for (0.75)",
160
+ :default_value => 0.75
161
+
162
+ ok.flag [:i, 'interval'], :desc => "SECONDS between events, can be decimal eg 0.1 (10)",
163
+ :default_value => 10
164
+
165
+ ok.flag [:e, 'entity'], :desc => "ENTITY to generate ok events for ('foo-app-01')",
166
+ :default_value => 'foo-app-01'
167
+
168
+ ok.flag [:k, 'check'], :desc => "CHECK to generate ok events for ('HTTP')",
169
+ :default_value => 'HTTP'
170
+
171
+ ok.flag [:T, 'tags'], :desc => "optional comma-separated list of TAGS to include as part of the event",
172
+ :type => Array, :default_value => []
173
+
174
+ ok.action do |global_options,options,args|
175
+ simulate = Flapjack::CLI::Simulate.new(global_options, options)
176
+ simulate.ok
177
+ end
178
+ end
179
+
180
+ end
@@ -45,6 +45,8 @@ module Flapjack
45
45
  :port => (redis['port'] || 6379)})
46
46
  )
47
47
 
48
+ redis_config[:password] = redis["password"] if redis["password"]
49
+
48
50
  redis_config
49
51
  end
50
52
 
@@ -30,23 +30,10 @@ module Flapjack
30
30
  def self.for_event_id(event_id, options = {})
31
31
  raise "Redis connection not set" unless redis = options[:redis]
32
32
  entity_name, check_name = event_id.split(':', 2)
33
- logger = options[:logger]
34
- if logger
35
- logger.debug("Flapjack::Data::EntityCheck#self.for_event_id called for event_id: #{event_id}")
36
- logger.debug("Flapjack::Data::EntityCheck#self.for_event_id found entity_name: #{entity_name}, check_name: #{check_name}")
37
- end
38
33
  create_entity = options[:create_entity]
34
+ logger = options[:logger]
39
35
  entity = Flapjack::Data::Entity.find_by_name(entity_name,
40
36
  :create => create_entity, :logger => logger, :redis => redis)
41
- if logger
42
- logger.debug("Flapjack::Data::EntityCheck#self.for_event_id found entity by name(#{entity_name}): #{entity.inspect}")
43
- end
44
- unless entity
45
- if logger
46
- logger.error("entity can't be instantiated for #{entity_name}!")
47
- end
48
- return nil
49
- end
50
37
  self.new(entity, check_name, :logger => logger, :redis => redis)
51
38
  end
52
39
 
@@ -127,13 +114,12 @@ module Flapjack
127
114
 
128
115
  def self.unacknowledged_failing(options = {})
129
116
  raise "Redis connection not set" unless redis = options[:redis]
130
- logger = options[:logger]
131
117
 
132
118
  redis.zrange('failed_checks', '0', '-1').reject {|entity_check|
133
119
  redis.exists(entity_check + ':unscheduled_maintenance')
134
120
  }.collect {|entity_check|
135
- Flapjack::Data::EntityCheck.for_event_id(entity_check, :redis => redis, :logger => logger)
136
- }.compact
121
+ Flapjack::Data::EntityCheck.for_event_id(entity_check, :redis => redis)
122
+ }
137
123
  end
138
124
 
139
125
  def self.conflate_to_keys(entity_checks_hash)
@@ -329,11 +315,8 @@ module Flapjack
329
315
  # if multiple scheduled maintenances found, find the end_time furthest in the future
330
316
  most_futuristic = current_sched_ms.max {|sm| sm[:end_time] }
331
317
  start_time = most_futuristic[:start_time]
332
-
333
- duration = most_futuristic[:end_time] - current_time
334
- if duration > 0
335
- @redis.setex("#{@key}:scheduled_maintenance", duration.to_i, start_time)
336
- end
318
+ duration = most_futuristic[:duration]
319
+ @redis.setex("#{@key}:scheduled_maintenance", duration.to_i, start_time)
337
320
  end
338
321
 
339
322
  # TODO allow summary to be changed as part of the termination
@@ -3,8 +3,6 @@
3
3
  require 'oj'
4
4
  require 'flapjack/data/tag_set'
5
5
 
6
- require 'flapjack/data/migration'
7
-
8
6
  module Flapjack
9
7
  module Data
10
8
  class Event
@@ -80,27 +78,24 @@ module Flapjack
80
78
  :events_archive_maxage => (3 * 60 * 60) }
81
79
  options = defaults.merge(opts)
82
80
 
83
- archive_dest = nil
81
+ archive_dest = nil
84
82
  base_time_str = Time.now.utc.strftime("%Y%m%d%H")
85
83
 
86
84
  if options[:archive_events]
87
85
  archive_dest = "events_archive:#{base_time_str}"
88
- unless @previous_base_time_str == base_time_str
89
- Flapjack::Data::Migration.purge_expired_archive_index(:redis => redis)
90
- end
91
- @previous_base_time_str = base_time_str
92
86
  if options[:block]
93
87
  raw = redis.brpoplpush(queue, archive_dest, 0)
94
88
  else
95
89
  raw = redis.rpoplpush(queue, archive_dest)
96
90
  return unless raw
97
91
  end
98
- redis.sadd("known_events_archive_keys", archive_dest)
99
- elsif options[:block]
100
- raw = redis.brpop(queue, 0)[1]
101
92
  else
102
- raw = redis.rpop(queue)
103
- return unless raw
93
+ if options[:block]
94
+ raw = redis.brpop(queue, 0)[1]
95
+ else
96
+ raw = redis.rpop(queue)
97
+ return unless raw
98
+ end
104
99
  end
105
100
  parsed = parse_and_validate(raw, :logger => options[:logger])
106
101
  if parsed.nil?
@@ -52,6 +52,7 @@ module Flapjack
52
52
  port = @smtp_config ? @smtp_config['port'] : nil
53
53
  starttls = @smtp_config ? !! @smtp_config['starttls'] : nil
54
54
  m_from = @smtp_config ? @smtp_config['from'] : "flapjack@#{@fqdn}"
55
+ m_reply_to = @smtp_config ? ( @smtp_config['reply_to'] ||= m_from ) : "flapjack@#{@fqdn}"
55
56
  if @smtp_config
56
57
  if auth_config = @smtp_config['auth']
57
58
  auth = {}
@@ -64,6 +65,7 @@ module Flapjack
64
65
  @logger.debug("flapjack_mailer: set from to #{m_from}")
65
66
 
66
67
  mail = prepare_email(:from => m_from,
68
+ :reply_to => m_reply_to,
67
69
  :to => alert.address,
68
70
  :message_id => "<#{alert.notification_id}@#{@fqdn}>",
69
71
  :alert => alert)
@@ -103,6 +105,7 @@ module Flapjack
103
105
  # returns a Mail object
104
106
  def prepare_email(opts = {})
105
107
  from = opts[:from]
108
+ reply_to = opts[:reply_to]
106
109
  to = opts[:to]
107
110
  message_id = opts[:message_id]
108
111
  alert = opts[:alert]
@@ -157,7 +160,7 @@ module Flapjack
157
160
  from from
158
161
  to to
159
162
  subject subject
160
- reply_to from
163
+ reply_to reply_to
161
164
  message_id message_id
162
165
 
163
166
  text_part do