Class: ForemanMaintain::UpgradeRunner

Inherits:
Runner
  • Object
show all
Extended by:
Concerns::Finders
Includes:
Concerns::Finders
Defined in:
lib/foreman_maintain/upgrade_runner.rb

Constant Summary collapse

PHASES =

Phases of the upgrade, see README.md for more info

[:pre_upgrade_checks,
:pre_migrations,
:migrations,
:post_migrations,
:post_upgrade_checks].freeze

Instance Attribute Summary collapse

Attributes inherited from Runner

#exit_code, #reporter

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::Finders

check, detector, feature, find_all_scenarios, find_checks, find_procedures, find_scenarios, procedure

Methods inherited from Runner

#add_steps, #ask_to_quit, #assumeyes?, #quit?, #run_scenario, #whitelisted_step?

Constructor Details

#initialize(version, reporter, options = {}) ⇒ UpgradeRunner

Returns a new instance of UpgradeRunner.



58
59
60
61
62
63
64
65
# 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

Instance Attribute Details

#phaseObject

Returns the value of attribute phase.



56
57
58
# File 'lib/foreman_maintain/upgrade_runner.rb', line 56

def phase
  @phase
end

#tagObject (readonly)

Returns the value of attribute tag.



56
57
58
# File 'lib/foreman_maintain/upgrade_runner.rb', line 56

def tag
  @tag
end

#versionObject (readonly)

Returns the value of attribute version.



56
57
58
# File 'lib/foreman_maintain/upgrade_runner.rb', line 56

def version
  @version
end

Class Method Details

.available_targetsObject



15
16
17
18
19
20
21
22
23
24
25
# 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

.clear_current_target_versionObject



51
52
53
# File 'lib/foreman_maintain/upgrade_runner.rb', line 51

def clear_current_target_version
  ForemanMaintain.storage.update_and_save(:upgrade_target_version => nil)
end

.clear_registerObject



39
40
41
# File 'lib/foreman_maintain/upgrade_runner.rb', line 39

def clear_register
  versions_to_tags.lear
end

.current_target_versionObject



43
44
45
# File 'lib/foreman_maintain/upgrade_runner.rb', line 43

def current_target_version
  ForemanMaintain.storage[:upgrade_target_version]
end

.current_target_version=(value) ⇒ Object



47
48
49
# File 'lib/foreman_maintain/upgrade_runner.rb', line 47

def current_target_version=(value)
  ForemanMaintain.storage.update_and_save(:upgrade_target_version => value)
end

.register_version(version, tag) ⇒ Object

registers target version to specific tag



32
33
34
35
36
37
# 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

.versions_to_tagsObject



27
28
29
# File 'lib/foreman_maintain/upgrade_runner.rb', line 27

def versions_to_tags
  @versions_to_tags ||= {}
end

Instance Method Details

#finish_upgradeObject



105
106
107
108
109
110
111
# File 'lib/foreman_maintain/upgrade_runner.rb', line 105

def finish_upgrade
  @finished = true
  @reporter.hline
  @reporter.puts <<-MESSAGE.strip_heredoc
    Upgrade finished.
  MESSAGE
end

#loadObject

deserializes the state of the run from the storage



128
129
130
131
# File 'lib/foreman_maintain/upgrade_runner.rb', line 128

def load
  return unless storage[:serialized]
  load_from_hash(storage[:serialized])
end

#runObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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

#run_phase(phase) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
# 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

#run_rollbackObject



98
99
100
101
102
103
# 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

#saveObject

serializes the state of the run to storage



118
119
120
121
122
123
124
125
# 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

#scenario(phase) ⇒ Object



67
68
69
70
71
72
73
# 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

#skip_phase(skipped_phase) ⇒ Object



145
146
147
148
149
150
151
152
153
154
# 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 <<-MESSAGE.strip_heredoc
      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

#storageObject



113
114
115
# File 'lib/foreman_maintain/upgrade_runner.rb', line 113

def storage
  ForemanMaintain.storage("upgrade_#{version}")
end

#update_current_target_versionObject



92
93
94
95
96
# 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