class Kontena::Plugin::Shell::Session

Attributes

context[R]

Public Class Methods

new(context) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 13
def initialize(context)
  @context = Context.new(context)
  read_history
end

Public Instance Methods

caret() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 167
def caret
  pastel.white('>')
end
config() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 146
def config
  Kontena::Cli::Config
end
config_file_modified_since?(time) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 79
def config_file_modified_since?(time)
  return false unless config.config_file_available?
  return true if File.mtime(config.config_filename) >= time
end
execute_with_fork(command) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 57
def execute_with_fork(command)
  start = Time.now
  pid = fork do
    Process.setproctitle("kosh-runner")
    command.run
  end
  trap('INT') {
    begin
      Process.kill('TERM', pid)
    rescue Errno::ESRCH
      raise SignalException, 'SIGINT'
    end
  }
  Process.waitpid(pid)
  if config_file_modified_since?(start)
    puts ""
    puts pastel.yellow("Config file has been modified, reloading configuration")
    puts ""
    config.reset_instance
  end
end
execute_with_thread(command) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 48
def execute_with_thread(command)
  old_trap = trap('INT', Proc.new { Thread.main[:command_thread] && Thread.main[:command_thread].kill })
  Thread.main[:command_thread] = Thread.new do
    command.run
  end
  Thread.main[:command_thread].join
  trap('INT', old_trap)
end
fork_supported?() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 44
def fork_supported?
  Process.respond_to?(:fork)
end
forkable_command?(command) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 37
def forkable_command?(command)
  return false if !command.is_a?(Kontena::Plugin::Shell::KontenaCommand)
  return false if command.subcommand_class.has_subcommands?

  true
end
grid_name() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 175
def grid_name
  config.current_grid
end
history_file() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 18
def history_file
  ENV['KOSH_HISTORY'] || File.join(Dir.home, '.kosh_history')
end
master_name() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 171
def master_name
  config.current_master.name if config.current_master
end
pastel() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 142
def pastel
  Kontena.pastel
end
prompt() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 150
def prompt
  if master_name && master_name.include?('/'.freeze)
    org, name = master_name.split('/')
    "#{pastel.bright_cyan(org)} / #{pastel.cyan(name)} #{pastel.yellow(context)} #{caret} "
  elsif master_name && grid_name
    "#{pastel.bright_cyan(master_name)} / #{pastel.cyan(grid_name)} #{pastel.yellow(context)} #{caret} "
  elsif master_name
    "#{pastel.bright_cyan(master_name)} / #{pastel.red('<no grid>')} #{pastel.yellow(context)} #{caret} "
  else
    if org = ENV['KONTENA_ORGANIZATION']
      "#{pastel.bright_cyan(org)} #{pastel.yellow(context)} #{caret} "
    else
      "#{pastel.yellow(context)} #{caret} "
    end
  end
end
read_history() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 22
def read_history
  File.readlines(history_file).each { |line| Readline::HISTORY.push(line.chomp) } if File.exist?(history_file)
end
run() click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 84
def run
  puts File.read(__FILE__)[/__END__$(.*)/m, 1]
  puts "Kontena Shell v#{Kontena::Plugin::Shell::VERSION} (c) 2017 Kontena"
  puts pastel.green("Enter 'help' to see a list of commands or 'help <command>' to get help on a specific command.")

  stty_save = `stty -g`.chomp rescue nil
  at_exit do
    File.write(history_file, Readline::HISTORY.to_a.uniq.last(100).join("\n"))
    system('stty', stty_save) if stty_save
  end

  # Hook stack command kontena.yml content prompting
  if Gem::Version.new(Kontena::Cli::VERSION) >= Gem::Version.new('1.4.0')
    require 'kontena/plugin/shell/prompt_loader'
  else
    require 'kontena/cli/stacks/validate_command'
    require 'kontena/cli/stacks/install_command'
    require 'kontena/cli/stacks/upgrade_command'
    require 'kontena/plugin/shell/stacks_common_ext'
    Kontena::Cli::Stacks::ValidateCommand.send(:include, Kontena::Plugin::Shell::StacksCommonExt)
    Kontena::Cli::Stacks::InstallCommand.send(:include, Kontena::Plugin::Shell::StacksCommonExt)
    Kontena::Cli::Stacks::UpgradeCommand.send(:include, Kontena::Plugin::Shell::StacksCommonExt)
  end

  Readline.completion_proc = Proc.new do |word|
    line = Readline.line_buffer
    tokens = line.shellsplit
    tokens.pop unless word.empty?

    if context.empty? && tokens.empty?
      completions = Kontena::MainCommand.recognised_subcommands.flat_map(&:names) + Shell.commands.keys
    else
      command = Shell.command(context.first || tokens.first || 'kontena')
      if command
        if command.completions.first.respond_to?(:call)
          completions = command.completions.first.call(context, tokens, word)
        else
          completions = Array(command.completions)
        end
      else
        completions = []
      end
    end

    word.empty? ? completions : completions.select { |c| c.start_with?(word) }
  end

  while buf = Readline.readline(prompt, true)
    if buf.strip.empty?
      Readline::HISTORY.pop
    else
      run_command(buf)
    end
  end
  puts
  puts pastel.green("Bye!")
end
run_command(buf) click to toggle source
# File lib/kontena/plugin/shell/session.rb, line 26
def run_command(buf)
  tokens = buf.split(/\s(?=(?:[^"]|"[^"]*")*$)/).map(&:strip)
  runner = Shell.command(tokens.first) || Shell.command(context.first) || Kontena::Plugin::Shell::KontenaCommand
  command = runner.new(context, tokens, self)
  if fork_supported? && forkable_command?(command)
    execute_with_fork(command)
  else
    execute_with_thread(command)
  end
end