foreman_maintain 1.6.4 → 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc4310d22dcb14b51945e3642cba4c7050e6660893dc09639064b013a2881380
4
- data.tar.gz: d305fc1da3bd0a013d4455ec1ae578f22529fe5302261f82be251be5a0ee9a84
3
+ metadata.gz: 9832b114fa0e778b687140d47774ffa583742e69c0883f7e0738fad23e6d0f87
4
+ data.tar.gz: dfd33002a93b7171aab581342c169d0eef6cee318302bad7d24108581e05b514
5
5
  SHA512:
6
- metadata.gz: d10f290659e20460fffcebf72291e7260a6caf3c8d0964bdb3bd40d9f86ec9b8a5f70781c2f9de2d01778f09bdcda1421defb679a7f541d7ff4b21406368ca3c
7
- data.tar.gz: c63898eece400b9d3813e06e070a3188c27ad5a06aaf57652c68e6f0887bf5b9173b6dd6eb9192acf37dff6b8d2b4c89285f65cf427de72a7a1aa69cc4b9f703
6
+ metadata.gz: 30c727eed2a0f6fb4402caedfcbca2b5e8466b322f94f938523e16726b9439d3b00737950d88c41993fdd61f8cedea7c67752d1917e91ff6a6dde57dfbca1544
7
+ data.tar.gz: fd20b2f2ea602071e1371266b62e7640b945a942208469019f0ee173ab90afd51de78e91c9790c525d1d6e689f5d47779e57ce22c032a1a1d3c53f61eb566135
@@ -12,7 +12,7 @@ module Checks::Repositories
12
12
 
13
13
  param :version,
14
14
  'Version for which repositories needs to be validated',
15
- :required => true
15
+ :required => false
16
16
 
17
17
  manual_detection
18
18
  end
@@ -21,6 +21,8 @@ module Checks::Repositories
21
21
  if feature(:instance).downstream.subscribed_using_activation_key?
22
22
  skip 'Your system is subscribed using custom activation key'
23
23
  else
24
+ @version ||= package_version(feature(:instance).downstream.package_name)
25
+
24
26
  with_spinner("Validating availability of repositories for #{@version}") do |spinner|
25
27
  find_absent_repos(spinner)
26
28
  end
@@ -5,7 +5,7 @@ module Procedures::Packages
5
5
  end
6
6
 
7
7
  def run
8
- status, output = execute_with_status('dnf needs-restarting --reboothint')
8
+ status, output = package_manager.reboot_required?
9
9
  if status == 1
10
10
  set_info_warn(output)
11
11
  else
@@ -7,13 +7,18 @@ module Procedures::Packages
7
7
  param :warn_on_errors, 'Do not interrupt scenario on failure',
8
8
  :flag => true, :default => false
9
9
  param :dnf_options, 'Extra dnf options if any', :array => true, :default => []
10
+ param :download_only, 'Download and cache packages only', :flag => true, :default => false
10
11
  param :clean_cache, 'If true will cause a DNF cache clean', :flag => true, :default => true
11
12
  end
12
13
 
13
14
  def run
14
15
  assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
15
16
  package_manager.clean_cache(:assumeyes => assumeyes_val) if @clean_cache
16
- opts = { :assumeyes => assumeyes_val, :dnf_options => @dnf_options }
17
+ opts = {
18
+ :assumeyes => assumeyes_val,
19
+ :options => @dnf_options,
20
+ :download_only => @download_only,
21
+ }
17
22
  packages_action(:update, @packages, opts)
18
23
  rescue ForemanMaintain::Error::ExecutionError => e
19
24
  if @warn_on_errors
@@ -28,15 +33,11 @@ module Procedures::Packages
28
33
  end
29
34
 
30
35
  def description
31
- if download_only?
36
+ if @download_only
32
37
  "Download package(s) #{@packages.join(', ')}"
33
38
  else
34
39
  "Update package(s) #{@packages.join(', ')}"
35
40
  end
36
41
  end
37
-
38
- def download_only?
39
- @dnf_options.include?('--downloadonly')
40
- end
41
42
  end
42
43
  end
@@ -10,8 +10,6 @@ module Procedures::Packages
10
10
  if @packages.nil? || @packages.empty?
