/lib/flapjack/cli/flapper.rb

https://github.com/clarkf/flapjack · Ruby · 200 lines · 155 code · 43 blank · 2 comment · 6 complexity · 649151a35636c5ed9cbe6b15c9b24099 MD5 · raw file

  1. #!/usr/bin/env ruby
  2. require 'eventmachine'
  3. require 'socket'
  4. require 'dante'
  5. module Flapjack
  6. module CLI
  7. class Flapper
  8. def self.local_ip
  9. # turn off reverse DNS resolution temporarily
  10. orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
  11. UDPSocket.open do |s|
  12. s.connect '64.233.187.99', 1
  13. s.addr.last
  14. end
  15. ensure
  16. Socket.do_not_reverse_lookup = orig
  17. end
  18. def initialize(global_options, options)
  19. @global_options = global_options
  20. @options = options
  21. end
  22. def start
  23. if runner.daemon_running?
  24. puts "flapper is already running."
  25. exit 1
  26. else
  27. print "flapper starting..."
  28. runner.execute(:daemonize => @options[:daemonize]) do
  29. main(@options['bind-ip'], @options['bind-port'].to_i, @options[:frequency])
  30. end
  31. puts " done."
  32. end
  33. end
  34. def stop
  35. if runner.daemon_running?
  36. print "flapper stopping..."
  37. runner.execute(:kill => true)
  38. puts " done."
  39. else
  40. puts "flapper is not running."
  41. exit 1
  42. end
  43. end
  44. def restart
  45. print "flapper restarting..."
  46. runner.execute(:daemonize => true, :restart => true) do
  47. main(@options['bind-ip'], @options['bind-port'].to_i, @options[:frequency])
  48. end
  49. puts " done."
  50. end
  51. def status
  52. uptime = (runner.daemon_running?) ? (Time.now - File.stat(@options[:pidfile]).ctime) : 0
  53. if runner.daemon_running?
  54. puts "flapper is running: #{uptime}"
  55. else
  56. puts "flapper is not running"
  57. exit 3
  58. end
  59. end
  60. private
  61. module Receiver
  62. def receive_data(data)
  63. send_data ">>>you sent: #{data}"
  64. close_connection if data === /quit/i
  65. end
  66. end
  67. def runner
  68. return @runner if @runner
  69. @runner = Dante::Runner.new('flapper', :pid_path => @options[:pidfile],
  70. :log_path => @options[:logfile])
  71. @runner
  72. end
  73. def main(bind_ip, bind_port, frequency)
  74. raise "bind_port must be an integer" unless bind_port.is_a?(Integer) && (bind_port > 0)
  75. start_every = frequency
  76. stop_after = frequency.to_f / 2
  77. EM.run do
  78. puts "#{Time.now}: starting server on #{bind_ip}:#{bind_port}"
  79. server_init = EM.start_server bind_ip, bind_port, Flapjack::CLI::Flapper::Receiver
  80. EM.add_timer(stop_after) do
  81. puts "#{Time.now}: stopping server"
  82. EM.stop_server(server_init)
  83. end
  84. EM.add_periodic_timer(start_every) do
  85. puts "#{Time.now}: starting server on #{bind_ip}:#{bind_port}"
  86. server = EM.start_server bind_ip, bind_port, Flapjack::CLI::Flapper::Receiver
  87. EM.add_timer(stop_after) do
  88. puts "#{Time.now}: stopping server"
  89. EM.stop_server(server)
  90. end
  91. end
  92. end
  93. end
  94. end
  95. end
  96. end
  97. desc 'Artificial service that oscillates up and down, for use in http://flapjack.io/docs/1.0/usage/oobetet'
  98. command :flapper do |flapper|
  99. flapper.desc 'start flapper'
  100. flapper.command :start do |start|
  101. start.switch [:d, 'daemonize'], :desc => 'Daemonize',
  102. :default_value => true
  103. start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to',
  104. :default_value => "/var/run/flapjack/flapper.pid"
  105. start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to',
  106. :default_value => "/var/log/flapjack/flapper.log"
  107. start.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
  108. :default_value => Flapjack::CLI::Flapper.local_ip
  109. start.flag [:P, 'bind-port'], :desc => 'PORT for flapper to bind to (default: 12345)',
  110. :default_value => '12345'
  111. start.flag [:f, 'frequency'], :desc => 'oscillate with a frequency of SECONDS [120]',
  112. :default_value => '120.0'
  113. start.action do |global_options, options, args|
  114. cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
  115. cli_flapper.start
  116. end
  117. end
  118. flapper.desc 'stop flapper'
  119. flapper.command :stop do |stop|
  120. stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to',
  121. :default_value => "/var/run/flapjack/flapper.pid"
  122. stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to',
  123. :default_value => "/var/log/flapjack/flapper.log"
  124. stop.action do |global_options, options, args|
  125. cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
  126. cli_flapper.stop
  127. end
  128. end
  129. flapper.desc 'restart flapper'
  130. flapper.command :restart do |restart|
  131. restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to',
  132. :default_value => "/var/run/flapjack/flapper.pid"
  133. restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to',
  134. :default_value => "/var/log/flapjack/flapper.log"
  135. restart.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
  136. :default_value => Flapjack::CLI::Flapper.local_ip
  137. restart.flag [:P, 'bind-port'], :desc => 'PORT for flapper to bind to (default: 12345)',
  138. :default_value => 12345
  139. restart.flag [:f, 'frequency'], :desc => 'oscillate with a frequency of SECONDS [120]',
  140. :default_value => 120.0
  141. restart.action do |global_options, options, args|
  142. cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
  143. cli_flapper.restart
  144. end
  145. end
  146. flapper.desc 'flapper status'
  147. flapper.command :status do |status|
  148. status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to',
  149. :default_value => "/var/run/flapjack/flapper.pid"
  150. status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to',
  151. :default_value => "/var/log/flapjack/flapper.log"
  152. status.action do |global_options, options, args|
  153. cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
  154. cli_flapper.status
  155. end
  156. end
  157. end