class Opsicle::Monitor::App

Constants

API_POLLING_INTERVAL
SCREEN_REFRESH_INTERVAL

Attributes

client[RW]
deploy[R]
deployment_id[R]
restarting[R]
running[R]

Public Class Methods

new(environment, options) click to toggle source
# File lib/opsicle/monitor/app.rb, line 24
def initialize(environment, options)
  @running       = false
  @restarting    = false
  @threads       = {}
  @deployment_id = options[:deployment_id]

  # Make client with correct configuration available to monitor spies
  App.client = Client.new(environment)
  if @deployment_id
    # `deploy`, `chef-update`, `execute-recipes` command, which is no-tty compatible so these can be automated via cron, etc.
    @deploy = Opsicle::Deployment.new(@deployment_id, App.client)
  else
    # `monitor` command, which requires a TTY.
    raise "Monitor requires a TTY." unless $stdout.tty?
  end
end

Public Instance Methods

do_command(key) click to toggle source
# File lib/opsicle/monitor/app.rb, line 88
def do_command(key)
  command = { 'q' => :stop,
              'h' => [:set_screen, :help],
              'b' => :open_opsworks_browser,
              'd' => [:set_screen, :deployments],
              'i' => [:set_screen, :instances], }[key]
  command ||= :invalid_input

  send *command unless command == :invalid_input

  wakey_wakey # wake threads for immediate response
end
restart() click to toggle source
# File lib/opsicle/monitor/app.rb, line 84
def restart
  @restarting = true
end
start() click to toggle source
# File lib/opsicle/monitor/app.rb, line 41
def start
  begin
    @running = true

    if $stdout.tty?
      setup

      @threads[:command] ||= Thread.new do
        command_loop # listen for commands
      end

      @threads[:refresh_screen] ||= Thread.new do
        refresh_screen_loop # refresh frequently
      end

      @threads[:refresh_data] ||= Thread.new do
        refresh_data_loop # refresh not so frequently
      end
    end

    if @deploy
      @threads[:check_status] ||= Thread.new do
        refresh_deploy_status_loop # refresh not so frequently
      end
    end

    @threads.each { |tname, t| t.join }
  ensure
    cleanup
  end
end
stop(options={}) click to toggle source
# File lib/opsicle/monitor/app.rb, line 73
def stop(options={})
  options = { error: nil, message: "" }.merge(options)

  @running = false
  wakey_wakey
  @screen.close unless @screen.nil?
  @screen = nil # Ruby curses lib doesn't have closed?(), so we set to nil, just in case

  options[:error] ? raise(options[:error]) : raise(QuitMonitor, options[:message])
end

Private Instance Methods

check_deploy_status() click to toggle source
# File lib/opsicle/monitor/app.rb, line 178
def check_deploy_status
  if deploy.running?
    Output.say(". ") unless $stdout.tty?
  else
    if deploy.failed?
      stop(error: Opsicle::Errors::DeployFailed.new(deploy.command))
    elsif deploy.successful?
      stop(message: "Deploy completed successfully")
    else
      stop
    end
  end
end
cleanup() click to toggle source
# File lib/opsicle/monitor/app.rb, line 111
def cleanup
  @screen.close if @screen
end
command_loop() click to toggle source
# File lib/opsicle/monitor/app.rb, line 119
def command_loop
  while @running do
    next unless @screen # #refresh_loop might be reattaching screen

    key = @screen.next_key

    next unless key # keep listening if timeout

    do_command(key)
  end
end
open_opsworks_browser() click to toggle source
# File lib/opsicle/monitor/app.rb, line 192
def open_opsworks_browser
  %x(open 'https://console.aws.amazon.com/opsworks/home?#/stack/#{App.client.config.opsworks_config[:stack_id]}')
end
refresh_data_loop() click to toggle source

This loop is specifically separate from the screen loop because we don't want to spam OpWorks with API calls every second.

# File lib/opsicle/monitor/app.rb, line 155
def refresh_data_loop
  while @running do
    next unless @screen # HACK: only certain test scenarios?

    @screen.refresh_spies

    sleep API_POLLING_INTERVAL
  end
end
refresh_deploy_status_loop() click to toggle source

This is an optional loop that is meant for keeping track of a deploy and exiting on completion. It uses it's own API call since digging down to the spies would get ugly.

# File lib/opsicle/monitor/app.rb, line 168
def refresh_deploy_status_loop
  while @running do
    next unless @screen || !$stdout.tty?# HACK: only certain test scenarios?

    check_deploy_status

    sleep API_POLLING_INTERVAL
  end
end
refresh_screen_loop() click to toggle source
# File lib/opsicle/monitor/app.rb, line 131
def refresh_screen_loop
  while @running do
    next unless @screen # HACK: only certain test scenarios?

    if @restarting || @screen.missized? # signal(s) or whilst still resizing
      panel_main = @screen.panel_main

      cleanup

      setup

      @screen.panel_main = panel_main

      @restarting = false
    end

    @screen.refresh

    sleep SCREEN_REFRESH_INTERVAL # go to sleep; could be rudely awoken on quit
  end
end
set_screen(screen) click to toggle source
# File lib/opsicle/monitor/app.rb, line 103
def set_screen(screen)
  @screen.panel_main = screen
end
setup() click to toggle source
# File lib/opsicle/monitor/app.rb, line 107
def setup
  @screen = Monitor::Screen.new
end
wakey_wakey() click to toggle source
# File lib/opsicle/monitor/app.rb, line 115
def wakey_wakey
  @threads.each { |tname, t| t.run if t.status == 'sleep' }
end