11
11
  question = "\nWARNING: No specific packages to update were provided\n" \
12
12
  "so we are going to update all available packages.\n" \
13
- "It is recommended to update everything only as part of upgrade\n" \
14
- "of the #{feature(:instance).product_name} to the next version. \n" \
15
13
  "To Upgrade to next version use 'foreman-maintain upgrade'.\n\n" \
16
14
  "Do you want to proceed with update of everything regardless\n" \
17
15
  'of the recommendations?'
@@ -115,22 +115,16 @@ module ForemanMaintain::Scenarios
115
115
  end
116
116
 
117
117
  add_step_with_context(Procedures::Packages::UnlockVersions)
118
+ add_step_with_context(
119
+ Procedures::Packages::Update,
120
+ :force => true,
121
+ :warn_on_errors => true,
122
+ :download_only => context.get(:downloadonly)
123
+ )
118
124
 
119
125
  if context.get(:downloadonly)
120
- add_step_with_context(
121
- Procedures::Packages::Update,
122
- :force => true,
123
- :warn_on_errors => true,
124
- :dnf_options => ['--downloadonly']
125
- )
126
126
  add_step_with_context(Procedures::Packages::LockVersions)
127
127
  else
128
- add_step_with_context(
129
- Procedures::Packages::Update,
130
- :force => true,
131
- :warn_on_errors => true
132
- )
133
-
134
128
  add_step_with_context(Procedures::Installer::Run)
135
129
  end
136
130
 
@@ -0,0 +1,126 @@
1
+ module Scenarios::Update
2
+ class Abstract < ForemanMaintain::Scenario
3
+ def self.update_metadata(&block)
4
+ metadata do
5
+ tags :update_scenario
6
+ instance_eval(&block)
7
+ end
8
+ end
9
+ end
10
+
11
+ class PreUpdateCheck < Abstract
12
+ update_metadata do
13
+ description 'Checks before updating'
14
+ tags :pre_update_checks
15
+ run_strategy :fail_slow
16
+ end
17
+
18
+ # rubocop:disable Metrics/MethodLength
19
+ def compose
20
+ add_steps(
21
+ Checks::Foreman::FactsNames, # if Foreman database present
22
+ Checks::ForemanProxy::CheckTftpStorage, # if Satellite with foreman-proxy+tftp
23
+ Checks::ForemanProxy::VerifyDhcpConfigSyntax, # if foreman-proxy+dhcp-isc
24
+ Checks::ForemanTasks::NotPaused, # if foreman-tasks present
25
+ Checks::Puppet::VerifyNoEmptyCacertRequests, # if puppetserver
26
+ Checks::ServerPing,
27
+ Checks::ServicesUp,
28
+ Checks::SystemRegistration,
29
+ Checks::CheckHotfixInstalled,
30
+ Checks::CheckTmout,
31
+ Checks::CheckUpstreamRepository,
32
+ Checks::Disk::AvailableSpace,
33
+ Checks::Disk::AvailableSpaceCandlepin, # if candlepin
34
+ Checks::Foreman::ValidateExternalDbVersion, # if external database
35
+ Checks::Foreman::CheckCorruptedRoles,
36
+ Checks::Foreman::CheckDuplicatePermissions,
37
+ Checks::Foreman::TuningRequirements, # if katello present
38
+ Checks::ForemanOpenscap::InvalidReportAssociations, # if foreman-openscap
39
+ Checks::ForemanTasks::Invalid::CheckOld, # if foreman-tasks
40
+ Checks::ForemanTasks::Invalid::CheckPendingState, # if foreman-tasks
41
+ Checks::ForemanTasks::Invalid::CheckPlanningState, # if foreman-tasks
42
+ Checks::ForemanTasks::NotRunning, # if foreman-tasks
43
+ Checks::NonRhPackages,
44
+ Checks::PackageManager::Dnf::ValidateDnfConfig,
45
+ Checks::Repositories::CheckNonRhRepository,
46
+ Checks::Repositories::Validate
47
+ )
48
+ end
49
+ # rubocop:enable Metrics/MethodLength
50
+ end
51
+
52
+ class PreMigrations < Abstract
53
+ update_metadata do
54
+ description 'Procedures before migrating'
55
+ tags :pre_migrations
56
+ end
57
+
58
+ def compose
59
+ add_steps(
60
+ Procedures::Packages::Update.new(
61
+ :assumeyes => true,
62
+ :dnf_options => ['--downloadonly']
63
+ ),
64
+ Procedures::MaintenanceMode::EnableMaintenanceMode,
65
+ Procedures::Crond::Stop,
66
+ Procedures::SyncPlans::Disable
67
+ )
68
+ end
69
+ end
70
+
71
+ class Migrations < Abstract
72
+ update_metadata do
73
+ description 'Migration scripts'
74
+ tags :migrations
75
+ run_strategy :fail_fast
76
+ end
77
+
78
+ def compose
79
+ add_steps(
80
+ Procedures::Service::Stop,
81
+ Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false),
82
+ Procedures::Installer::Run.new(:assumeyes => true),
83
+ Procedures::Installer::UpgradeRakeTask
84
+ )
85
+ end
86
+ end
87
+
88
+ class PostMigrations < Abstract
89
+ update_metadata do
90
+ description 'Procedures after migrating'
91
+ tags :post_migrations
92
+ end
93
+
94
+ def compose
95
+ add_steps(
96
+ Procedures::RefreshFeatures,
97
+ Procedures::Service::Start,
98
+ Procedures::Crond::Start,
99
+ Procedures::SyncPlans::Enable,
100
+ Procedures::MaintenanceMode::DisableMaintenanceMode
101
+ )
102
+ end
103
+ end
104
+
105
+ class PostUpdateChecks < Abstract
106
+ update_metadata do
107
+ description 'Checks after update'
108
+ tags :post_update_checks
109
+ run_strategy :fail_slow
110
+ end
111
+
112
+ def compose
113
+ add_steps(
114
+ Checks::Foreman::FactsNames, # if Foreman database present
115
+ Checks::ForemanProxy::CheckTftpStorage, # if Satellite with foreman-proxy+tftp
116
+ Checks::ForemanProxy::VerifyDhcpConfigSyntax, # if foreman-proxy+dhcp-isc
117
+ Checks::ForemanTasks::NotPaused, # if foreman-tasks present
118
+ Checks::Puppet::VerifyNoEmptyCacertRequests, # if puppetserver
119
+ Checks::ServerPing,
120
+ Checks::ServicesUp,
121
+ Checks::SystemRegistration,
122
+ Procedures::Packages::CheckForReboot
123
+ )
124
+ end
125
+ end
126
+ end
@@ -63,7 +63,7 @@ module Scenarios::Capsule_6_16
63
63
  end
