#!/usr/bin/env ruby unless $:.include?(File.dirname(__FILE__) + '/../lib/') $: << File.dirname(__FILE__) + '/../lib' end require 'optparse' require 'ostruct' require 'redis' require 'eventmachine' require 'json' require 'flapjack/configuration' require 'flapjack/data/event' def pike(message) puts "piking out: #{message}" exit 1 end def send_event(event, opts) redis = opts[:redis] Flapjack::Data::Event.add(event, :redis => redis) end def fail(opts) redis = Redis.new(opts[:redis_options]) stop_after = (opts[:minutes] * 60).to_i recover = opts[:recover] state = opts[:state] || 'critical' event = { 'entity' => opts[:entity] || 'foo-app-01', 'check' => opts[:check] || 'HTTP', 'type' => 'service' } failure = event.merge('state' => state, 'summary' => 'Simulated check output (test by operator)') recovery = event.merge('state' => 'ok', 'summary' => 'Simulated check output (test by operator)') key = "#{event['entity']}:#{event['check']}" puts "#{Time.now}: sending failure event (#{state}) for #{key}" send_event(failure, :redis => redis) EM.run { EM.add_timer(stop_after) do puts "#{Time.now}: stopping" if recover puts "#{Time.now}: sending recovery event for #{key}" send_event(recovery.merge('time' => Time.now.to_i), :redis => redis) end EM.stop end EM.add_periodic_timer(opts[:interval]) do puts "#{Time.now}: sending failure event (#{state}) for #{key}" send_event(failure.merge('time' => Time.now.to_i), :redis => redis) end } end options = OpenStruct.new options.config = Flapjack::Configuration::DEFAULT_CONFIG_PATH options.daemonize = nil exe = File.basename(__FILE__) optparse = OptionParser.new do |opts| opts.banner = "Usage: #{exe} COMMAND [OPTIONS]" opts.separator "" opts.separator "Commands" opts.separator " fail-and-recover" opts.separator " fail" opts.separator "" opts.separator "Options" opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c| options.config = c end opts.on("-n", "--environment [ENV]", String, "Environment to boot") do |e| options.environment = e end opts.on("-t", "--time MINUTES", String, "MINUTES to generate failure events for (0.75)") do |t| options.minutes = t.to_f end opts.on("-i", "--interval SECONDS", String, "SECONDS between events, can be decimal eg 0.1 (10)") do |i| options.interval = i.to_f end opts.on("-e", "--entity ENTITY", String, "ENTITY to generate failure events for ('foo-app-01')") do |e| options.entity = e end opts.on("-k", "--check CHECK", String, "CHECK to generate failure events for ('HTTP')") do |k| options.check = k end opts.on("-s", "--state STATE", String, "optional STATE to generate failure events with ('CRITICAL')") do |s| options.state = s end end optparse.parse!(ARGV) unless options.interval.to_f > 0 options.interval = 10.0 end unless options.minutes options.minutes = 0.75 end FLAPJACK_ENV = options.environment || ENV['FLAPJACK_ENV'] || 'production' config = Flapjack::Configuration.new config.load(options.config) config_env = config.all redis_options = config.for_redis if config_env.nil? || config_env.empty? puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'" puts "\n#{optparse}" exit 1 end options = {:redis_options => redis_options, :minutes => options.minutes, :entity => options.entity, :check => options.check, :state => options.state, :interval => options.interval} case ARGV[0] when "fail-and-recover" fail(options.merge(:recover => true)) puts " done." when "fail" fail(options.merge(:recover => false)) puts " done." else if ARGV.nil? || ARGV.empty? puts "No command provided." else puts "Unknown command provided: '#{ARGV[0]}'" end puts "\n#{optparse}" exit 1 end