Phases of the upgrade, see README.md for more info
# 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 versions_to_tags.inject([]) do |available_targets, (version, tag)| if !find_scenarios(:tags => [tag]).empty? available_targets << version else available_targets end end.sort end
# File lib/foreman_maintain/upgrade_runner.rb, line 51 def clear_current_target_version ForemanMaintain.storage.update_and_save(:upgrade_target_version => nil) end
# File lib/foreman_maintain/upgrade_runner.rb, line 39 def clear_register versions_to_tags.lear end
# File lib/foreman_maintain/upgrade_runner.rb, line 43 def current_target_version ForemanMaintain.storage[:upgrade_target_version] end
# File lib/foreman_maintain/upgrade_runner.rb, line 47 def current_target_version=(value) ForemanMaintain.storage.update_and_save(:upgrade_target_version => value) end
# File lib/foreman_maintain/upgrade_runner.rb, line 58 def initialize(version, reporter, options = {}) super(reporter, [], options) @tag = self.class.versions_to_tags[version] raise "Unknown version #{version}" unless tag @version = version @scenario_cache = {} self.phase = :pre_upgrade_checks end
registers target version to specific tag
# File lib/foreman_maintain/upgrade_runner.rb, line 32 def register_version(version, tag) if versions_to_tags.key?(version) && versions_to_tags[version] != tag raise "Version #{version} already registered to tag #{versions_to_tags[version]}" end @versions_to_tags[version] = tag end
# File lib/foreman_maintain/upgrade_runner.rb, line 105 def finish_upgrade @finished = true @reporter.hline @reporter.puts " Upgrade finished. ".strip_heredoc end
deserializes the state of the run from the storage
# File lib/foreman_maintain/upgrade_runner.rb, line 128 def load return unless storage[:serialized] load_from_hash(storage[:serialized]) end
# File lib/foreman_maintain/upgrade_runner.rb, line 75 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
# File lib/foreman_maintain/upgrade_runner.rb, line 133 def run_phase(phase) with_non_empty_scenario(phase) do |scenario| confirm_scenario(scenario) return if quit? self.phase = phase run_scenario(scenario, false) # 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
# File lib/foreman_maintain/upgrade_runner.rb, line 98 def run_rollback # we only are able to rollback from pre_migrations phase if phase == :pre_migrations rollback_pre_migrations end end
serializes the state of the run to storage
# File lib/foreman_maintain/upgrade_runner.rb, line 118 def save if @finished storage.delete(:serialized) else storage[:serialized] = to_hash end storage.save end
# File lib/foreman_maintain/upgrade_runner.rb, line 67 def scenario(phase) return @scenario_cache[phase] if @scenario_cache.key?(phase) condition = { :tags => [tag, phase] } matching_scenarios = find_all_scenarios(condition) raise "Too many scenarios match #{condition.inspect}" if matching_scenarios.size > 1 @scenario_cache[phase] = matching_scenarios.first end
# File lib/foreman_maintain/upgrade_runner.rb, line 145 def skip_phase(skipped_phase) with_non_empty_scenario(skipped_phase) do |scenario| @reporter.before_scenario_starts(scenario) @reporter.puts " Skipping #{skipped_phase} phase as it was already run before. To enforce to run the phase, use `upgrade run --phase #{skipped_phase}` ".strip_heredoc @reporter.after_scenario_finishes(scenario) end end
# File lib/foreman_maintain/upgrade_runner.rb, line 113 def storage ForemanMaintain.storage("upgrade_#{version}") end
# File lib/foreman_maintain/upgrade_runner.rb, line 92 def update_current_target_version if phase == :pre_upgrade_checks || @finished UpgradeRunner.clear_current_target_version end end
# File lib/foreman_maintain/upgrade_runner.rb, line 205 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(" 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 the modification part of the upgrade ".strip_heredoc.strip) if [:no, :quit].include?(response) ask_to_quit end end response ensure @ask_to_confirm_upgrade = false end
# File lib/foreman_maintain/upgrade_runner.rb, line 195 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
# File lib/foreman_maintain/upgrade_runner.rb, line 228 def phase=(phase) raise "Unknown phase #{phase}" unless PHASES.include?(phase) @phase = phase end
rubocop:disable Metrics/AbcSize
# File lib/foreman_maintain/upgrade_runner.rb, line 159 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 @last_scenario = nil # to prevent the unnecessary confirmation questions [: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 " The upgrade failed and system was restored to pre-upgrade state. ".strip_heredoc end
# File lib/foreman_maintain/upgrade_runner.rb, line 223 def skip?(next_phase) # the next_phase was run before the current phase PHASES.index(next_phase) < PHASES.index(phase) end
# File lib/foreman_maintain/upgrade_runner.rb, line 187 def to_hash ret = { :phase => phase, :scenarios => {} } @scenario_cache.each do |key, scenario| ret[:scenarios][key] = scenario.to_hash end ret end
rubocop:enable Metrics/AbcSize, Lint/NonLocalExitFromIterator
# File lib/foreman_maintain/upgrade_runner.rb, line 180 def with_non_empty_scenario(phase) next_scenario = scenario(phase) unless next_scenario.nil? || next_scenario.steps.empty? yield next_scenario end end