class ForemanMaintain::UpgradeRunner
Constants
- PHASES
Phases of the upgrade, see README.md for more info
Attributes
phase[R]
tag[R]
version[R]
Public Class Methods
available_targets()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 15 def available_targets # when some upgrade is in progress, we don't allow upgrade to different version return [current_target_version] if current_target_version find_scenarios(:tags => :upgrade_scenario).map(&:target_version).uniq.sort end
clear_current_target_version()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 30 def clear_current_target_version ForemanMaintain.storage.update_and_save(:upgrade_target_version => nil) end
current_target_version()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 22 def current_target_version ForemanMaintain.storage[:upgrade_target_version] end
current_target_version=(value)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 26 def current_target_version=(value) ForemanMaintain.storage.update_and_save(:upgrade_target_version => value) end
new(reporter, options = {})
click to toggle source
Calls superclass method
ForemanMaintain::Runner::new
# File lib/foreman_maintain/upgrade_runner.rb, line 37 def initialize(reporter, options = {}) super(reporter, [], options) @scenario_cache = {} @phase = :pre_upgrade_checks condition = { :tags => [:upgrade_scenario, phase] } matching_scenarios = find_scenarios(condition) @version = matching_scenarios.first&.target_version end
Public Instance Methods
available?()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 46 def available? condition = { :tags => [:upgrade_scenario, :pre_upgrade_checks] } matching_scenarios = find_scenarios(condition) !matching_scenarios.empty? end
finish_upgrade()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 93 def finish_upgrade @finished = true @reporter.hline @reporter.puts <<~MESSAGE Upgrade finished. MESSAGE end
load()
click to toggle source
deserializes the state of the run from the storage
# File lib/foreman_maintain/upgrade_runner.rb, line 116 def load return unless storage[:serialized] load_from_hash(storage[:serialized]) end
run()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 62 def run self.class.current_target_version = @version PHASES.each do |phase| return run_rollback if quit? if skip?(phase) skip_phase(phase) else run_phase(phase) end end unless quit? finish_upgrade end ensure update_current_target_version end
run_phase(phase)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 122 def run_phase(phase) with_non_empty_scenario(phase) do |scenario| confirm_scenario(scenario) return if quit? self.phase = phase run_scenario(scenario) # if we started from the :pre_upgrade_checks, ensure to ask before # continuing with the rest of the upgrade @ask_to_confirm_upgrade = phase == :pre_upgrade_checks end end
run_rollback()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 86 def run_rollback # we only are able to rollback from pre_migrations phase if phase == :pre_migrations rollback_pre_migrations end end
save()
click to toggle source
serializes the state of the run to storage
# File lib/foreman_maintain/upgrade_runner.rb, line 106 def save if @finished storage.delete(:serialized) else storage[:serialized] = to_hash end storage.save end
scenario(phase)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 52 def scenario(phase) return @scenario_cache[phase] if @scenario_cache.key?(phase) condition = { :tags => [:upgrade_scenario, phase] } matching_scenarios = find_scenarios(condition) raise "Too many scenarios match #{condition.inspect}" if matching_scenarios.size > 1 @scenario_cache[phase] = matching_scenarios.first end
skip_phase(skipped_phase)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 135 def skip_phase(skipped_phase) with_non_empty_scenario(skipped_phase) do |scenario| @reporter.before_scenario_starts(scenario) @reporter.puts <<~MESSAGE Skipping #{skipped_phase} phase as it was already run before. To enforce to run the phase, use `upgrade run --phase #{skipped_phase}` MESSAGE @reporter.after_scenario_finishes(scenario) end end
storage()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 101 def storage ForemanMaintain.storage("upgrade_#{version}") end
update_current_target_version()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 80 def update_current_target_version if phase == :pre_upgrade_checks || @finished UpgradeRunner.clear_current_target_version end end
Private Instance Methods
confirm_scenario(scenario)
click to toggle source
Calls superclass method
ForemanMaintain::Runner#confirm_scenario
# File lib/foreman_maintain/upgrade_runner.rb, line 197 def confirm_scenario(scenario) decision = super(scenario) # we have not asked the user already about next steps if decision.nil? && @ask_to_confirm_upgrade response = reporter.ask_decision(<<~MESSAGE.strip) The pre-upgrade checks indicate that the system is ready for upgrade. It's recommended to perform a backup at this stage. Confirm to continue with the modification part of the upgrade MESSAGE if [:no, :quit].include?(response) ask_to_quit end end response ensure @ask_to_confirm_upgrade = false end
load_from_hash(hash)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 186 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
phase=(phase)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 220 def phase=(phase) raise "Unknown phase #{phase}" unless PHASES.include?(phase) @phase = phase end
rollback_pre_migrations()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 148 def rollback_pre_migrations raise "Unexpected phase #{phase}, expecting pre_migrations" unless phase == :pre_migrations rollback_needed = scenario(:pre_migrations).steps.any? { |s| s.executed? && s.success? } if rollback_needed @quit = false # prevent the unnecessary confirmation questions @last_scenario = nil @last_scenario_continuation_confirmed = true [:post_migrations, :post_upgrade_checks].each do |phase| if quit? && phase == :post_upgrade_checks self.phase = :pre_migrations return # rubocop:disable Lint/NonLocalExitFromIterator end run_phase(phase) end end self.phase = :pre_upgrade_checks # rollback finished @reporter.puts <<~MESSAGE The upgrade failed and system was restored to pre-upgrade state. MESSAGE end
skip?(next_phase)
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 215 def skip?(next_phase) # the next_phase was run before the current phase PHASES.index(next_phase) < PHASES.index(phase) end
to_hash()
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 178 def to_hash ret = { :phase => phase, :scenarios => {} } @scenario_cache.each do |key, scenario| ret[:scenarios][key] = scenario.to_hash end ret end
with_non_empty_scenario(phase) { |next_scenario| ... }
click to toggle source
# File lib/foreman_maintain/upgrade_runner.rb, line 171 def with_non_empty_scenario(phase) next_scenario = scenario(phase) unless next_scenario.nil? || next_scenario.steps.empty? yield next_scenario end end