Project

General

Profile

Download (3.79 KB) Statistics
| Branch: | Tag: | Revision:
module ForemanMaintain
class Executable
extend Forwardable
attr_reader :options
def_delegators :execution,
:success?, :fail?, :warning?, :output,
:assumeyes?, :whitelisted?,
:execution, :puts, :print, :with_spinner, :ask

attr_accessor :associated_feature

def initialize(options = {})
@options = options.inject({}) { |h, (k, v)| h.update(k.to_s => v) }
@param_values = {}
setup_params
after_initialize
end

# To be able to call uniq on a set of steps to deduplicate the same steps
# inside the scenario
def eql?(other)
self.class.eql?(other.class) && options.eql?(other.options)
end

def hash
[self.class, options].hash
end

# public method to be overriden to perform after-initialization steps
def after_initialize; end

# processes the params from provided options
def setup_params
@options.validate_options!(params.values.map(&:name).map(&:to_s))
params.values.each do |param|
set_param_variable(param.name, param.process(@options[param.name.to_s]))
end
end

def set_param_variable(param_name, value)
@param_values[param_name] = value
if instance_variable_defined?("@#{param_name}")
raise "Instance variable @#{param_name} already set"
end
instance_variable_set("@#{param_name}", value)
end

def associated_feature
return @associated_feature if defined? @associated_feature
if metadata[:for_feature]
@associated_feature = feature(metadata[:for_feature])
end
end

# next steps to be offered to the user after the step is run
# It can be added for example from the assert method
def next_steps
@next_steps ||= []
end

# make the step to fail: the failure is considered significant and
# the next steps should not continue. The specific behaviour depends
# on the scenario it's being used on. In check-sets scenario, the next
# steps of the same scenario might continue, while the following scenarios
# would be aborted.
def fail!(message)
raise Error::Fail, message
end

# make the step a warning: this doesn't indicate the whole scenario should
# not continue, but the user will be warning about proceeding
def warn!(message)
raise Error::Warn, message
end

# rubocop:disable Style/AccessorMethodName
def set_fail(message)
execution.status = :fail
execution.output << message
end

def set_warn(message)
execution.status = :warning
execution.output << message
end

# public method to be overriden
def run
raise NotImplementedError
end

def execution
if @_execution
@_execution
else
raise 'Trying to get execution information before the run started happened'
end
end

# public method to be overriden: it can perform additional checks
# to say, if the step is actually necessary to run. For example an `InstallPackage`
# procedure would not be necessary when the package is already installed.
def necessary?
true
end

# update reporter about the current message
def say(message)
execution.update(message)
end

# internal method called by executor
def __run__(execution)
setup_execution_state(execution)
run
end

# method defined both on object and class to ensure we work always with object
# even when the definitions provide us only class
def ensure_instance
self
end

# clean the execution-specific state to prepare for the next execution
# attempts
def setup_execution_state(execution)
@_execution = execution
@next_steps = []
end

class << self
def ensure_instance
new
end
end
end
end
(8-8/19)