Revision fe78718e
Added by Ivan Necas almost 7 years ago
lib/foreman_maintain/executable.rb | ||
---|---|---|
module ForemanMaintain
|
||
class Executable
|
||
extend Forwardable
|
||
extend Concerns::Finders
|
||
attr_reader :options
|
||
def_delegators :execution,
|
||
:success?, :fail?, :warning?, :output,
|
||
... | ... | |
@next_steps = []
|
||
end
|
||
|
||
# serialization methods
|
||
def to_hash
|
||
ret = { :label => label, :param_values => @param_values }
|
||
if @_execution
|
||
ret[:status] = @_execution.status
|
||
ret[:output] = @_execution.output
|
||
end
|
||
ret
|
||
end
|
||
|
||
def matches_hash?(hash)
|
||
label == hash[:label] && @param_values == hash[:param_values]
|
||
end
|
||
|
||
def update_from_hash(hash)
|
||
raise "The step is not matching the hash #{hash.inspect}" unless matches_hash?(hash)
|
||
raise "Can't update step that was already executed" if @_execution
|
||
@_execution = Runner::StoredExecution.new(self, :status => hash[:status],
|
||
:output => hash[:output])
|
||
end
|
||
|
||
class << self
|
||
def ensure_instance
|
||
new
|
lib/foreman_maintain/runner.rb | ||
---|---|---|
attr_reader :reporter
|
||
|
||
require 'foreman_maintain/runner/execution'
|
||
require 'foreman_maintain/runner/stored_execution'
|
||
def initialize(reporter, scenarios, options = {})
|
||
options.validate_options!(:assumeyes, :whitelist)
|
||
@assumeyes = options.fetch(:assumeyes, false)
|
lib/foreman_maintain/runner/execution.rb | ||
---|---|---|
class Execution
|
||
include Concerns::Logger
|
||
extend Forwardable
|
||
def_delegators :@reporter, :with_spinner, :puts, :print, :ask, :assumeyes?
|
||
def_delegators :reporter, :with_spinner, :puts, :print, :ask, :assumeyes?
|
||
|
||
# Step performed as part of the execution
|
||
attr_reader :step
|
lib/foreman_maintain/runner/stored_execution.rb | ||
---|---|---|
module ForemanMaintain
|
||
class Runner
|
||
# Class representing an execution of a single step in scenario
|
||
class StoredExecution < Execution
|
||
include Concerns::Logger
|
||
extend Forwardable
|
||
|
||
def initialize(step, hash)
|
||
@step = step
|
||
@status = hash[:status]
|
||
@output = hash[:output]
|
||
end
|
||
|
||
def reporter
|
||
raise 'Can not access reporter from stored execution'
|
||
end
|
||
|
||
def run
|
||
raise 'Can not run stored execution'
|
||
end
|
||
end
|
||
end
|
||
end
|
lib/foreman_maintain/scenario.rb | ||
---|---|---|
include Concerns::SystemHelpers
|
||
include Concerns::ScenarioMetadata
|
||
include Concerns::Finders
|
||
extend Concerns::Finders
|
||
|
||
attr_reader :steps
|
||
|
||
... | ... | |
def inspect
|
||
"#{self.class.metadata[:description]}<#{self.class.name}>"
|
||
end
|
||
|
||
def to_hash
|
||
{ :label => label,
|
||
:steps => steps.map(&:to_hash) }
|
||
end
|
||
|
||
def self.new_from_hash(hash)
|
||
scenarios = find_scenarios(:label => hash[:label])
|
||
unless scenarios.size == 1
|
||
raise "Could not find scenario #{hash[:label]}, found #{scenarios.size} scenarios"
|
||
end
|
||
scenario = scenarios.first
|
||
scenario.load_step_states(hash[:steps])
|
||
scenario
|
||
end
|
||
|
||
def load_step_states(steps_hash)
|
||
steps = self.steps.dup
|
||
steps_hash.each do |step_hash|
|
||
until steps.empty?
|
||
step = steps.shift
|
||
if step.matches_hash?(step_hash)
|
||
step.update_from_hash(step_hash)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
lib/foreman_maintain/upgrade_runner.rb | ||
---|---|---|
# if we started from the :pre_upgrade_checks, ensure to ask before
|
||
# continuing with the rest of the upgrade
|
||
@ask_to_confirm_upgrade = (self.phase == :pre_upgrade_checks)
|
||
self.phase = phase
|
||
end
|
||
end
|
||
|
||
def storage
|
||
# TODO: determine from upgrade scenario
|
||
ForemanMaintain.storage(:upgrade)
|
||
end
|
||
|
||
# serializes the state of the run to storage
|
||
def save
|
||
storage[:serialized] = to_hash
|
||
storage.save
|
||
end
|
||
|
||
# deserializes the state of the run from the storage
|
||
def load
|
||
load_from_hash(storage[:serialized])
|
||
end
|
||
|
||
private
|
||
|
||
def to_hash
|
||
ret = { :phase => phase, :scenarios => {} }
|
||
@scenario_cache.each do |key, scenario|
|
||
ret[:scenarios][key] = scenario.to_hash
|
||
end
|
||
ret
|
||
end
|
||
|
||
def load_from_hash(hash)
|
||
unless @scenario_cache.empty?
|
||
raise "Some scenarios are already initialized: #{@scenario_cache.keys}"
|
||
end
|
||
self.phase = hash[:phase]
|
||
hash[:scenarios].each do |key, scenario_hash|
|
||
@scenario_cache[key] = Scenario.new_from_hash(scenario_hash)
|
||
end
|
||
end
|
||
|
||
def confirm_scenario(scenario)
|
||
decision = super(scenario)
|
||
# we have not asked the user already about next steps
|
test/lib/upgrade_runner_test.rb | ||
---|---|---|
'present_service pre_upgrade_checks scenario'])
|
||
end
|
||
|
||
it 'remembers the state of the previous run of the upgrade'
|
||
|
||
it 'asks for confirmation before getting into pre_migrations from pre upgrade checks' do
|
||
upgrade_runner_with_whitelist.run
|
||
reporter.log.last.must_equal ['ask', <<-MESSAGE.strip_heredoc.strip]
|
||
... | ... | |
MESSAGE
|
||
end
|
||
|
||
it 'remembers the state of the previous run of the upgrade' do
|
||
upgrade_runner_with_whitelist.storage.data.clear
|
||
upgrade_runner_with_whitelist.run
|
||
upgrade_runner_with_whitelist.save
|
||
original_scenario = upgrade_runner_with_whitelist.scenario(:pre_upgrade_checks)
|
||
|
||
ForemanMaintain.detector.refresh
|
||
new_upgrade_runner = UpgradeRunner.new('1.15', reporter)
|
||
new_upgrade_runner.load
|
||
new_upgrade_runner.phase.must_equal :pre_migrations
|
||
restored_scenario = new_upgrade_runner.scenario(:pre_upgrade_checks)
|
||
restored_scenario.steps.map { |s| s.execution.status }.
|
||
must_equal(original_scenario.steps.map { |step| step.execution.status })
|
||
end
|
||
|
||
it 'does not run the pre_upgrade_checks again when already in pre_migrations phase' do
|
||
upgrade_runner.send(:phase=, :pre_migrations)
|
||
upgrade_runner.run
|
Also available in: Unified diff
Support for scenario serialization/deserialization