64
64
  add_step(Procedures::Packages::Update.new(
65
65
  :assumeyes => true,
66
- :dnf_options => ['--downloadonly']
66
+ :download_only => true
67
67
  ))
68
68
  add_step(Procedures::Service::Stop.new)
69
69
  add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
@@ -45,7 +45,7 @@ module Scenarios::Capsule_6_16_z
45
45
  end
46
46
  add_step(Procedures::Packages::Update.new(
47
47
  :assumeyes => true,
48
- :dnf_options => ['--downloadonly']
48
+ :download_only => true
49
49
  ))
50
50
  add_steps(find_procedures(:pre_migrations))
51
51
  end
@@ -60,7 +60,7 @@ module Scenarios::Katello_Nightly
60
60
  end
61
61
  add_step(Procedures::Packages::Update.new(
62
62
  :assumeyes => true,
63
- :dnf_options => ['--downloadonly']
63
+ :download_only => true
64
64
  ))
65
65
  add_step(Procedures::Service::Stop.new)
66
66
  add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
@@ -65,7 +65,7 @@ module Scenarios::Satellite_6_16
65
65
  end
66
66
  add_step(Procedures::Packages::Update.new(
67
67
  :assumeyes => true,
68
- :dnf_options => ['--downloadonly']
68
+ :download_only => true
69
69
  ))
70
70
  add_step(Procedures::Service::Stop.new)
71
71
  add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
@@ -45,7 +45,7 @@ module Scenarios::Satellite_6_16_z
45
45
  end
