class ForemanMaintain::UpdateRunner

Constants

PHASES

Attributes

phase[R]

Public Class Methods

new(reporter, options = {}) click to toggle source
Calls superclass method ForemanMaintain::Runner::new
# File lib/foreman_maintain/update_runner.rb, line 15
def initialize(reporter, options = {})
  super(reporter, [], options)
  @scenario_cache = {}
  self.phase = :pre_update_checks
end

Public Instance Methods

available?() click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 21
def available?
  condition = { :tags => [:update_scenario, :pre_update_checks] }
  matching_scenarios = find_scenarios(condition)
  !matching_scenarios.empty?
end
find_scenario(phase) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 27
def find_scenario(phase)
  return @scenario_cache[phase] if @scenario_cache.key?(phase)

  condition = { :tags => [:update_scenario, phase] }
  matching_scenarios = find_scenarios(condition)
  @scenario_cache[phase] = matching_scenarios.first
end
finish_update() click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 56
def finish_update
  @finished = true
  @reporter.hline
  @reporter.puts("Update finished.\n")
end
load() click to toggle source

deserializes the state of the run from the storage

# File lib/foreman_maintain/update_runner.rb, line 77
def load
  return unless storage[:serialized]

  load_from_hash(storage[:serialized])
end
run() click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 35
def run
  PHASES.each do |phase|
    return run_rollback if quit?

    if skip?(phase)
      skip_phase(phase)
    else
      run_phase(phase)
    end
  end

  finish_update unless quit?
end
run_phase(phase) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 83
def run_phase(phase)
  scenario = find_scenario(phase)
  return if scenario.nil? || scenario.steps.empty?

  confirm_scenario(scenario)
  return if quit?

  self.phase = phase
  run_scenario(scenario)
  # if we started from the :pre_update_checks, ensure to ask before
  # continuing with the rest of the update
  @ask_to_confirm_update = phase == :pre_update_checks
end
run_rollback() click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 49
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/update_runner.rb, line 67
def save
  if @finished
    storage.delete(:serialized)
  else
    storage[:serialized] = to_hash
  end
  storage.save
end
skip_phase(skipped_phase) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 97
    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.
        MESSAGE
        @reporter.after_scenario_finishes(scenario)
      end
    end
storage() click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 62
def storage
  ForemanMaintain.storage("update")
end

Private Instance Methods

confirm_scenario(scenario) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 152
    def confirm_scenario(scenario)
      decision = super(scenario)
      # we have not asked the user already about next steps
      if decision.nil? && @ask_to_confirm_update
        response = reporter.ask_decision(<<~MESSAGE.strip)
          The pre-update checks indicate that the system is ready for update.
          It's recommended to perform a backup at this stage.
          Confirm to continue with the modification part of the update
        MESSAGE
        if [:no, :quit].include?(response)
          ask_to_quit
        end
      end
      response
    ensure
      @ask_to_confirm_update = false
    end
load_from_hash(hash) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 141
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/update_runner.rb, line 175
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/update_runner.rb, line 109
def rollback_pre_migrations
  raise "Unexpected phase #{phase}, expecting pre_migrations" unless phase == :pre_migrations

  rollback_needed = find_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_update_checks].each do |phase|
      run_phase(phase)
    end
  end
  self.phase = :pre_update_checks # rollback finished
  @reporter.puts("The update failed and system was restored to pre-update state.")
end
skip?(next_phase) click to toggle source
# File lib/foreman_maintain/update_runner.rb, line 170
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/update_runner.rb, line 133
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/update_runner.rb, line 126
def with_non_empty_scenario(phase)
  next_scenario = find_scenario(phase)
  unless next_scenario.nil? || next_scenario.steps.empty?
    yield next_scenario
  end
end