From b2b4504300a038e1f70a8dcb62c54cf730ff34df Mon Sep 17 00:00:00 2001 From: "Eric D. Helms" Date: Fri, 31 May 2024 11:57:18 -0400 Subject: [PATCH] Fail self-upgrade if current and target version are different --- definitions/features/foreman_install.rb | 12 ++ definitions/features/satellite.rb | 4 + definitions/scenarios/self_upgrade.rb | 44 +++++-- .../scenarios/self_upgrade_test.rb | 116 +++++++++++++++--- test/definitions/test_helper.rb | 1 + 5 files changed, 149 insertions(+), 28 deletions(-) diff --git a/definitions/features/foreman_install.rb b/definitions/features/foreman_install.rb index fc50612f7..f053a5ab5 100644 --- a/definitions/features/foreman_install.rb +++ b/definitions/features/foreman_install.rb @@ -9,4 +9,16 @@ class Features::ForemanInstall < ForemanMaintain::Feature !feature(:instance).downstream && feature(:foreman_server) end end + + def target_version + '3.11' + end + + def current_version + @current_version ||= package_version(package_name) + end + + def package_name + 'foreman' + end end diff --git a/definitions/features/satellite.rb b/definitions/features/satellite.rb index 7154a51da..58777af74 100644 --- a/definitions/features/satellite.rb +++ b/definitions/features/satellite.rb @@ -10,6 +10,10 @@ class Features::Satellite < ForemanMaintain::Feature end end + def target_version + '6.16' + end + def current_version @current_version ||= package_version(package_name) || version_from_source end diff --git a/definitions/scenarios/self_upgrade.rb b/definitions/scenarios/self_upgrade.rb index 841d5876d..e20e3e98e 100644 --- a/definitions/scenarios/self_upgrade.rb +++ b/definitions/scenarios/self_upgrade.rb @@ -4,11 +4,21 @@ class SelfUpgradeBase < ForemanMaintain::Scenario include ForemanMaintain::Concerns::Versions def target_version - @target_version ||= Gem::Version.new(current_version).bump.to_s + if feature(:instance).downstream + feature(:satellite).target_version + else + feature(:foreman_install).target_version + end end def current_version - feature(:instance).downstream.current_version.to_s[/^\d+\.\d+\.\d+/] + version = if feature(:instance).downstream + feature(:instance).downstream.current_version + else + feature(:instance).foreman_install.current_version + end + + version.to_s[/^\d+\.\d+\.\d+/] end def maintenance_repo_label @@ -47,12 +57,12 @@ def req_repos_to_update_pkgs end end - def upstream_target_version - if feature(:katello_install) - return foreman_version_by_katello(target_version) - else - target_version - end + def upgrade_allowed? + Gem::Version.new(current_version) == Gem::Version.new(target_version) + end + + def version_difference + ((Gem::Version.new(target_version).version.to_f - current_version.to_f).round(2) * 100).to_i end end @@ -65,6 +75,22 @@ class SelfUpgrade < SelfUpgradeBase end def downstream_self_upgrade(pkgs_to_update) + unless upgrade_allowed? + if version_difference > 1 + raise( + ForemanMaintain::Error::Warn, + "foreman-maintain is too many versions ahead, given the" \ + "target version is #{target_version}. Please rollback " \ + "foreman-maintain to the proper version." + ) + else + raise( + ForemanMaintain::Error::Warn, + "self-upgrade has already been executed, and is ready to upgrade to #{target_version}" + ) + end + end + ForemanMaintain.enable_maintenance_module add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true, @@ -77,7 +103,7 @@ def upstream_self_upgrade(pkgs_to_update) # 2. Update the foreman-maintain packages from next major version repository # 3. Rollback the repository to current major version - add_step(Procedures::Repositories::Setup.new(:version => upstream_target_version)) + add_step(Procedures::Repositories::Setup.new(:version => target_version)) add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true)) ensure rollback_repositories diff --git a/test/definitions/scenarios/self_upgrade_test.rb b/test/definitions/scenarios/self_upgrade_test.rb index 3276530f5..302727505 100644 --- a/test/definitions/scenarios/self_upgrade_test.rb +++ b/test/definitions/scenarios/self_upgrade_test.rb @@ -1,29 +1,107 @@ require 'test_helper' +require_relative '../test_helper' +require_relative '../../../definitions/scenarios/self_upgrade' -module Scenarios - describe ForemanMaintain::Scenarios::SelfUpgradeBase do - include DefinitionsTestHelper +describe ForemanMaintain::Scenarios::SelfUpgradeBase do + include ::DefinitionsTestHelper - describe 'with default params' do - let(:scenario) do - ForemanMaintain::Scenarios::SelfUpgradeBase.new - end + before do + ForemanMaintain.stubs(:el?).returns(true) + end + + let(:scenario) do + ForemanMaintain::Scenarios::SelfUpgradeBase.new + end + + it 'computes the target version correctly for downstream' do + assume_satellite_present + + assert_equal '6.16', scenario.target_version + end + + it 'returns target version correctly for upstream' do + assume_feature_present(:foreman_install) - it 'computes the target version correctly coming from normal release 6.10.0' do - assume_satellite_present do |feature_class| - feature_class.any_instance.stubs(:current_version => version('6.10.0')) - end + assert_equal '3.11', scenario.target_version + end + + it 'allow upgrade when versions are equal' do + assume_satellite_present + scenario.expects(:current_version).returns('6.16') + scenario.expects(:target_version).returns('6.16') + + assert scenario.upgrade_allowed? + end + + it 'does not allow upgrade when versions are off by 1' do + assume_satellite_present + scenario.expects(:current_version).returns('6.15') + scenario.expects(:target_version).returns('6.16') + + refute scenario.upgrade_allowed? + end - assert_equal '6.11', scenario.target_version - end + it 'does not allow upgrade when versions are off by 2 or more' do + assume_satellite_present + scenario.expects(:current_version).returns('6.14') + scenario.expects(:target_version).returns('6.16') + + refute scenario.upgrade_allowed? + end +end + +describe ForemanMaintain::Scenarios::SelfUpgrade do + include ::DefinitionsTestHelper + + before do + ForemanMaintain::Concerns::OsFacts.stubs(:el?).returns(true) + end + + it 'runs successfully for downstream' do + ForemanMaintain. + package_manager. + expects(:find_installed_package). + with('satellite', "%{VERSION}"). + returns('6.16.0') + assume_feature_present(:satellite) + scenario = ForemanMaintain::Scenarios::SelfUpgrade.new + scenario.expects(:target_version).twice.returns('6.16') + scenario.compose + + assert run_step(scenario) + end + + it 'fails if versions are off 1' do + ForemanMaintain. + package_manager. + expects(:find_installed_package). + with('satellite', "%{VERSION}"). + returns('6.15.0') + assume_feature_present(:satellite) + + msg = "self-upgrade has already been executed, and is ready to upgrade to 6.16" + assert_raises(ForemanMaintain::Error::Warn, msg) do + scenario = ForemanMaintain::Scenarios::SelfUpgrade.new + scenario.expects(:target_version).twice.returns('6.16') + scenario.compose + end + end - it 'computes the target version correctly coming from an async release 6.11.1.1' do - assume_satellite_present do |feature_class| - feature_class.any_instance.stubs(:current_version => version('6.11.1.1')) - end + it 'fails if versions are off 2 or more' do + ForemanMaintain. + package_manager. + expects(:find_installed_package). + with('satellite', "%{VERSION}"). + returns('6.14.0') + assume_feature_present(:satellite) - assert_equal '6.12', scenario.target_version - end + msg = "foreman-maintain is too many versions ahead, given the " \ + "target version is 6.16. Please rollback foreman-maintain " \ + "to the proper version." + assert_raises(ForemanMaintain::Error::Warn, msg) do + scenario = ForemanMaintain::Scenarios::SelfUpgrade.new + scenario.expects(:target_version).twice.returns('6.16') + scenario.compose end end end diff --git a/test/definitions/test_helper.rb b/test/definitions/test_helper.rb index 000d09ff5..c4fd85cbd 100644 --- a/test/definitions/test_helper.rb +++ b/test/definitions/test_helper.rb @@ -1,5 +1,6 @@ require File.expand_path('../test_helper', File.dirname(__FILE__)) require File.expand_path('assume_feature_dependencies_helper', File.dirname(__FILE__)) + module DefinitionsTestHelper include ForemanMaintain::Concerns::Finders include ForemanMaintain::Concerns::SystemService