46
46
  add_step(Procedures::Packages::Update.new(
47
47
  :assumeyes => true,
48
- :dnf_options => ['--downloadonly']
48
+ :download_only => true
49
49
  ))
50
50
  add_steps(find_procedures(:pre_migrations))
51
51
  end
@@ -0,0 +1,48 @@
1
+ require 'foreman_maintain/update_runner'
2
+
3
+ module ForemanMaintain
4
+ module Cli
5
+ class UpdateCommand < Base
6
+ def self.disable_self_update_option
7
+ option '--disable-self-update', :flag, 'Disable automatic self update',
8
+ :default => false
9
+ end
10
+
11
+ def update_runner
12
+ update_runner = ForemanMaintain::UpdateRunner.new(
13
+ reporter,
14
+ :assumeyes => assumeyes?,
15
+ :whitelist => whitelist || [],
16
+ :force => force?
17
+ )
18
+ update_runner.load
19
+ update_runner
20
+ end
21
+
22
+ subcommand 'check', 'Run pre-update checks before updating' do
23
+ interactive_option
24
+ disable_self_update_option
25
+
26
+ def execute
27
+ ForemanMaintain.validate_downstream_packages
28
+ ForemanMaintain.perform_self_upgrade unless disable_self_update?
29
+ update_runner.run_phase(:pre_update_checks)
30
+ exit update_runner.exit_code
31
+ end
32
+ end
33
+
34
+ subcommand 'run', 'Run an update' do
35
+ interactive_option
36
+ disable_self_update_option
37
+
38
+ def execute
39
+ ForemanMaintain.validate_downstream_packages
40
+ ForemanMaintain.perform_self_upgrade unless disable_self_update?
41
+ update_runner.run
42
+ update_runner.save
43
+ exit update_runner.exit_code
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -12,6 +12,7 @@ require 'foreman_maintain/cli/maintenance_mode_command'
12
12
  require 'foreman_maintain/cli/packages_command'
13
13
  require 'foreman_maintain/cli/plugin_command'
14
14
  require 'foreman_maintain/cli/self_upgrade_command'
15
+ require 'foreman_maintain/cli/update_command'
15
16
 
16
17
  Clamp.allow_options_after_parameters = true
17
18
 
@@ -22,6 +23,7 @@ module ForemanMaintain
22
23
 
23
24
  subcommand 'health', 'Health related commands', HealthCommand
24
25
  subcommand 'upgrade', 'Upgrade related commands', UpgradeCommand
26
+ subcommand 'update', 'Update related commands', UpdateCommand
25
27
  subcommand 'service', 'Control applicable services', ServiceCommand
26
28
  subcommand 'backup', 'Backup server', BackupCommand
27
29
  subcommand 'restore', 'Restore a backup', RestoreCommand
@@ -100,13 +100,17 @@ module ForemanMaintain
100
100
  end
101
101
 
102
102
  def packages_action(action, packages, options = {})
103
- options.validate_options!(:assumeyes, :dnf_options)
103
+ options.validate_options!(:assumeyes, :options, :download_only)
104
104
  case action
105
105
  when :install
106
106
  package_manager.install(packages, :assumeyes => options[:assumeyes])
107
107
  when :update
108
- package_manager.update(packages, :assumeyes => options[:assumeyes],
109
- :dnf_options => options[:dnf_options])
108
+ package_manager.update(
109
+ packages,
110
+ :assumeyes => options[:assumeyes],
111
+ :options => options[:options],
112
+ :download_only => options[:download_only]
113
+ )
110
114
  when :remove
111
115
  package_manager.remove(packages, :assumeyes => options[:assumeyes])
112
116
  else
@@ -138,7 +138,11 @@ module ForemanMaintain
138
138
  def __run__(execution)
139
139
  setup_execution_state(execution)
140
140
  unless skipped?
141
- run
141
+ if defined?(self.class.present?)
142
+ run if self.class.present?
143
+ else
144
+ run
145
+ end
142
146
  end
143
147
  rescue Error::Skip => e
144
148
  set_skip(e.message)
@@ -19,10 +19,12 @@ module ForemanMaintain::PackageManager
19
19
  apt_action('remove', packages, :assumeyes => assumeyes)
