class Locd::CLI::Command::Agent

CLI interface using the `thor` gem.

@see whatisthor.com/

Definitions

Definitions

Definitions

Definitions

Definitions

Definitions

CLI interface using the `thor` gem.

@see whatisthor.com/

Definitions

Definitions

Definitions

Definitions

Definitions

Definitions

Public Class Methods

agent_class() click to toggle source

Helpers

# File lib/locd/cli/command/agent.rb, line 40
def self.agent_class
  Locd::Agent
end
agent_type() click to toggle source
# File lib/locd/cli/command/agent.rb, line 44
def self.agent_type
  agent_class.name.split( '::' ).last.downcase
end

Public Instance Methods

add(*cmd_template, **kwds) click to toggle source
# File lib/locd/cli/command/agent/add.rb, line 44
def add *cmd_template, **kwds
  logger.trace __method__.to_s,
    cmd_template: cmd_template,
    kwds: kwds,
    options: options
  
  # Merge all the keywords together into the format needed to call
  # {Locd::Agent.add}
  kwds.merge! **option_kwds( :force, groups: [ :write ] ),
              cmd_template: cmd_template
  
  # Check args
  
  # `:cmd_template` can not be empty at this point
  if kwds[:cmd_template].empty? || kwds[:cmd_template].all?( &:empty? )
    raise Thor::RequiredArgumentMissingError,
      "CMD_TEMPLATE argument is required to add an agent"
  end
  
  # Need a `:label` too
  unless t.non_empty_str === kwds[:label]
    raise Thor::RequiredArgumentMissingError,
      "--label=LABEL option is required to add an agent"
  end
  
  # Do the add
  agent = agent_class.add **kwds
  
  # Reload (unless we were told not to... usually you want to reload)
  agent.reload if options[:load]
  
  respond agent
end
ls() click to toggle source
# File lib/locd/cli/command/agent/ls.rb, line 38
def ls
  results = if pattern.nil?
    agent_class.all
  else
    agent_class.list pattern, **option_kwds( groups: :pattern )
  end
  
  respond results.values.sort
end
open() click to toggle source
# File lib/locd/cli/command/agent/open.rb, line 31
def open
  Locd::Agent::Proxy.get!.ensure_running
  
  find_multi!( pattern ).each do |agent|
    if options[:start]
      agent.ensure_running( **option_kwds( groups: :start ) )
    end
    
    Cmds! "open %s", agent.url
    
    logger.info "Opened agent `#{ agent.label }` at #{ agent.url }"
  end
end
plist() click to toggle source
# File lib/locd/cli/command/agent/plist.rb, line 26
def plist
  agent = find_only! pattern
  
  if options[:json] || options[:yaml]
    respond agent.plist
  else
    respond agent.path.read
  end
end
restart() click to toggle source
# File lib/locd/cli/command/agent/restart.rb, line 28
def restart
  find_multi!( pattern ).
    each { |agent|
      agent.restart **option_kwds( groups: [ :restart, :stop, :start ] )
    }
end
rm() click to toggle source
# File lib/locd/cli/command/agent/rm.rb, line 33
def rm
  kwds = option_kwds :logs
  find_multi!( pattern ).each { |agent| agent.remove **kwds }
end
start() click to toggle source
# File lib/locd/cli/command/agent/start.rb, line 25
def start
  find_multi!( pattern ).
    each { |agent| agent.start **option_kwds( groups: :start ) }
end
status() click to toggle source
# File lib/locd/cli/command/agent/status.rb, line 26
def status
  agent = find_only! pattern
  respond \
    label:  agent.label,
    status: agent.status.to_h( compact: false )
end
stop() click to toggle source
# File lib/locd/cli/command/agent/stop.rb, line 26
def stop
  kwds = option_kwds groups: :stop
  find_multi!( pattern ).each { |agent| agent.stop **kwds }
