Skip to content

Commit

Permalink
Add actor to verify if target version is supported
Browse files Browse the repository at this point in the history
If the target version is unsupported, the actor will invoke an
inhibitor. Allow setting the environment variable
`LEAPP_UNSUPPORTED=1` to bypass this check.

* Add tests for actor

Remove old target check implementations:
* Choice check from '--target' argument which invoked error from both
  pre-upgrade and upgrade.
* Unsupported target check from the 'command_utils' library,.

Resolves: RHEL-51072
  • Loading branch information
tomasfratrik committed Jan 15, 2025
1 parent d183370 commit 4cbe76c
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 12 deletions.
8 changes: 0 additions & 8 deletions commands/command_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ def vet_upgrade_path(args):
Make sure the user requested upgrade_path is a supported one.
If LEAPP_DEVEL_TARGET_RELEASE is set then it's value is not vetted against upgrade_paths_map but used as is.
:raises: `CommandError` if the specified upgrade_path is not supported
:return: `tuple` (target_release, flavor)
"""
flavor = get_upgrade_flavour()
Expand All @@ -135,13 +134,6 @@ def vet_upgrade_path(args):
check_version(env_version_override)
return (env_version_override, flavor)
target_release = args.target or get_target_version(flavor)
supported_target_versions = get_supported_target_versions(flavor)
if target_release not in supported_target_versions:
raise CommandError(
"Upgrade to {to} for {flavor} upgrade path is not supported, possible choices are {choices}".format(
to=target_release,
flavor=flavor,
choices=','.join(supported_target_versions)))
return (target_release, flavor)


Expand Down
3 changes: 1 addition & 2 deletions commands/preupgrade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
choices=['ga', 'e4s', 'eus', 'aus'],
value_type=str.lower) # This allows the choices to be case insensitive
@command_opt('iso', help='Use provided target RHEL installation image to perform the in-place upgrade.')
@command_opt('target', choices=command_utils.get_supported_target_versions(),
help='Specify RHEL version to upgrade to for {} detected upgrade flavour'.format(
@command_opt('target', help='Specify RHEL version to upgrade to for {} detected upgrade flavour'.format(
command_utils.get_upgrade_flavour()))
@command_opt('report-schema', help='Specify report schema version for leapp-report.json',
choices=['1.0.0', '1.1.0', '1.2.0'], default=get_config().get('report', 'schema'))
Expand Down
3 changes: 1 addition & 2 deletions commands/upgrade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
choices=['ga', 'e4s', 'eus', 'aus'],
value_type=str.lower) # This allows the choices to be case insensitive
@command_opt('iso', help='Use provided target RHEL installation image to perform the in-place upgrade.')
@command_opt('target', choices=command_utils.get_supported_target_versions(),
help='Specify RHEL version to upgrade to for {} detected upgrade flavour'.format(
@command_opt('target', help='Specify RHEL version to upgrade to for {} detected upgrade flavour'.format(
command_utils.get_upgrade_flavour()))
@command_opt('report-schema', help='Specify report schema version for leapp-report.json',
choices=['1.0.0', '1.1.0', '1.2.0'], default=get_config().get('report', 'schema'))
Expand Down
21 changes: 21 additions & 0 deletions repos/system_upgrade/common/actors/verifytargetversion/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from leapp.actors import Actor
from leapp.libraries.actor import verifytargetversion
from leapp.models import Report
from leapp.tags import FactsPhaseTag, IPUWorkflowTag


class VerifyTargetVersion(Actor):
"""
Verify if the target system version is supported by the upgrade process.
Invoke inhibitor if the target system is not supported.
Allow unsupported target if `LEAPP_UNSUPPORTED=1` is set.
"""

name = 'verify_target_version'
consumes = ()
produces = (Report,)
tags = (FactsPhaseTag, IPUWorkflowTag)

def process(self):
verifytargetversion.process()
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os

from leapp import reporting
from leapp.cli.commands import command_utils
from leapp.exceptions import StopActorExecution
from leapp.libraries.stdlib import api

FMT_LIST_SEPARATOR = '\n - '


def process():
flavour = os.environ.get('LEAPP_UPGRADE_PATH_FLAVOUR')
target_version = os.environ.get('LEAPP_UPGRADE_PATH_TARGET_RELEASE')
supported_target_versions = command_utils.get_supported_target_versions(flavour)

unsupported = target_version not in supported_target_versions and os.environ.get('LEAPP_UNSUPPORTED') != '1'

if unsupported:
hint = (
'Upgrade to a supported version\n'
'Supported target versions for your source version are: {sep}{ver}\n'
'Alternatively, if you want to upgrade to an unsupported version, '
'set the `LEAPP_UNSUPPORTED=1` environment variable.'
.format(sep=FMT_LIST_SEPARATOR, ver=FMT_LIST_SEPARATOR.join(supported_target_versions))
)

reporting.create_report([
reporting.Title('Target version is not supported'),
reporting.Summary(
'You are trying to upgrade to an unsupported target\n'
'Those are the targets without EUS (Extended Update Support)'
),
reporting.Groups([reporting.Groups.INHIBITOR]),
reporting.Severity(reporting.Severity.HIGH),
reporting.Remediation(hint=hint),
reporting.ExternalLink(
url='https://access.redhat.com/articles/4263361',
title='Learn more about supported in-place upgrade paths'
)
])
raise StopActorExecution()
api.current_logger().info('Target version is supported')
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import pytest

from leapp import reporting
from leapp.cli.commands import command_utils
from leapp.exceptions import StopActorExecution
from leapp.libraries.actor import verifytargetversion
from leapp.libraries.common.testutils import create_report_mocked, logger_mocked
from leapp.libraries.stdlib import api

upgrade_paths = {
"7.9": ["8.10"],
"8.10": ["9.4", "9.5", "9.6"],
"9.6": ["10.0"],
"7": ["8.10"],
"8": ["9.4", "9.5", "9.6"],
"9": ["10.0"]
}


def _get_supported_target_versions(source_version):
return upgrade_paths.get(source_version, [])


@pytest.fixture
def setup_monkeypatch(monkeypatch):
"""Fixture to set up common monkeypatches."""

def _setup(source_version, target_version, leapp_unsupported="0"):
monkeypatch.setenv('LEAPP_UPGRADE_PATH_FLAVOUR', 'default')
monkeypatch.setenv('LEAPP_UPGRADE_PATH_TARGET_RELEASE', target_version)
monkeypatch.setenv('LEAPP_UNSUPPORTED', leapp_unsupported)
monkeypatch.setattr(command_utils, 'get_supported_target_versions',
lambda flavour: _get_supported_target_versions(source_version))
monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(api, 'current_logger', logger_mocked())
return _setup


@pytest.mark.parametrize("source_version, target_version, leapp_unsupported", [
# LEAPP_UNSUPPORTED=0
("7.9", "9.0", "0"),
("8.10", "9.0", "0"),
("9.6", "10.1", "0"),
("7", "9.0", "0"),
("8", "9.0", "0"),
("9", "10.1", "0"),
# LEAPP_UNSUPPORTED=1
("7.9", "9.0", "1"),
("8.10", "9.0", "1"),
("9.6", "10.1", "1"),
("7", "9.0", "1"),
("8", "9.0", "1"),
("9", "10.1", "1"),
])
def test_unsuppoted_paths(setup_monkeypatch, source_version, target_version, leapp_unsupported):
setup_monkeypatch(source_version, target_version, leapp_unsupported)

if leapp_unsupported == "1":
verifytargetversion.process()
assert reporting.create_report.called == 0
assert api.current_logger.infomsg == ['Target version is supported']
else:
with pytest.raises(StopActorExecution):
verifytargetversion.process()
assert reporting.create_report.called == 1
assert 'Target version is not supported' in reporting.create_report.report_fields['title']
assert 'You are trying to upgrade ' in reporting.create_report.report_fields['summary']
assert 'inhibitor' in reporting.create_report.report_fields['groups']


@pytest.mark.parametrize("source_version, target_version", [
("7.9", "8.10"),
("8.10", "9.4"),
("8.10", "9.5"),
("8.10", "9.6"),
("9.6", "10.0"),
("7", "8.10"),
("8", "9.4"),
("8", "9.5"),
("8", "9.6"),
("9", "10.0"),
])
def test_supported_paths(setup_monkeypatch, source_version, target_version):
setup_monkeypatch(source_version, target_version, leapp_unsupported="0")

verifytargetversion.process()
assert reporting.create_report.called == 0
assert api.current_logger.infomsg == ['Target version is supported']

0 comments on commit 4cbe76c

Please sign in to comment.