20
20
  end
21
21
 
22
- def update(packages = [], assumeyes: false)
22
+ # rubocop:disable Lint/UnusedMethodArgument
23
+ def update(packages = [], assumeyes: false, options: [], download_only: false)
23
24
  action = packages.any? ? '--only-upgrade install' : 'upgrade'
24
- apt_action(action, packages, :assumeyes => assumeyes)
25
+ apt_action(action, packages, :assumeyes => assumeyes, :download_only => download_only)
25
26
  end
27
+ # rubocop:enable Lint/UnusedMethodArgument
26
28
 
27
29
  def clean_cache(assumeyes: false)
28
30
  apt_action('clean', :assumeyes => assumeyes)
@@ -60,10 +62,18 @@ module ForemanMaintain::PackageManager
60
62
  false
61
63
  end
62
64
 
63
- def apt_action(action, packages, with_status: false, assumeyes: false, valid_exit_statuses: [0])
65
+ def reboot_required?
66
+ status = File.exist?('/var/run/reboot-required') ? 1 : 0
67
+ output = ''
68
+ [status, output]
69
+ end
70
+
71
+ # rubocop:disable Layout/LineLength
72
+ def apt_action(action, packages, with_status: false, assumeyes: false, valid_exit_statuses: [0], download_only: false)
64
73
  apt_options = []
65
74
  packages = [packages].flatten(1)
66
75
  apt_options << '-y' if assumeyes
76
+ apt_options << '--download-only' if download_only
67
77
  apt_options_s = apt_options.empty? ? '' : ' ' + apt_options.join(' ')
68
78
  packages_s = packages.empty? ? '' : ' ' + packages.join(' ')
69
79
  if with_status
@@ -74,5 +84,6 @@ module ForemanMaintain::PackageManager
74
84
  :interactive => !assumeyes, :valid_exit_statuses => valid_exit_statuses)
75
85
  end
76
86
  end
87
+ # rubocop:enable Layout/LineLength
77
88
  end
78
89
  end
@@ -59,8 +59,14 @@ module ForemanMaintain::PackageManager
59
59
  dnf_action('remove', packages, assumeyes: assumeyes)
60
60
  end
61
61
 
62
- def update(packages = [], assumeyes: false, dnf_options: [])
63
- dnf_action('update', packages, assumeyes: assumeyes, dnf_options: dnf_options)
62
+ def update(packages = [], assumeyes: false, options: [], download_only: false)
63
+ dnf_action(
64
+ 'update',
65
+ packages,
66
+ assumeyes: assumeyes,
67
+ dnf_options: options,
68
+ download_only: download_only
69
+ )
64
70
  end
65
71
 
66
72
  def check_update(packages: nil, with_status: false)
@@ -121,13 +127,18 @@ module ForemanMaintain::PackageManager
121
127
  dnf_action('module info', name, with_status: true, assumeyes: true)
122
128
  end
123
129
 
130
+ def reboot_required?
131
+ sys.execute_with_status('dnf needs-restarting --reboothint', :interactive => false)
132
+ end
133
+
124
134
  private
125
135
 
126
- # rubocop:disable Metrics/LineLength, Metrics/ParameterLists
127
- def dnf_action(action, packages, with_status: false, assumeyes: false, dnf_options: [], valid_exit_statuses: [0])
136
+ # rubocop:disable Layout/LineLength, Metrics/ParameterLists
137
+ def dnf_action(action, packages, with_status: false, assumeyes: false, dnf_options: [], valid_exit_statuses: [0], download_only: false)
128
138
  packages = [packages].flatten(1)
129
139
 
130
140
  dnf_options << '-y' if assumeyes
141
+ dnf_topions << '--downloadonly' if download_only
131
142
  dnf_options << '--disableplugin=foreman-protector'
132
143
 
133
144
  command = ['dnf', dnf_options.join(' '), action]
@@ -148,7 +159,7 @@ module ForemanMaintain::PackageManager
148
159
  )
149
160
  end
150
161
  end
151
- # rubocop:enable Metrics/LineLength, Metrics/ParameterLists
162
+ # rubocop:enable Layout/LineLength, Metrics/ParameterLists
152
163
 
