class ForemanMaintain::Reporter::CLIReporter

Attributes

last_line[R]
max_length[R]
select_option_counter[RW]

Public Class Methods

new(stdout = $stdout, stdin = $stdin, options = {}) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 75
def initialize(stdout = $stdout, stdin = $stdin, options = {})
  @stdout = stdout
  @stdin = stdin
  options.validate_options!(:assumeyes)
  @assumeyes = options.fetch(:assumeyes, false)
  @plaintext = options.fetch(:plaintext, false)
  @hl = HighLine.new(@stdin, @stdout)
  @max_length = 80
  @line_char = '-'
  @cell_char = '|'
  @spinner = Spinner.new(self)
  @spinner.start_spinner if @stdout.tty?
  @last_line = ''
  @select_option_counter = 0
end

Public Instance Methods

after_execution_finishes(execution) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 152
def after_execution_finishes(execution)
  puts_status(execution.status)
  puts(execution.output) unless execution.output.empty?
  puts(already_run_msg) if execution.status == :already_run
  hline
  new_line_if_needed
  logger.info("--- Execution step '#{execution.name}' finished ---")
end
after_scenario_finishes(scenario) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 161
def after_scenario_finishes(scenario)
  scenario_failure_message(scenario)
  puts "\n"
  logger.info("=== Scenario '#{scenario.description || scenario.class}' finished ===")
end
ask(message, options = {}) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 122
def ask(message, options = {})
  new_line_if_needed
  options.validate_options!(:password)
  # the answer is confirmed by ENTER which will emit a new line
  @new_line_next_time = false
  @last_line = ''
  # add space at the end as otherwise highline would add new line there :/
  message = "#{message} " unless /\s\Z/.match?(message)
  answer = @hl.ask(message) { |q| q.echo = false if options[:password] }
  answer&.to_s&.chomp
end
ask_decision(message, actions_msg: 'y(yes), n(no), q(quit)', ignore_assumeyes: false, run_strategy: :fail_fast) click to toggle source

rubocop:disable Metrics/LineLength

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 198
def ask_decision(message, actions_msg: 'y(yes), n(no), q(quit)', ignore_assumeyes: false, run_strategy: :fail_fast)
  actions_msg = 'y(yes), n(no)' if run_strategy == :fail_slow
  if !ignore_assumeyes && assumeyes?
    print("#{message} (assuming yes)\n")
    return :yes
  end
  until_valid_decision do
    filter_decision(ask("#{message}, [#{actions_msg}]"))
  end
ensure
  clear_line
end
ask_to_select(message, steps, run_strategy) click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 222
def ask_to_select(message, steps, run_strategy)
  if assumeyes?
    step = steps[@select_option_counter]
    @select_option_counter += 1
    puts("(assuming option #{@select_option_counter})")
    return step
  end

  until_valid_decision do
    actions = run_strategy == :fail_slow ? 'n(next)' : 'n(next), q(quit)'
    answer = ask("#{message}, [#{actions}]")
    if answer =~ /^\d+$/ && (answer.to_i - 1) < steps.size
      steps[answer.to_i - 1]
    else
      decision = filter_decision(answer)
      if decision == :yes
        steps.first
      else
        decision
      end
    end
  end
ensure
  clear_line
end
assumeyes?() click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 175
def assumeyes?
  @assumeyes
end
before_execution_starts(execution) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 97
def before_execution_starts(execution)
  label = execution.step.label.to_s.tr('_', '-')
  logger.info("--- Execution step '#{execution.name}' [#{label}] started ---")
  puts(execution_info(execution, ''))
end
before_scenario_starts(scenario) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 91
def before_scenario_starts(scenario)
  logger.info("=== Scenario '#{scenario.description || scenario.class}' started ===")
  puts "Running #{scenario.description || scenario.class}"
  hline('=')
end
clear_line() click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 167
def clear_line
  if plaintext?
    print "\n"
  else
    print "\r" + ' ' * @max_length + "\r"
  end
end
execution_info(execution, text) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 256
def execution_info(execution, text)
  prefix = "#{execution.name}:"
  "#{prefix} #{text}"
end
filter_decision(answer) click to toggle source

rubocop:enable Metrics/LineLength

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 212
def filter_decision(answer)
  decision = nil
  answer   = answer.downcase
  DECISION_MAPPER.each do |options, decision_label|
    decision = decision_label if options.include?(answer)
  end
  decision
end
hline(line_char = @line_char) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 288
def hline(line_char = @line_char)
  puts line_char * @max_length
end
multiple_steps_decision(steps, run_strategy) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 189
def multiple_steps_decision(steps, run_strategy)
  puts 'There are multiple steps to proceed:'
  steps.each_with_index do |step, index|
    puts "#{index + 1}) #{step.runtime_message}"
  end
  ask_to_select('Select step to continue', steps, run_strategy)
end
new_line_if_needed() click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 134
def new_line_if_needed
  if @new_line_next_time
    @stdout.print("\n")
    @stdout.flush
    @new_line_next_time = false
  end
