class MiGA::Cli::Action::Run

Public Instance Methods

parse_cli() click to toggle source
# File lib/miga/cli/action/run.rb, line 7
def parse_cli
  cli.defaults = { try_load: false, thr: 1, env: false, check_first: false }
  cli.parse do |opt|
    cli.opt_object(opt, [:project, :dataset_opt, :result_opt])
    opt.on(
      '-t', '--threads INT', Integer,
      "Threads to use in the local run (by default: #{cli[:thr]})"
    ) { |v| cli[:thr] = v }
    opt.on(
      '-R', '--remote STR',
      'Description of remote SSH node to launch the job, as "user@hostname"',
      'By default, the job is executed locally'
    ) { |v| cli[:remote] = v }
    opt.on(
      '-l', '--log PATH',
      'Path to the output log file to be created. If not set, STDOUT'
    ) { |v| cli[:log] = v }
    opt.on(
      '-e', '--environment',
      'Load PROJECT, DATASET, and CORES from the environment'
    ) { |v| cli[:env] = v }
    opt.on(
      '--check-first',
      'Check if the result exists, and run only if it does not'
    ) { |v| cli[:check_first] = v }
  end
end
perform() click to toggle source
# File lib/miga/cli/action/run.rb, line 35
def perform
  # Load environment variables if requested (typically by the daemon)
  if cli[:env]
    cli[:project] ||= ENV['PROJECT']
    cli[:dataset] ||= ENV['DATASET']
    cli[:thr] = ENV['CORES'].to_i unless ENV['CORES'].nil?
    cli[:result] = File.basename(cli[:result].to_s, '.bash').to_sym
  end
  %[project dataset result].each do |i|
    cli[i] = nil if cli[i].nil? || cli[i].empty?
  end

  # Unset dataset if the requested result is for projects
  if (MiGA::Project.RESULT_DIRS.keys + [:p]).include? cli[:result]
    cli[:dataset] = nil
  end

  # Use virtual result if not explicitly passed
  cli[:result] ||= cli[:dataset] ? :d : :p

  # Load project
  p = cli.load_project

  # Check if result already exists
  if cli[:check_first]
    obj = cli[:dataset] ? p.dataset(cli[:dataset]) : p
    if obj.result(cli[:result])
      cli.say('Result already exists')
      return
    end
  end

  # Prepare command
  miga = MiGA.root_path
  opts = {}
  cmd = [
    "PROJECT=#{p.path.shellescape}",
    "RUNTYPE=#{cli[:remote] ? 'ssh' : 'bash'}",
    "MIGA=#{miga.shellescape}",
    "CORES=#{cli[:thr]}"
  ]
  obj = cli.load_project_or_dataset
  klass = obj.class
  virtual_task = %[p d maintenance].include?(cli[:result])
  cmd << "DATASET=#{obj.name.shellescape}" if obj.is_a? MiGA::Dataset
  if klass.RESULT_DIRS[cli[:result]].nil? and not virtual_task
    raise "Unsupported #{klass.to_s.sub(/.*::/, '')} result: #{cli[:result]}."
  end

  cmd << MiGA.script_path(cli[:result], miga: miga, project: p).shellescape
  if cli[:remote]
    cmd = [
      'ssh', '-t', '-t', '-o', 'StrictHostKeyChecking off'.shellescape,
      cli[:remote].shellescape,
      cmd.join(' ').shellescape
    ]
  end

  if cli[:log]
    opts[:stdout] = cli[:log]
    opts[:err2out] = true
  end

  # Launch
  # note that all elements were carefully escaped in advace, so this has to be
  # passed as String to avoid double-escaping or unintentionally escaping
  # characters such as `=` and `>`
  MiGA::MiGA.run_cmd(cmd.join(' '), opts)
end