153
164
  def protector_config
154
165
  File.exist?(protector_config_file) ? File.read(protector_config_file) : ''
@@ -163,14 +163,14 @@ module ForemanMaintain
163
163
  scenarios
164
164
  end
165
165
 
166
- def add_steps(steps)
167
- steps.each do |step|
166
+ def add_steps(*steps)
167
+ steps.flatten.each do |step|
168
168
  self.steps << step.ensure_instance
169
169
  end
170
170
  end
171
171
 
172
172
  def add_step(step)
173
- add_steps([step]) unless step.nil?
173
+ add_steps(step) unless step.nil?
174
174
  end
175
175
 
176
176
  def add_step_with_context(definition, extra_params = {})
@@ -0,0 +1,156 @@
1
+ module ForemanMaintain
2
+ class UpdateRunner < Runner
3
+ include Concerns::Finders
4
+
5
+ PHASES = [
6
+ :pre_update_checks,
7
+ :pre_migrations,
8
+ :migrations,
9
+ :post_migrations,
10
+ :post_update_checks,
11
+ ].freeze
12
+
13
+ attr_reader :phase
14
+
15
+ def initialize(reporter, options = {})
16
+ super(reporter, [], options)
17
+ @scenario_cache = {}
18
+ self.phase = :pre_update_checks
19
+ end
20
+
21
+ def find_scenario(phase)
22
+ return @scenario_cache[phase] if @scenario_cache.key?(phase)
23
+
24
+ condition = { :tags => [:update_scenario, phase] }
25
+ matching_scenarios = find_scenarios(condition)
26
+ @scenario_cache[phase] = matching_scenarios.first
27
+ end
28
+
29
+ def run
30
+ PHASES.each do |phase|
31
+ return run_rollback if quit?
32
+
33
+ run_phase(phase)
34
+ end
35
+
36
+ finish_update unless quit?
37
+ end
38
+
39
+ def run_rollback
40
+ # we only are able to rollback from pre_migrations phase
41
+ if phase == :pre_migrations
42
+ rollback_pre_migrations
43
+ end
44
+ end
45
+
46
+ def finish_update
47
+ @finished = true
48
+ @reporter.hline
49
+ @reporter.puts("Update finished.")
50
+ end
51
+
52
+ def storage
53
+ ForemanMaintain.storage("update")
54
+ end
55
+
56
+ # serializes the state of the run to storage
57
+ def save
58
+ if @finished
59
+ storage.delete(:serialized)
60
+ else
61
+ storage[:serialized] = to_hash
62
+ end
63
+ storage.save
64
+ end
65
+
66
+ # deserializes the state of the run from the storage
67
+ def load
68
+ return unless storage[:serialized]
69
+
70
+ load_from_hash(storage[:serialized])
71
+ end
72
+
73
+ def run_phase(phase)
74
+ scenario = find_scenario(phase)
75
+ return if scenario.nil? || scenario.steps.empty?
76
+
77
+ confirm_scenario(scenario)
78
+ return if quit?
79
+
80
+ self.phase = phase
81
+ run_scenario(scenario)
82
+ # if we started from the :pre_update_checks, ensure to ask before
83
+ # continuing with the rest of the update
84
+ @ask_to_confirm_update = phase == :pre_update_checks
85
+ end
86
+
87
+ private
88
+
89
+ def rollback_pre_migrations
90
+ raise "Unexpected phase #{phase}, expecting pre_migrations" unless phase == :pre_migrations
91
+
92
+ rollback_needed = scenario(:pre_migrations).steps.any? { |s| s.executed? && s.success? }
93
+ if rollback_needed
94
+ @quit = false
95
+ # prevent the unnecessary confirmation questions
96
+ @last_scenario = nil
97
+ @last_scenario_continuation_confirmed = true
98
+ [:post_migrations, :post_update_checks].each do |phase|
99
+ run_phase(phase)
100
+ end
101
+ end
102
+ self.phase = :pre_update_checks # rollback finished
103
+ @reporter.puts("The update failed and system was restored to pre-update state.")
104
+ end
105
+
106
+ def with_non_empty_scenario(phase)
107
+ next_scenario = scenario(phase)
108
+ unless next_scenario.nil? || next_scenario.steps.empty?
109
+ yield next_scenario
110
+ end
111
+ end
112
+
113
+ def to_hash
114
+ ret = { :phase => phase, :scenarios => {} }
115
+ @scenario_cache.each do |key, scenario|
116
+ ret[:scenarios][key] = scenario.to_hash
117
+ end
118
+ ret
119
+ end
120
+
121
+ def load_from_hash(hash)
122
+ unless @scenario_cache.empty?
123
+ raise "Some scenarios are already initialized: #{@scenario_cache.keys}"
124
+ end
125
+
126
+ self.phase = hash[:phase]
127
+ hash[:scenarios].each do |key, scenario_hash|
128
+ @scenario_cache[key] = Scenario.new_from_hash(scenario_hash)
129
+ end
130
+ end
131
+
132
+ def confirm_scenario(scenario)
133
+ decision = super(scenario)
134
+ # we have not asked the user already about next steps
135
+ if decision.nil? && @ask_to_confirm_update
136
+ response = reporter.ask_decision(<<-MESSAGE.strip_heredoc.strip)
137
+ The pre-update checks indicate that the system is ready for update.
138
+ It's recommended to perform a backup at this stage.
139
+ Confirm to continue with the modification part of the update
140
+ MESSAGE
141
+ if [:no, :quit].include?(response)
142
+ ask_to_quit
143
+ end
144
+ end
145
+ response
146
+ ensure
147
+ @ask_to_confirm_update = false
148
+ end
149
+
150
+ def phase=(phase)
151
+ raise "Unknown phase #{phase}" unless PHASES.include?(phase)
152
+
153
+ @phase = phase
154
+ end
155
+ end
156
+ end
@@ -63,6 +63,14 @@ module ForemanMaintain::Utils
63
63
  end
