Project

General

Profile

« Previous | Next » 

Revision fe78718e

Added by Ivan Necas almost 7 years ago

Support for scenario serialization/deserialization

View differences:

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