class Kontena::Command

Attributes

arguments[RW]
exit_code[R]
result[R]

Public Class Methods

banner(msg, extra_feed = true) click to toggle source

Overwrite Clamp's banner command. Calling banner multiple times will now add lines to the banner message instead of overwriting the whole message. This is useful if callbacks add banner messages.

@param [String] message

callback_matcher(cmd_class = nil, cmd_type = nil) click to toggle source
# File lib/kontena/command.rb, line 82
def self.callback_matcher(cmd_class = nil, cmd_type = nil)
  unless cmd_class
    if @command_class.nil?
      return nil
    else
      return [@command_class, @command_type]
    end
  end
  @command_class = cmd_class.to_sym
  @command_type = cmd_type.to_sym
  [@command_class, @command_type]
end
inherited(where) click to toggle source
# File lib/kontena/command.rb, line 78
def self.inherited(where)
  where.extend Finalizer
end
load_subcommand(path) click to toggle source
# File lib/kontena/command.rb, line 74
def self.load_subcommand(path)
  Kontena::Cli::SubcommandLoader.new(path)
end
requires_current_account_token() click to toggle source
# File lib/kontena/command.rb, line 124
def self.requires_current_account_token
  unless Kontena::Cli::Config.current_account && Kontena::Cli::Config.current_account.token && Kontena::Cli::Config.current_account.token.access_token
    banner "#{Kontena.pastel.green("Requires account authentication")}: This command requires that you have authenticated to Kontena Cloud using 'kontena cloud auth'"
  end
  @requires_current_account_token = true
end
requires_current_account_token?() click to toggle source
# File lib/kontena/command.rb, line 148
def self.requires_current_account_token?
  @requires_current_account_token ||= false
end
requires_current_grid() click to toggle source
# File lib/kontena/command.rb, line 117
def self.requires_current_grid
  unless Kontena::Cli::Config.current_grid
    banner "#{Kontena.pastel.green("Requires current grid")}: This command requires that you have selected a grid as the current grid using 'kontena grid use' or by setting KONTENA_GRID environment variable."
  end
  @requires_current_grid = true
end
requires_current_grid?() click to toggle source
# File lib/kontena/command.rb, line 140
def self.requires_current_grid?
  @requires_current_grid ||= false
end
requires_current_master() click to toggle source
# File lib/kontena/command.rb, line 110
def self.requires_current_master
  unless Kontena::Cli::Config.current_master
    banner "#{Kontena.pastel.green("Requires current master")}: This command requires that you have selected a current master using 'kontena master login' or 'kontena master use'. You can also use the environment variable KONTENA_URL to specify the master address or KONTENA_MASTER=master_name to override the current_master setting."
  end
  @requires_current_master = true
end
requires_current_master?() click to toggle source
# File lib/kontena/command.rb, line 132
def self.requires_current_master?
  @requires_current_master ||= false
end
requires_current_master_token() click to toggle source
# File lib/kontena/command.rb, line 157
def self.requires_current_master_token
  @requires_current_master_token = true
end
requires_current_master_token?() click to toggle source
# File lib/kontena/command.rb, line 161
def self.requires_current_master_token?
  @requires_current_master_token ||= false
end

Public Instance Methods

help_requested?() click to toggle source
# File lib/kontena/command.rb, line 183
def help_requested?
  return true if @arguments.include?('--help')
  return true if @arguments.include?('-h')
  false
end
instance(arguments) click to toggle source

Returns an instance of the command, just like with Kontena.run! but before calling “execute” You can use it for specs or reuse of instancemethods. Example:

cmd = Kontena::FooCommand.instance(['-n', 'foo'])
cmd.fetch_stuff
# File lib/kontena/command.rb, line 194
def instance(arguments)
  @arguments = arguments
  parse @arguments
  self