64
64
  end
65
65
 
66
+ def matches?(service)
67
+ if service.is_a? String
68
+ service == @name || File.fnmatch(service, @name)
69
+ else
70
+ super
71
+ end
72
+ end
73
+
66
74
  private
67
75
 
68
76
  def execute(action)
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '1.6.4'.freeze
2
+ VERSION = '1.6.5'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_maintain
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.4
4
+ version: 1.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-17 00:00:00.000000000 Z
11
+ date: 2024-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -316,6 +316,7 @@ files:
316
316
  - definitions/scenarios/restore.rb
317
317
  - definitions/scenarios/self_upgrade.rb
318
318
  - definitions/scenarios/services.rb
319
+ - definitions/scenarios/update.rb
319
320
  - definitions/scenarios/upgrade_to_capsule_6_16.rb
320
321
  - definitions/scenarios/upgrade_to_capsule_6_16_z.rb
321
322
  - definitions/scenarios/upgrade_to_foreman_nightly.rb
@@ -346,6 +347,7 @@ files:
346
347
  - lib/foreman_maintain/cli/self_upgrade_command.rb
347
348
  - lib/foreman_maintain/cli/service_command.rb
348
349
  - lib/foreman_maintain/cli/transform_clamp_options.rb
350
+ - lib/foreman_maintain/cli/update_command.rb
349
351
  - lib/foreman_maintain/cli/upgrade_command.rb
350
352
  - lib/foreman_maintain/concerns/base_database.rb
351
353
  - lib/foreman_maintain/concerns/directory_marker.rb
@@ -391,6 +393,7 @@ files:
391
393
  - lib/foreman_maintain/runner/stored_execution.rb
392
394
  - lib/foreman_maintain/scenario.rb
393
395
  - lib/foreman_maintain/top_level_modules.rb
396
+ - lib/foreman_maintain/update_runner.rb
394
397
  - lib/foreman_maintain/upgrade_runner.rb
395
398
  - lib/foreman_maintain/utils.rb
396
399
  - lib/foreman_maintain/utils/backup.rb
@@ -433,7 +436,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
433
436
  - !ruby/object:Gem::Version
434
437
  version: '0'
435
438
  requirements: []
436
- rubygems_version: 3.3.26
439
+ rubygems_version: 3.3.27
437
440
  signing_key:
438
441
  specification_version: 4
439
442
  summary: Foreman maintenance tool belt