class Expectacle::ThrowerBase

Basic state setup/management

Basic state setup/management

Basic state setup/management

Attributes

base_dir[R]

@return [String] Base directory path to find params/hosts/commands file.

logger[RW]

@return [Logger] Logger instance.

Public Class Methods

new(timeout: 60, verbose: true, base_dir: Dir.pwd, logger: $stdout) click to toggle source

Constructor @param timeout [Integer] Seconds to timeout. (default: 60sec) @param verbose [Boolean] Flag to enable verbose output.

(default: `true`)

@param base_dir [String] Base directory to find files.

(default: `Dir.pwd`)

@param logger [IO,String,Symbol] IO Object (default `$stdout`),

File name, or :syslog to logging.

@return [Expectacle::ThrowerBase]

# File lib/expectacle/thrower_base.rb, line 23
def initialize(timeout: 60, verbose: true,
               base_dir: Dir.pwd, logger: $stdout)
  # default
  @host_param = {}
  # remote connection timeout (sec)
  @timeout = timeout
  # cli mode flag
  @enable_mode = false
  # debug (use debug print to stdout)
  $expect_verbose = verbose
  # base dir
  @base_dir = File.expand_path(base_dir)
  # logger
  setup_default_logger(logger)
end

Public Instance Methods

commands_dir() click to toggle source

Path to command list file directory. @return [String]

# File lib/expectacle/thrower_base.rb, line 53
def commands_dir
  File.join @base_dir, 'commands'
end
hosts_dir() click to toggle source

Path to host list file directory. @return [String]

# File lib/expectacle/thrower_base.rb, line 47
def hosts_dir
  File.join @base_dir, 'hosts'
end
opts_dir() click to toggle source

Path to span command options file directory. @return [String]

# File lib/expectacle/thrower_base.rb, line 59
def opts_dir
  File.join @base_dir, 'opts'
end
prompts_dir() click to toggle source

Path to prompt file directory. @return [String]

# File lib/expectacle/thrower_base.rb, line 41
def prompts_dir
  File.join @base_dir, 'prompts'
end

Private Instance Methods

check_embed_envvar(command) click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 46
def check_embed_envvar(command)
  return unless command =~ /<%=\s*ENV\[[\'\"]?(.+)[\'\"]\]?\s*%>/
  envvar_name = Regexp.last_match(1)
  if !ENV.key?(envvar_name)
    @logger.error "Variable name: #{envvar_name} is not found in ENV"
  elsif ENV[envvar_name] =~ /^\s*$/
    @logger.warn "Env var: #{envvar_name} exists, but null string"
  end
end
cu_command() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 15
def cu_command
  @local_serial = true
  opts = load_spawn_command_opts_file
  ['cu', @host_param[:cu_opts], opts].join(' ')
end
default_io_logger(logger_io, progname) click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 26
def default_io_logger(logger_io, progname)
  logger = Logger.new(logger_io)
  logger.progname = progname
  logger.datetime_format = '%Y-%m-%d %H:%M:%D %Z'
  logger
end
do_on_interactive_process() { |match| ... } click to toggle source
# File lib/expectacle/thrower_base.rb, line 76
def do_on_interactive_process
  until @reader.closed? || @reader.eof?
    @reader.expect(expect_regexp, @timeout) do |match|
      yield match
    end
  end
rescue Errno::EIO => error
  # on linux, PTY raises Errno::EIO when spawned process closed.
  @logger.debug "PTY raises Errno::EIO, #{error.message}"
end
embed_command(command) click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 68
def embed_command(command)
  embed_var(command)
end
embed_ipaddr() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 76
def embed_ipaddr
  embed_var(@host_param[:ipaddr])
end
embed_password() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 62
def embed_password
  @host_param[:enable] = '_NOT_DEFINED_' unless @host_param.key?(:enable)
  base_str = @enable_mode ? @host_param[:enable] : @host_param[:password]
  embed_var(base_str)
end
embed_user_name() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 72
def embed_user_name
  embed_var(@host_param[:username])
end
embed_var(param) click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 56
def embed_var(param)
  check_embed_envvar(param)
  erb = ERB.new(param)
  erb.result(binding)
end
expect_regexp() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 21
def expect_regexp
  /
    ( #{@prompt[:password]} | #{@prompt[:enable_password]}
    | #{@prompt[:username]}
    | #{@prompt[:command1]} | #{@prompt[:command2]}
    | #{@prompt[:sub1]} | #{@prompt[:sub2]}
    | #{@prompt[:yn]}
    )\s*$
  /x
end
load_prompt_file() click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 53
def load_prompt_file
  prompt_file = "#{prompts_dir}/#{@host_param[:type]}_prompt.yml"
  @prompt = load_yaml_file('prompt file', prompt_file)
end
load_spawn_command_opts_file() click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 58
def load_spawn_command_opts_file
  opts_file = "#{opts_dir}/#{@host_param[:protocol]}_opts.yml"
  if File.exist?(opts_file)
    load_yaml_file("#{@host_param[:protocol]} opts file", opts_file)
  else
    @logger.warn "Opts file #{opts_file} not found."
    []
  end
end
load_yaml_file(file_type, file_name) click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 46
def load_yaml_file(file_type, file_name)
  YAML.load_file file_name
rescue StandardError => error
  @logger.error "Cannot load #{file_type}: #{file_name}"
  raise error
end
make_spawn_command() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 32
def make_spawn_command
  case @host_param[:protocol]
  when /^telnet$/i
    ['telnet', embed_ipaddr].join(' ')
  when /^ssh$/i
    ssh_command
  when /^cu$/i
    cu_command
  else
    @logger.error "Unknown protocol #{@host_param[:protocol]}"
    nil
  end
end
open_interactive_process(spawn_cmd) { || ... } click to toggle source
# File lib/expectacle/thrower_base.rb, line 87
def open_interactive_process(spawn_cmd)
  @logger.info "Begin spawn: #{spawn_cmd}"
  PTY.spawn(spawn_cmd) do |reader, writer, _pid|
    @enable_mode = false
    @reader = reader
    @writer = writer
    @writer.sync = true
    yield
  end
end
ready_to_open_host_session() { |spawn_cmd| ... } click to toggle source
# File lib/expectacle/thrower_base.rb, line 65
def ready_to_open_host_session
  @local_serial = false # default for host
  load_prompt_file # prompt regexp of device
  spawn_cmd = make_spawn_command
  if @prompt && spawn_cmd
    yield spawn_cmd
  else
    @logger.error 'Invalid parameter in param file(S)'
  end
end
setup_default_logger(logger) click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 33
def setup_default_logger(logger)
  progname = 'Expectacle'
  @logger = if logger == :syslog
              Syslog::Logger.new(progname)
            else
              default_io_logger(logger, progname)
            end
  @logger.level = Logger::INFO
  @logger.formatter = proc do |severity, datetime, pname, msg|
    "#{datetime} #{pname} [#{severity}] #{msg}\n"
  end
end
ssh_command() click to toggle source
# File lib/expectacle/thrower_base_params.rb, line 10
def ssh_command
  opts = load_spawn_command_opts_file
  ['ssh', opts, "-l #{embed_user_name}", embed_ipaddr].join(' ')
end
write_and_logging(message, command, secret = false) click to toggle source
# File lib/expectacle/thrower_base_io.rb, line 15
def write_and_logging(message, command, secret = false)
  logging_message = secret ? message : message + command
  @logger.info logging_message
  if @writer.closed?
    @logger.error "Try to write #{command}, but writer closed"
    @commands.clear
  else
    @writer.puts command
  end
end