end
tail(*tail_options) click to toggle source
# File lib/locd/cli/command/agent/tail.rb, line 37
  def tail          *tail_options
    agent = find_only! pattern
    
    path = case options[:stream]
    when nil
      paths = agent.log_paths
      
      unless paths.length == 1
        raise Thor::RequiredArgumentMissingError.new binding.erb <<~END
          Agent `<%= agent.label %>` has multiple log files.
          
          out: <%= agent.out_path.to_s %>
          err: <%= agent.err_path.to_s %>
          
          Must specify one via the `--stream` option.
          
        END
      end
      
      paths[0]
      
    when 'out'
      agent.out_path
      
    when 'err'
      agent.err_path
      
    else
      raise "WTF"
    end
    
    cmd = ['tail']
    cmd += ['-F'] if options[:follow]
    
    exec *cmd, *tail_options, path.to_s
  end
truncate_logs() click to toggle source
# File lib/locd/cli/command/agent/truncate_logs.rb, line 31
def truncate_logs
  find_multi!( pattern ).each do |agent|
    log_paths = [agent.out_path, agent.err_path].compact.uniq
    
    unless log_paths.empty?
      restart = options[:restart] && agent.running?
      
      agent.stop if restart
      
      log_paths.each do |log_path|
        begin
          log_path.open( 'w' ) { |f| f.truncate 0 }
        rescue Exception => error
          logger.error "Failed to truncate #{ log_path }", error
        else
          logger.info "Truncated",
            'file' => log_path.to_s,
            'agent.label' => agent.label
        end
      end # each log_path
      
      agent.start if restart
    end # unless log_paths.empty?
  end # each agent
end
update(*cmd_template) click to toggle source
# File lib/locd/cli/command/agent/update.rb, line 29
def update        *cmd_template
  agent = find_only! pattern
  
  new_agent = agent.update \
    cmd_template: cmd_template,
    **option_kwds( groups: :write )
  
  logger.info "Agent `#{ agent.label }` updated"
  
  respond agent
end

Protected Instance Methods

agent_class() click to toggle source
# File lib/locd/cli/command/agent.rb, line 52
def agent_class
  self.class.agent_class
end
agent_table(agents) click to toggle source
# File lib/locd/cli/command/agent.rb, line 62
def agent_table agents
  Locd::CLI::Table.build do |t|
    t.col "PID", &:pid
    t.col "LEC", desc: "Last Exit Code", &:last_exit_code
    t.col "Label", &:label
    t.col "File" do |agent| agent_file agent end
    
    t.rows agents
  end
end
agent_type() click to toggle source
# File lib/locd/cli/command/agent.rb, line 57
def agent_type
  self.class.agent_type
end
check_pattern!(pattern) click to toggle source

The {#pattern} argument is not required because system agent subclasses don't need or want one.

My current solution is to check {#pattern} before using it in {#find_only!} and {#find_multi!} and override those in system agent commands.

# File lib/locd/cli/command/agent.rb, line 81
def check_pattern! pattern
  if pattern.nil?
    raise Thor::RequiredArgumentMissingError,
      "No value provided for required arguments 'pattern'"
  end
end
find_multi!(pattern) click to toggle source
# File lib/locd/cli/command/agent.rb, line 106
def find_multi! pattern
  check_pattern! pattern
  # Behavior depend on the `:all` option...
  if options[:all]
    # `:all` is set, so we find all the agents for the pattern, raising
    # if we don't find any
    agent_class.find_all!(
      pattern,
      **option_kwds( groups: :pattern )
    ).values
  else
    # `:all` is not set, so we need to find exactly one or error
    [find_only!( pattern )]
  end
end
find_only!(pattern) click to toggle source

Find exactly one {Locd::Agent} for a `pattern`, using the any `:pattern` shared options provided, and raising if there are no matches or more than one.

@param pattern (see Locd::Agent.find_only!)

@return [Locd::Agent]

Matched agent.

@raise If more or less than one agent is matched.

# File lib/locd/cli/command/agent.rb, line 100
def find_only! pattern
  check_pattern! pattern
  agent_class.find_only! pattern, **option_kwds( groups: :pattern )
end