end
print(string) click to toggle source
puts(string) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 110
def puts(string)
  # we don't print the new line right away, as we want to be able to put
  # the status label at the end of the last line, if possible.
  # Therefore, we just mark that we need to print the new line next time
  # we are printing something.
  new_line_if_needed
  @stdout.print(string)
  @stdout.flush
  @new_line_next_time = true
  record_last_line(string)
end
puts_status(status) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 261
def puts_status(status)
  label_offset = 10
  padding = @max_length - @last_line.to_s.size - label_offset
  if padding < 0
    new_line_if_needed
    padding = @max_length - label_offset
  end
  @stdout.print(' ' * padding + status_label(status))
  @new_line_next_time = true
end
record_last_line(string) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 292
def record_last_line(string)
  @last_line = string.lines.to_a.last
end
single_step_decision(step, run_strategy) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 179
def single_step_decision(step, run_strategy)
  answer = ask_decision("Continue with step [#{step.runtime_message}]?",
    run_strategy: run_strategy)
  if answer == :yes
    step
  else
    answer
  end
end
status_label(status) click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 272
def status_label(status)
  mapping = { :success => { :label => '[OK]', :color => :green },
              :fail => { :label => '[FAIL]', :color => :red },
              :abort => { :label => '[ABORTED]', :color => :red },
              :running => { :label => '[RUNNING]', :color => :blue },
              :skipped => { :label => '[SKIPPED]', :color => :yellow },
              :already_run => { :label => '[ALREADY RUN]', :color => :yellow },
              :warning => { :label => '[WARNING]', :color => :yellow } }
  properties = mapping[status]
  if @plaintext
    properties[:label]
  else
    @hl.color(properties[:label], properties[:color], :bold)
  end
end
until_valid_decision() { |until decision| ... } click to toggle source

loop over the block until it returns some non-false value

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 250
def until_valid_decision
  decision = nil
  decision = yield until decision
  decision
end
with_spinner(message) { |spinner| ... } click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 142
def with_spinner(message)
  new_line_if_needed
  @spinner.activate
  @spinner.update(message)
  yield @spinner
ensure
  @spinner.deactivate
  @new_line_next_time = true
end

Private Instance Methods

already_run_msg() click to toggle source
# File lib/foreman_maintain/reporter/cli_reporter.rb, line 373
def already_run_msg
  'The step was skipped as it was already run and it is marked' \
  ' as run_once. Use --force to enforce the execution.'
end
format_steps(steps, join_with = ', ', indent = 0) click to toggle source

rubocop:enable Metrics/MethodLength, Metrics/AbcSize

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 369
def format_steps(steps, join_with = ', ', indent = 0)
  steps.map { |s| "#{' ' * indent}[#{s.label_dashed}]" }.join(join_with)
end
scenario_failure_message(scenario) click to toggle source

rubocop:disable Metrics/MethodLength, Metrics/AbcSize

# File lib/foreman_maintain/reporter/cli_reporter.rb, line 299
      def scenario_failure_message(scenario)
        return if scenario.passed? && !scenario.warning?

        message = []
        message << <<-MESSAGE.strip_heredoc
          Scenario [#{scenario.description}] failed.
        MESSAGE
        recommend = []

        steps_with_abort = scenario.steps_with_abort(:whitelisted => false)
        unless steps_with_abort.empty?
          message << format(<<-MESSAGE.strip_heredoc, format_steps(steps_with_abort, "\n", 2))
          The processing was aborted by user during the following steps:

          %s
          MESSAGE
        end

        steps_with_error = scenario.steps_with_error(:whitelisted => false)
        steps_with_skipped = scenario.steps_with_skipped(:whitelisted => true)
        not_skippable_steps = scenario.steps_with_error.select do |step|
          step.metadata[:do_not_whitelist] == true
        end

        steps_to_whitelist = steps_with_error + steps_with_skipped - not_skippable_steps
        unless steps_with_error.empty?
          message << format(<<-MESSAGE.strip_heredoc, format_steps(steps_with_error, "\n", 2))
          The following steps ended up in failing state:

          %s
          MESSAGE
          whitelist_labels = steps_to_whitelist.map(&:label_dashed).join(',')
          unless whitelist_labels.empty?
            recommend << if scenario.detector.feature(:instance).downstream
                           format(<<-MESSAGE.strip_heredoc, whitelist_labels)
              Resolve the failed steps and rerun the command.

              If the situation persists and, you are unclear what to do next,
              contact Red Hat Technical Support.

              In case the failures are false positives, use
              --whitelist="%s"
                           MESSAGE
                         else
                           format(<<-MESSAGE.strip_heredoc, whitelist_labels)
              Resolve the failed steps and rerun the command.
              In case the failures are false positives, use
              --whitelist="%s"
                           MESSAGE
                         end
          end
        end

        steps_with_warning = scenario.steps_with_warning(:whitelisted => false)
        unless steps_with_warning.empty?
          message << format(<<-MESSAGE.strip_heredoc, format_steps(steps_with_warning, "\n", 2))
          The following steps ended up in warning state:

          %s
          MESSAGE

          recommend << <<-MESSAGE.strip_heredoc
          The steps in warning state itself might not mean there is an error,
          but it should be reviewed to ensure the behavior is expected
          MESSAGE
        end
        puts((message + recommend).join("\n"))
      end