end
run(arguments) click to toggle source
# File lib/kontena/command.rb, line 200
def run(arguments)
  Kontena.logger.debug { "Running #{self.class.name} with #{arguments.inspect} -- callback matcher = '#{self.class.callback_matcher.nil? ? "nil" : self.class.callback_matcher.map(&:to_s).join(' ')}'" }
  @arguments = arguments

  run_callbacks :before_parse unless help_requested?

  parse @arguments

  unless help_requested?
    verify_current_master
    verify_current_master_token
    verify_current_grid
    run_callbacks :before
  end

  begin
    @result = execute
    @exit_code = @result.kind_of?(FalseClass) ? 1 : 0
  rescue SystemExit => exc
    @result = exc.status == 0
    @exit_code = exc.status
  end
  run_callbacks :after unless help_requested?
  exit(@exit_code) if @exit_code.to_i > 0
  @result
rescue Excon::Error::Socket => ex
  if ex.message.include?('Unable to verify certificate')
    $stderr.puts " [#{Kontena.pastel.red('error')}] The server uses a certificate signed by an unknown authority."
    $stderr.puts "         You can trust this server by copying server CA pem file to: #{Kontena.pastel.yellow("~/.kontena/certs/<hostname>.pem")}"
    $stderr.puts "         If kontena cannot find your system ca bundle, you can set #{Kontena.pastel.yellow('SSL_CERT_DIR=/etc/ssl/certs')} env variable to load them from another location."
    $stderr.puts "         Protip: you can bypass the certificate check by setting #{Kontena.pastel.yellow('SSL_IGNORE_ERRORS=true')} env variable, but any data you send to the server could be intercepted by others."
    abort
  else
    abort(ex.message)
  end
rescue Kontena::Errors::StandardError => ex
  raise ex if Kontena.debug?
  Kontena.logger.error(ex)
  abort(" [#{Kontena.pastel.red('error')}] #{ex.status} : #{ex.message}")
rescue Errno::EPIPE
  # If user is piping the command outputs to some other command that might exit before CLI has outputted everything
  abort
rescue Clamp::HelpWanted, Clamp::UsageError
  raise
rescue => ex
  raise ex if Kontena.debug?
  Kontena.logger.error(ex)
  abort(" [#{Kontena.pastel.red('error')}] #{ex.class.name} : #{ex.message}\n         See #{Kontena.log_target} or run the command again with environment DEBUG=true set to see the full exception")
end
run_callbacks(state) click to toggle source
# File lib/kontena/command.rb, line 95
def run_callbacks(state)
  if self.class.respond_to?(:callback_matcher) && !self.class.callback_matcher.nil? && !self.class.callback_matcher.compact.empty?
    Kontena::Callback.run_callbacks(self.class.callback_matcher, state, self)
  end
end
verify_current_account_token() click to toggle source
# File lib/kontena/command.rb, line 152
def verify_current_account_token
  retried ||= false
  Kontena::Cli::Config.instance.require_current_account_token if self.class.requires_current_account_token?
end
verify_current_grid() click to toggle source
# File lib/kontena/command.rb, line 144
def verify_current_grid
  Kontena::Cli::Config.instance.require_current_grid if self.class.requires_current_grid?
end
verify_current_master() click to toggle source
# File lib/kontena/command.rb, line 136
def verify_current_master
  Kontena::Cli::Config.instance.require_current_master if self.class.requires_current_master?
end
verify_current_master_token() click to toggle source
# File lib/kontena/command.rb, line 165
def verify_current_master_token
  return nil unless self.class.requires_current_master_token?
  retried ||= false
  Kontena::Cli::Config.instance.require_current_master_token
rescue Kontena::Cli::Config::TokenExpiredError
  server = Kontena::Cli::Config.instance.current_master
  success = Kontena::Client.new(server.url, server.token,
    ssl_cert_path: server.ssl_cert_path,
    ssl_subject_cn: server.ssl_subject_cn,
  ).refresh_token
  if success && !retried
    retried = true
    retry
  else
    raise Kontena::Cli::Config::TokenExpiredError, "The access token has expired and refresh failed. Try authenticating again, use: kontena master login"
  end
end