Project

General

Profile

« Previous | Next » 

Revision 181810b0

Added by Ivan Necas almost 7 years ago

Add --whitelist option

Allows to mark some steps to be ignored in the results: allows to
continue even when some checks are failing.

View differences:

lib/foreman_maintain/cli.rb
module ForemanMaintain
module Cli
class MainCommand < Base
include Concerns::Logger
subcommand 'health', 'Health related commands', HealthCommand
subcommand 'upgrade', 'Upgrade related commands', UpgradeCommand
def run(*arguments)
logger.info("Running foreman-maintain command with arguments #{arguments.inspect}")
begin
super
exit_code = 0
rescue Error::UsageError => e
puts e.message
logger.error(e)
exit_code = 1
end
return exit_code
ensure
logger.info("foreman-maintain command finished with #{exit_code}")
end
end
end
end
lib/foreman_maintain/cli/base.rb
end
def run_scenario(scenarios)
ForemanMaintain::Runner.new(reporter, scenarios, :assumeyes => assumeyes?).run
ForemanMaintain::Runner.new(reporter, scenarios,
:assumeyes => assumeyes?,
:whitelist => whitelist || []).run
end
def available_checks
......
def self.interactive_option
option ['-y', '--assumeyes'], :flag,
'Automatically answer yes for all questions'
option ['-w', '--whitelist'], :whitelist,
'Comma-separated list of labels of steps to be ignored' do |whitelist|
raise ArgumentError, 'value not specified' if whitelist.nil? || whitelist.empty?
whitelist.split(',').map(&:strip)
end
end
end
end
lib/foreman_maintain/error.rb
ret
end
end
# Error caused by incorrect usage, usually connected to passed CLI options
class UsageError < StandardError
end
end
end
lib/foreman_maintain/executable.rb
class Executable
extend Forwardable
attr_reader :options
def_delegators :execution, :success?, :fail?, :warning?, :output, :assumeyes?
def_delegators :execution, :puts, :print, :with_spinner, :ask
def_delegators :execution,
:success?, :fail?, :warning?, :output,
:assumeyes?, :whitelisted?,
:execution, :puts, :print, :with_spinner, :ask
attr_accessor :associated_feature
lib/foreman_maintain/reporter/cli_reporter.rb
@last_line = ''
end
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def before_scenario_starts(scenario, last_scenario = nil)
decision = if last_scenario && last_scenario.steps_with_error.any?
:quit
elsif last_scenario && last_scenario.steps_with_warning.any?
ask_decision("Continue with [#{scenario.description}]")
else
:yes
end
decision = :yes
if last_scenario
decision = if last_scenario.steps_with_error(:whitelisted => false).any?
:quit
elsif last_scenario.steps_with_warning(:whitelisted => false).any?
ask_decision("Continue with [#{scenario.description}]")
else
:yes
end
end
if decision == :yes
puts "Running #{scenario.description || scenario.class}"
hline('=')
......
Scenario [#{scenario.description}] failed.
MESSAGE
recommend = []
unless scenario.steps_with_error.empty?
steps_with_error = scenario.steps_with_error(:whitelisted => false)
unless steps_with_error.empty?
message << <<-MESSAGE.strip_heredoc
The following steps ended up in failing state:
#{format_steps(scenario.steps_with_error, "\n", 2)}
#{format_steps(steps_with_error, "\n", 2)}
MESSAGE
recommend << <<-MESSAGE.strip_heredoc
Resolve the failed steps and rerun
the command. In case the failures are false positives,
use --whitelist="#{scenario.steps_with_error.map(&:label_dashed).join(',')}"
use --whitelist="#{steps_with_error.map(&:label_dashed).join(',')}"
MESSAGE
end
unless scenario.steps_with_warning.empty?
steps_with_warning = scenario.steps_with_warning(:whitelisted => false)
unless steps_with_warning.empty?
message << <<-MESSAGE.strip_heredoc
The following steps ended up in warning state:
#{format_steps(scenario.steps_with_warning, "\n", 2)}
#{format_steps(steps_with_warning, "\n", 2)}
MESSAGE
recommend << <<-MESSAGE.strip_heredoc
lib/foreman_maintain/runner.rb
class Runner
require 'foreman_maintain/runner/execution'
def initialize(reporter, scenarios, options = {})
options.validate_options!(:assumeyes)
options.validate_options!(:assumeyes, :whitelist)
@assumeyes = options.fetch(:assumeyes, false)
@whitelist = options.fetch(:whitelist, [])
@reporter = reporter
@scenarios = Array(scenarios)
@scenarios_with_dependencies = scenarios_with_dependencies
validate_whitelist!
@quit = false
end
......
while !@quit && !@steps_to_run.empty?
step = @steps_to_run.shift
@reporter.puts('Rerunning the check after fix procedure') if rerun_check?(step)
execution = Execution.new(step, @reporter)
execution = Execution.new(step, @reporter, :whitelisted => whitelisted_step?(step))
execution.run
ask_about_offered_steps(step)
end
@reporter.after_scenario_finishes(scenario)
end
def validate_whitelist!
valid_labels = @scenarios_with_dependencies.inject([]) do |step_labels, scenario|
step_labels.concat(scenario.steps.map(&:label_dashed))
end.map(&:to_s)
invalid_whitelist_labels = @whitelist - valid_labels
unless invalid_whitelist_labels.empty?
raise Error::UsageError, "Invalid whitelist value #{invalid_whitelist_labels.join(',')}"
end
end
def whitelisted_step?(step)
@whitelist.include?(step.label_dashed.to_s)
end
def confirm_scenario(scenario)
decision = @reporter.before_scenario_starts(scenario, @last_scenario)
case decision
lib/foreman_maintain/runner/execution.rb
attr_reader :reporter
def initialize(step, reporter)
def initialize(step, reporter, options = {})
options.validate_options!(:whitelisted)
@step = step
@reporter = reporter
@status = :pending
@output = ''
@whitelisted = options[:whitelisted]
end
def name
@step.description
end
def whitelisted?
@whitelisted
end
def success?
@status == :success
end
lib/foreman_maintain/scenario.rb
end.uniq
end
def steps_with_error
steps.find_all(&:fail?)
def steps_with_error(options = {})
filter_whitelisted(steps.find_all(&:fail?), options)
end
def steps_with_warning
steps.find_all(&:warning?)
def steps_with_warning(options = {})
filter_whitelisted(steps.find_all(&:warning?), options)
end
def filter_whitelisted(steps, options)
options.validate_options!(:whitelisted)
if options.key?(:whitelisted)
steps.select do |step|
options[:whitelisted] ? step.whitelisted? : !step.whitelisted?
end
else
steps
end
end
def passed?
(steps_with_error + steps_with_warning).empty?
(steps_with_error(:whitelisted => false) + steps_with_warning(:whitelisted => false)).empty?
end
def failed?
test/lib/reporter_test.rb
MESSAGE
end
it 'informs the user about warnings and failures of the last scenario ===' do
it 'informs the user about warnings and failures of the last scenario' do
run_scenario(warn_and_fail_scenario)
reporter.after_scenario_finishes(warn_and_fail_scenario)
assert_equal <<-MESSAGE.strip_heredoc.strip, captured_out(false).strip
......
MESSAGE
end
it 'ignores whitelisted warnings and failures of the last scenario' do
run_scenario(warn_and_fail_scenario, :whitelisted => true)
reporter.after_scenario_finishes(warn_and_fail_scenario)
assert_equal <<-MESSAGE.strip_heredoc.strip, captured_out(false).strip
check that ends up with warning: [WARNING]
this check is always causing warnings
--------------------------------------------------------------------------------
check that ends up with fail: [FAIL]
this check is always causing failure
--------------------------------------------------------------------------------
check that ends up with success: [OK]
--------------------------------------------------------------------------------
MESSAGE
end
describe 'assumeyes' do
let(:reporter) do
Reporter::CLIReporter.new(capture, fake_stdin, :assumeyes => true)
......
out
end
def run_scenario(scenario)
def run_scenario(scenario, options = {})
scenario.steps.each do |step|
ForemanMaintain::Runner::Execution.new(step, reporter).tap(&:run)
ForemanMaintain::Runner::Execution.new(step, reporter, options).tap(&:run)
end
end
end

Also available in: Unified diff