From 2066b4c7a2b769754beb9c3af2fc8407b72aa5fd Mon Sep 17 00:00:00 2001 From: Yuriy Kohut Date: Fri, 10 Oct 2025 14:16:21 +0300 Subject: [PATCH] Update Vendors patch against upstream e749dbc430099ac0d0cb06fb9dff4ec458d359b3 (0.23.0-1) The package version 0.23.0-1.elevate.3 --- SOURCES/leapp-repository-0.23.0-elevate.patch | 2033 ++++++++++++++++- SPECS/leapp-repository.spec | 5 +- 2 files changed, 2022 insertions(+), 16 deletions(-) diff --git a/SOURCES/leapp-repository-0.23.0-elevate.patch b/SOURCES/leapp-repository-0.23.0-elevate.patch index 666d54e..388fa23 100644 --- a/SOURCES/leapp-repository-0.23.0-elevate.patch +++ b/SOURCES/leapp-repository-0.23.0-elevate.patch @@ -1,3 +1,95 @@ +diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml +index 3e595e32..4b07e4b3 100644 +--- a/.github/workflows/codespell.yml ++++ b/.github/workflows/codespell.yml +@@ -14,7 +14,7 @@ jobs: + runs-on: ubuntu-latest + + steps: +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + - uses: codespell-project/actions-codespell@v2 + with: + ignore_words_list: ro,fo,couldn,repositor,zeor,bootup +diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml +index e1bafb93..6c81713c 100644 +--- a/.github/workflows/differential-shellcheck.yml ++++ b/.github/workflows/differential-shellcheck.yml +@@ -19,7 +19,7 @@ jobs: + + steps: + - name: Repository checkout +- uses: actions/checkout@v4 ++ uses: actions/checkout@v5 + with: + fetch-depth: 0 + +diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml +index ed82e0e5..d1b8fb2a 100644 +--- a/.github/workflows/unit-tests.yml ++++ b/.github/workflows/unit-tests.yml +@@ -19,40 +19,40 @@ jobs: + - name: 'Unit tests (python:3.12; repos:el9toel10,common)' + python: python3.12 + repos: 'el9toel10,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.12; repos:el9toel10,common)' + python: python3.12 + repos: 'el9toel10,common' +- container: ubi9-lint ++ container: el9-lint + - name: 'Unit tests (python:3.9; repos:el9toel10,common)' + python: python3.9 + repos: 'el9toel10,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.9; repos:el9toel10,common)' + python: python3.9 + repos: 'el9toel10,common' +- container: ubi9-lint ++ container: el9-lint + # 8to9 + - name: 'Unit tests (python:3.9; repos:el8toel9,common)' + python: python3.9 + repos: 'el8toel9,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.9; repos:el8toel9,common)' + python: python3.9 + repos: 'el8toel9,common' +- container: ubi9-lint ++ container: el9-lint + - name: 'Unit tests (python:3.6; repos:el8toel9,common)' + python: python3.6 + repos: 'el8toel9,common' +- container: ubi8 ++ container: el8 + - name: 'Linters (python:3.6; repos:el8toel9,common)' + python: python3.6 + repos: 'el8toel9,common' +- container: ubi8-lint ++ container: el8-lint + + steps: + - name: Checkout code +- uses: actions/checkout@v4 ++ uses: actions/checkout@v5 + with: + # NOTE(ivasilev) fetch-depth 0 is critical here as leapp deps discovery depends on specific substring in + # commit message and default 1 option will get us just merge commit which has an unrelevant message. +@@ -63,4 +63,10 @@ jobs: + run: | + git branch -f main origin/main + - name: ${{matrix.scenarios.name}} +- run: script -e -c /bin/bash -c 'TERM=xterm podman build --security-opt=seccomp=unconfined -t leapp-tests -f utils/container-tests/Containerfile.${{matrix.scenarios.container}} utils/container-tests && PYTHON_VENV=${{matrix.scenarios.python}} REPOSITORIES=${{matrix.scenarios.repos}} podman run --security-opt=seccomp=unconfined --rm -ti -v ${PWD}:/payload --env=PYTHON_VENV --env=REPOSITORIES leapp-tests' ++ run: | ++ script -e -c /bin/bash -c \ ++ 'TERM=xterm \ ++ podman build -t leapp-tests -f utils/container-tests/ci/Containerfile.${{matrix.scenarios.container}} . && \ ++ PYTHON_VENV=${{matrix.scenarios.python}} \ ++ REPOSITORIES=${{matrix.scenarios.repos}} \ ++ podman run --rm -ti -v ${PWD}:/payload --env=PYTHON_VENV --env=REPOSITORIES leapp-tests' diff --git a/.gitignore b/.gitignore index 0bb92d3d..a04c7ded 100644 --- a/.gitignore @@ -10,6 +102,265 @@ index 0bb92d3d..a04c7ded 100644 # pycharm .idea +diff --git a/.packit.yaml b/.packit.yaml +index 607dff93..3d1cd7ff 100644 +--- a/.packit.yaml ++++ b/.packit.yaml +@@ -155,7 +155,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -182,7 +182,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -209,7 +209,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -232,7 +232,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -258,7 +258,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -284,7 +284,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -306,7 +306,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -332,7 +332,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -358,7 +358,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -434,7 +434,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:9to10 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -463,7 +463,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -489,7 +489,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -514,7 +514,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:9to10 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -543,7 +543,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +@@ -572,7 +572,7 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: + context: +diff --git a/Makefile b/Makefile +index 81b16376..754c2c63 100644 +--- a/Makefile ++++ b/Makefile +@@ -51,7 +51,7 @@ _COPR_CONFIG=$${COPR_CONFIG:-~/.config/copr_rh_oamg.conf} + _CONTAINER_TOOL=$${CONTAINER_TOOL:-podman} + + # container to run tests in +-_TEST_CONTAINER=$${TEST_CONTAINER:-rhel8} ++_TEST_CONTAINER=$${TEST_CONTAINER:-el8} + + # In case just specific CHROOTs should be used for the COPR build, you can + # set the multiple CHROOTs separated by comma in the COPR_CHROOT envar, e.g. +@@ -129,7 +129,7 @@ help: + @echo " test lint source code and run tests" + @echo " test_no_lint run tests without linting the source code" + @echo " test_container run lint and tests in container" +- @echo " - default container is 'rhel8'" ++ @echo " - default container is 'el8'" + @echo " - can be changed by setting TEST_CONTAINER env" + @echo " test_container_all run lint and tests in all available containers" + @echo " test_container_no_lint run tests without linting in container, see test_container" +@@ -164,9 +164,9 @@ help: + @echo " PR=7 SUFFIX='my_additional_suffix' make " + @echo " MR=6 COPR_CONFIG='path/to/the/config/copr/file' make " + @echo " ACTOR= TEST_LIBS=y make test" +- @echo " BUILD_CONTAINER=rhel8 make build_container" +- @echo " TEST_CONTAINER=f34 make test_container" +- @echo " CONTAINER_TOOL=docker TEST_CONTAINER=rhel8 make test_container_no_lint" ++ @echo " BUILD_CONTAINER=el8 make build_container" ++ @echo " TEST_CONTAINER=f42 make test_container" ++ @echo " CONTAINER_TOOL=docker TEST_CONTAINER=el8 make test_container_no_lint" + @echo "" + + clean: +@@ -252,10 +252,10 @@ build_container: + echo "--- Build RPM ${PKGNAME}-${VERSION}-${RELEASE}.el$(DIST_VERSION).rpm in container ---"; + case "$(BUILD_CONTAINER)" in \ + el8) \ +- CONT_FILE="utils/container-builds/Containerfile.ubi8"; \ ++ CONT_FILE="utils/container-builds/Containerfile.el8"; \ + ;; \ + el9) \ +- CONT_FILE="utils/container-builds/Containerfile.ubi9"; \ ++ CONT_FILE="utils/container-builds/Containerfile.el9"; \ + ;; \ + "") \ + echo "BUILD_CONTAINER must be set"; \ +@@ -379,7 +379,6 @@ test_no_lint: + done; \ + $(_PYTHON_VENV) -m pytest $(REPORT_ARG) $(TEST_PATHS) $(LIBRARY_PATH) $(PYTEST_ARGS) + +- + test: lint test_no_lint + + # container images act like a cache so that dependencies can only be downloaded once +@@ -416,7 +415,7 @@ lint_container: + @_TEST_CONT_TARGET="lint" $(MAKE) test_container + + lint_container_all: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in f42 el{8,9}; do \ + TEST_CONTAINER=$$container $(MAKE) lint_container || exit 1; \ + done + +@@ -426,20 +425,20 @@ lint_container_all: + # because e.g RHEL8 to RHEL9 IPU must work on python3.6 and python3.9. + test_container: + @case $(_TEST_CONTAINER) in \ +- f34) \ +- export CONT_FILE="utils/container-tests/Containerfile.f34"; \ +- export _VENV="python3.9"; \ ++ f42) \ ++ export CONT_FILE="utils/container-tests/Containerfile.f42"; \ ++ export _VENV="python3.13"; \ + ;; \ +- rhel8) \ +- export CONT_FILE="utils/container-tests/Containerfile.rhel8"; \ ++ el8) \ ++ export CONT_FILE="utils/container-tests/Containerfile.el8"; \ + export _VENV="python3.6"; \ + ;; \ +- rhel9) \ +- export CONT_FILE="utils/container-tests/Containerfile.rhel9"; \ ++ el9) \ ++ export CONT_FILE="utils/container-tests/Containerfile.el9"; \ + export _VENV="python3.9"; \ + ;; \ + *) \ +- echo "Error: Available containers are: f34, rhel8, rhel9"; exit 1; \ ++ echo "Error: Available containers are: f42, el8, el9"; exit 1; \ + ;; \ + esac; \ + export TEST_IMAGE="leapp-repo-tests-$(_TEST_CONTAINER)"; \ +@@ -471,7 +470,7 @@ test_container: + exit $$res + + test_container_all: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in "f42" "el8" "el9"; do \ + TEST_CONTAINER=$$container $(MAKE) test_container || exit 1; \ + done + +@@ -479,14 +478,13 @@ test_container_no_lint: + @_TEST_CONT_TARGET="test_no_lint" $(MAKE) test_container + + test_container_all_no_lint: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in f42 el{8,9}; do \ + TEST_CONTAINER=$$container $(MAKE) test_container_no_lint || exit 1; \ + done + + # clean all testing and building containers and their images + clean_containers: +- @for i in "leapp-repo-tests-f34" "leapp-repo-tests-rhel8" \ +- "leapp-repo-tests-rhel9" "leapp-repo-build-el8"; do \ ++ @for i in leapp-repo-tests-f42 leapp-repo-tests-el{8,9} leapp-repo-build-el{8,9}; do \ + $(_CONTAINER_TOOL) kill "$$i-cont" || :; \ + $(_CONTAINER_TOOL) rm "$$i-cont" || :; \ + $(_CONTAINER_TOOL) rmi "$$i" || :; \ diff --git a/ci/.gitignore b/ci/.gitignore new file mode 100644 index 00000000..e6f97f0f @@ -3421,6 +3772,22 @@ index 00000000..370758e6 + end + end +end +diff --git a/commands/tests/test_upgrade_paths.py b/commands/tests/test_upgrade_paths.py +index 89b5eb71..9bdf5792 100644 +--- a/commands/tests/test_upgrade_paths.py ++++ b/commands/tests/test_upgrade_paths.py +@@ -42,6 +42,11 @@ def test_get_target_version(mock_open, monkeypatch): + }, + ) + def test_get_target_release(mock_open, monkeypatch): # do not remove mock_open ++ # Make it look like it's RHEL even on centos, because that's what the test ++ # assumes. ++ # Otherwise the test, when ran on Centos, fails because it works ++ # with MAJOR.MINOR version format while Centos uses MAJOR format. ++ monkeypatch.setattr(command_utils, 'get_distro_id', lambda: 'rhel') + monkeypatch.setattr(command_utils, 'get_os_release_version_id', lambda x: '8.6') + + # make sure env var LEAPP_DEVEL_TARGET_RELEASE takes precedence diff --git a/etc/leapp/transaction/to_reinstall b/etc/leapp/transaction/to_reinstall new file mode 100644 index 00000000..c6694a8e @@ -3624,6 +3991,197 @@ index 00000000..52f5af9d + api.produce(ActiveVendorList(data=list(active_vendors))) + else: + self.log.info("No active vendors found, vendor list not generated") +diff --git a/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py b/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py +index 57a94e9d..d52b9e73 100644 +--- a/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py ++++ b/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py +@@ -3,6 +3,7 @@ from leapp.libraries.common.config.version import get_source_major_version + from leapp.libraries.stdlib import api + from leapp.models import ( + CephInfo, ++ CopyFile, + DracutModule, + LuksDumps, + StorageInfo, +@@ -156,8 +157,13 @@ def check_invalid_luks_devices(): + 'tpm2-tools', + 'tpm2-abrmd' + ] +- api.produce(TargetUserSpaceUpgradeTasks(install_rpms=required_crypt_rpms)) +- api.produce(UpgradeInitramfsTasks(include_dracut_modules=[ ++ api.produce(TargetUserSpaceUpgradeTasks( ++ copy_files=[CopyFile(src="/etc/crypttab")], ++ install_rpms=required_crypt_rpms) ++ ) ++ api.produce(UpgradeInitramfsTasks( ++ include_files=['/etc/crypttab'], ++ include_dracut_modules=[ + DracutModule(name='clevis'), + DracutModule(name='clevis-pin-tpm2') + ]) +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/actor.py b/repos/system_upgrade/common/actors/checktargetrepos/actor.py +index d61fb685..a5bdde10 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/actor.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/actor.py +@@ -6,7 +6,9 @@ from leapp.tags import ChecksPhaseTag, IPUWorkflowTag + + class Checktargetrepos(Actor): + """ +- Check whether target yum repositories are specified. ++ Check whether target dnf repositories are specified on RHEL. ++ ++ NOTE: this actor does nothing on distros other than RHEL. + + RHSM | RHUI | ER | CTR | CTRF || result + -----+------+----+-----+------++------- +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py b/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py +index c286ed4f..ea21e1de 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py +@@ -2,12 +2,14 @@ from leapp import reporting + from leapp.libraries.common import config, rhsm + from leapp.libraries.common.config.version import get_target_major_version + from leapp.libraries.stdlib import api +-from leapp.models import CustomTargetRepositoryFile, RHUIInfo, TargetRepositories ++from leapp.models import CustomTargetRepositoryFile, RHELTargetRepository, RHUIInfo, TargetRepositories ++from leapp.utils.deprecation import suppress_deprecation + + # TODO: we need to provide this path in a shared library + CUSTOM_REPO_PATH = '/etc/leapp/files/leapp_upgrade_repositories.repo' + + ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + def _any_custom_repo_defined(): + for tr in api.consume(TargetRepositories): + if tr.custom_repos: +@@ -38,9 +40,10 @@ def process(): + + rhui_info = next(api.consume(RHUIInfo), None) + +- if not rhsm.skip_rhsm() or rhui_info: +- # getting RH repositories through RHSM or RHUI; resolved by seatbelts +- # implemented in other actors ++ if config.get_distro_id() != 'rhel' or (not rhsm.skip_rhsm() or rhui_info): ++ # RHEL: getting RH repositories through RHSM or RHUI; ++ # resolved by seatbelts in other actors ++ # other: distro repos provided by the distro directly, seatbelts elsewhere + return + + # rhsm skipped; take your seatbelts please +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py b/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py +index c1ca8cd1..e055b3a6 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py +@@ -8,12 +8,11 @@ from leapp.libraries.stdlib import api + from leapp.models import ( + CustomTargetRepository, + CustomTargetRepositoryFile, +- EnvVar, +- Report, +- RepositoryData, ++ DistroTargetRepository, + RHELTargetRepository, + TargetRepositories + ) ++from leapp.utils.deprecation import suppress_deprecation + from leapp.utils.report import is_inhibitor + + +@@ -32,11 +31,21 @@ class MockedConsume(object): + return iter([msg for msg in self._msgs if isinstance(msg, model)]) + + +-_RHEL_REPOS = [ +- RHELTargetRepository(repoid='repo1'), +- RHELTargetRepository(repoid='repo2'), +- RHELTargetRepository(repoid='repo3'), +- RHELTargetRepository(repoid='repo4'), ++@suppress_deprecation(RHELTargetRepository) ++def _test_rhel_repos(): ++ return [ ++ RHELTargetRepository(repoid='repo1'), ++ RHELTargetRepository(repoid='repo2'), ++ RHELTargetRepository(repoid='repo3'), ++ RHELTargetRepository(repoid='repo4'), ++ ] ++ ++ ++_DISTRO_REPOS = [ ++ DistroTargetRepository(repoid='repo1'), ++ DistroTargetRepository(repoid='repo2'), ++ DistroTargetRepository(repoid='repo3'), ++ DistroTargetRepository(repoid='repo4'), + ] + + _CUSTOM_REPOS = [ +@@ -46,16 +55,17 @@ _CUSTOM_REPOS = [ + CustomTargetRepository(repoid='repo4', name='repo4name', baseurl=None, enabled=True), + ] + +-_TARGET_REPOS_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS, custom_repos=_CUSTOM_REPOS) +-_TARGET_REPOS_NO_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS) ++_TARGET_REPOS_CUSTOM = TargetRepositories( ++ rhel_repos=_test_rhel_repos(), distro_repos=_DISTRO_REPOS, custom_repos=_CUSTOM_REPOS ++) ++_TARGET_REPOS_NO_CUSTOM = TargetRepositories(rhel_repos=_test_rhel_repos(), distro_repos=_DISTRO_REPOS) + _CUSTOM_TARGET_REPOFILE = CustomTargetRepositoryFile(file='/etc/leapp/files/leapp_upgrade_repositories.repo') + + + def test_checktargetrepos_rhsm(monkeypatch): + monkeypatch.setattr(reporting, 'create_report', create_report_mocked()) + monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: False) +- monkeypatch.setattr(api, 'consume', MockedConsume()) +- monkeypatch.setattr(checktargetrepos, 'get_target_major_version', lambda: '8') ++ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked()) + checktargetrepos.process() + assert reporting.create_report.called == 0 + +diff --git a/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py b/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py +index ea154173..5dcdd967 100644 +--- a/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py ++++ b/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py +@@ -22,6 +22,7 @@ from leapp.models import ( + CustomTargetRepository, + DNFPluginTask, + InstalledRPM, ++ RHELTargetRepository, + RHUIInfo, + RpmTransactionTasks, + TargetRepositories, +@@ -30,6 +31,7 @@ from leapp.models import ( + TargetRHUISetupInfo, + TargetUserSpacePreupgradeTasks + ) ++from leapp.utils.deprecation import suppress_deprecation + + MatchingSetup = namedtuple('MatchingSetup', ['family', 'description']) + +@@ -370,11 +372,12 @@ def emit_rhui_setup_tasks_based_on_config(rhui_config_dict): + api.produce(rhui_info) + + ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + def request_configured_repos_to_be_enabled(rhui_config): + config_repos_to_enable = rhui_config[RhuiTargetRepositoriesToUse.name] + custom_repos = [CustomTargetRepository(repoid=repoid) for repoid in config_repos_to_enable] + if custom_repos: +- target_repos = TargetRepositories(custom_repos=custom_repos, rhel_repos=[]) ++ target_repos = TargetRepositories(custom_repos=custom_repos, rhel_repos=[], distro_repos=[]) + api.produce(target_repos) + + +diff --git a/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py b/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py +index 3ac9c1b8..02ca352e 100644 +--- a/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py ++++ b/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py +@@ -468,6 +468,7 @@ def test_request_configured_repos_to_be_enabled(monkeypatch): + + target_repos = api.produce.model_instances[0] + assert isinstance(target_repos, TargetRepositories) ++ assert not target_repos.distro_repos + assert not target_repos.rhel_repos + + custom_repoids = sorted(custom_repo_model.repoid for custom_repo_model in target_repos.custom_repos) diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh index 56a94b5d..46c5d9b6 100755 --- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh @@ -3844,6 +4402,19 @@ index 366b5cab..d2bf7313 100644 -After=basic.target sysroot.mount +After=basic.target sysroot.mount initrd-fs.target AllowIsolate=yes +diff --git a/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py b/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py +index 5302cdd2..c1cefc37 100644 +--- a/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py ++++ b/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py +@@ -6,7 +6,7 @@ import pytest + + @pytest.mark.skipif(os.getuid() != 0, reason='User is not a root') + @pytest.mark.skipif( +- distro.linux_distribution()[0] == 'Fedora', ++ distro.id() == 'fedora', + reason='default.target.wants does not exists on Fedora distro', + ) + def test_create_resume_service(current_actor_context): diff --git a/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py b/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py index 003f3fc5..9e7bbf4a 100644 --- a/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py @@ -4774,6 +5345,20 @@ index 00000000..b814f6ce + ] + assert sorted(files) == sorted(expected_files) + assert mount_unit_generator._delete_file.removal_called +diff --git a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py +index 02c3fd9d..3ad92167 100644 +--- a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py ++++ b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py +@@ -436,6 +436,9 @@ def _generate_livemode_initramfs(context, userspace_initramfs_dest, target_kerne + '--lvmconf', '--mdadmconf', + '--kver', target_kernel_ver, '-f', userspace_initramfs_dest] + ++ # Add included files ++ cmd.extend(itertools.chain(*(('--install', file) for file in initramfs_includes.files))) ++ + # Add dracut modules + cmd.extend(itertools.chain(*(('--add', module) for module in dracut_modules))) + diff --git a/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py b/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py index 32e4527b..1e595e9a 100644 --- a/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py @@ -5638,18 +6223,23 @@ index 91855818..3a7e955b 100644 tags = (IPUWorkflowTag, FactsPhaseTag) diff --git a/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos.py b/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos.py -index a6073aa3..dfa565c1 100644 +index a6073aa3..afffb2b8 100644 --- a/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos.py +++ b/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos.py -@@ -1,6 +1,7 @@ - +@@ -1,9 +1,11 @@ +- from leapp.libraries.actor import setuptargetrepos_repomap ++from leapp.libraries.common.config import get_distro_id from leapp.libraries.common.config.version import get_source_major_version, get_source_version, get_target_version +from leapp.libraries.common.repomaputils import combine_repomap_messages from leapp.libraries.stdlib import api from leapp.models import ( CustomTargetRepository, -@@ -13,7 +14,8 @@ from leapp.models import ( ++ DistroTargetRepository, + InstalledRPM, + RepositoriesBlacklisted, + RepositoriesFacts, +@@ -13,8 +15,10 @@ from leapp.models import ( RHUIInfo, SkippedRepositories, TargetRepositories, @@ -5657,9 +6247,11 @@ index a6073aa3..dfa565c1 100644 + UsedRepositories, + VendorCustomTargetRepositoryList ) ++from leapp.utils.deprecation import suppress_deprecation RHUI_CLIENT_REPOIDS_RHEL88_TO_RHEL810 = { -@@ -80,13 +82,62 @@ def _get_mapped_repoids(repomap, src_repoids): + 'rhui-microsoft-azure-rhel8-sapapps': 'rhui-microsoft-azure-rhel8-base-sap-apps', +@@ -80,13 +84,63 @@ def _get_mapped_repoids(repomap, src_repoids): return mapped_repoids @@ -5702,6 +6294,7 @@ index a6073aa3..dfa565c1 100644 + return result + + ++@suppress_deprecation(RHELTargetRepository) def process(): # Load relevant data from messages used_repoids_dict = _get_used_repo_dict() @@ -5722,7 +6315,67 @@ index a6073aa3..dfa565c1 100644 # Setup repomap handler repo_mappig_msg = next(api.consume(RepositoriesMapping), RepositoriesMapping()) -@@ -168,6 +219,10 @@ def process(): +@@ -103,10 +157,11 @@ def process(): + # installed packages that have mapping to prevent missing repositories that are disabled during the upgrade, but + # can be used to upgrade installed packages. + repoids_to_map = enabled_repoids.union(repoids_from_installed_packages_with_mapping) ++ is_rhel = get_distro_id() == 'rhel' + + # RHEL8.10 use a different repoid for client repository, but the repomapping mechanism cannot distinguish these + # as it does not use minor versions. Therefore, we have to hardcode these changes. +- if get_source_version() == '8.10': ++ if is_rhel and get_source_version() == '8.10': + for rhel88_rhui_client_repoid, rhel810_rhui_client_repoid in RHUI_CLIENT_REPOIDS_RHEL88_TO_RHEL810.items(): + if rhel810_rhui_client_repoid in repoids_to_map: + # Replace RHEL8.10 rhui client repoids with RHEL8.8 repoids, +@@ -119,9 +174,9 @@ def process(): + default_channels = setuptargetrepos_repomap.get_default_repository_channels(repomap, repoids_to_map) + repomap.set_default_channels(default_channels) + +- # Get target RHEL repoids based on the repomap ++ # Get target distro repoids based on the repomap + expected_repos = repomap.get_expected_target_pesid_repos(repoids_to_map) +- target_rhel_repoids = set() ++ target_distro_repoids = set() + for target_pesid, target_pesidrepo in expected_repos.items(): + if not target_pesidrepo: + # NOTE this could happen only for enabled repositories part of the set, +@@ -139,7 +194,7 @@ def process(): + if target_pesidrepo.repoid in excluded_repoids: + api.current_logger().debug('Skipping the {} repo (excluded).'.format(target_pesidrepo.repoid)) + continue +- target_rhel_repoids.add(target_pesidrepo.repoid) ++ target_distro_repoids.add(target_pesidrepo.repoid) + + # FIXME: this could possibly result into a try to enable multiple repositories + # from the same family (pesid). But unless we have a bug in previous actors, +@@ -151,7 +206,7 @@ def process(): + if repo in excluded_repoids: + api.current_logger().debug('Skipping the {} repo from setup task (excluded).'.format(repo)) + continue +- target_rhel_repoids.add(repo) ++ target_distro_repoids.add(repo) + + # On 8.10, some RHUI setups have different names than the one computed by repomapping. + # Although such situation could be avoided (having another client repo when a single +@@ -159,15 +214,23 @@ def process(): + # solution. + if get_target_version() == '8.10': + for pre_810_repoid, post_810_repoid in RHUI_CLIENT_REPOIDS_RHEL88_TO_RHEL810.items(): +- if pre_810_repoid in target_rhel_repoids: +- target_rhel_repoids.remove(pre_810_repoid) +- target_rhel_repoids.add(post_810_repoid) ++ if pre_810_repoid in target_distro_repoids: ++ target_distro_repoids.remove(pre_810_repoid) ++ target_distro_repoids.add(post_810_repoid) + + # create the final lists and sort them (for easier testing) +- rhel_repos = [RHELTargetRepository(repoid=repoid) for repoid in sorted(target_rhel_repoids)] ++ if is_rhel: ++ rhel_repos = [RHELTargetRepository(repoid=repoid) for repoid in sorted(target_distro_repoids)] ++ else: ++ rhel_repos = [] ++ distro_repos = [DistroTargetRepository(repoid=repoid) for repoid in sorted(target_distro_repoids)] custom_repos = [repo for repo in custom_repos if repo.repoid not in excluded_repoids] custom_repos = sorted(custom_repos, key=lambda x: x.repoid) @@ -5733,6 +6386,65 @@ index a6073aa3..dfa565c1 100644 # produce message about skipped repositories enabled_repoids_with_mapping = _get_mapped_repoids(repomap, enabled_repoids) skipped_repoids = enabled_repoids & set(used_repoids_dict.keys()) - enabled_repoids_with_mapping +@@ -179,5 +242,6 @@ def process(): + + api.produce(TargetRepositories( + rhel_repos=rhel_repos, ++ distro_repos=distro_repos, + custom_repos=custom_repos, + )) +diff --git a/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos_repomap.py b/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos_repomap.py +index 37be03f1..343ee2ea 100644 +--- a/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos_repomap.py ++++ b/repos/system_upgrade/common/actors/setuptargetrepos/libraries/setuptargetrepos_repomap.py +@@ -1,4 +1,4 @@ +-from leapp.libraries.common.config import get_target_product_channel ++from leapp.libraries.common.config import get_distro_id, get_target_product_channel + from leapp.libraries.common.config.version import get_source_major_version, get_target_major_version + from leapp.libraries.stdlib import api + +@@ -44,7 +44,7 @@ class RepoMapDataHandler(object): + # ideal for work, but there is not any significant impact.. + self.repositories = repo_map.repositories + self.mapping = repo_map.mapping +- self.distro = distro or api.current_actor().configuration.os_release.release_id ++ self.distro = distro or get_distro_id() + # FIXME(pstodulk): what about default_channel -> fallback_channel + # hardcoded always as ga? instead of list of channels.. + # it'd be possibly confusing naming now... +diff --git a/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py b/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py +index 1f898e8f..e4a30f7f 100644 +--- a/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py ++++ b/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py +@@ -198,11 +198,23 @@ def test_repos_mapping_for_distro(monkeypatch, distro_id): + setuptargetrepos.process() + assert api.produce.called + ++ distro_repos = api.produce.model_instances[0].distro_repos + rhel_repos = api.produce.model_instances[0].rhel_repos +- assert len(rhel_repos) == 3 + ++ assert len(distro_repos) == 3 ++ ++ produced_distro_repoids = {repo.repoid for repo in distro_repos} + produced_rhel_repoids = {repo.repoid for repo in rhel_repos} +- expected_rhel_repoids = {'{0}-8-for-x86_64-baseos-htb-rpms'.format(distro_id), +- '{0}-8-for-x86_64-appstream-htb-rpms'.format(distro_id), +- '{0}-8-for-x86_64-satellite-extras-rpms'.format(distro_id)} +- assert produced_rhel_repoids == expected_rhel_repoids ++ ++ expected_repoids = { ++ "{0}-8-for-x86_64-baseos-htb-rpms".format(distro_id), ++ "{0}-8-for-x86_64-appstream-htb-rpms".format(distro_id), ++ "{0}-8-for-x86_64-satellite-extras-rpms".format(distro_id), ++ } ++ ++ assert produced_distro_repoids == expected_repoids ++ if distro_id == 'rhel': ++ assert len(rhel_repos) == 3 ++ assert produced_rhel_repoids == expected_repoids ++ else: ++ assert len(rhel_repos) == 0 diff --git a/repos/system_upgrade/common/actors/systemfacts/actor.py b/repos/system_upgrade/common/actors/systemfacts/actor.py index 59b12c87..85d4a09e 100644 --- a/repos/system_upgrade/common/actors/systemfacts/actor.py @@ -5747,10 +6459,35 @@ index 59b12c87..85d4a09e 100644 def process(self): self.produce(systemfacts.get_sysctls_status()) diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -index 55877d05..0b7a5b3a 100644 +index 55877d05..9862f5d8 100644 --- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py +++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -@@ -152,9 +152,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): +@@ -6,7 +6,7 @@ import shutil + from leapp import reporting + from leapp.exceptions import StopActorExecution, StopActorExecutionError + from leapp.libraries.actor import constants +-from leapp.libraries.common import dnfplugin, mounting, overlaygen, repofileutils, rhsm, utils ++from leapp.libraries.common import distro, dnfplugin, mounting, overlaygen, repofileutils, rhsm, utils + from leapp.libraries.common.config import get_distro_id, get_env, get_product_type + from leapp.libraries.common.config.version import get_target_major_version + from leapp.libraries.common.gpg import get_path_to_gpg_certs, is_nogpgcheck_set +@@ -17,6 +17,7 @@ from leapp.models import ( + CustomTargetRepositoryFile, + PkgManagerInfo, + RepositoriesFacts, ++ RHELTargetRepository, + RHSMInfo, + RHUIInfo, + StorageInfo, +@@ -57,6 +58,7 @@ from leapp.utils.deprecation import suppress_deprecation + PROD_CERTS_FOLDER = 'prod-certs' + PERSISTENT_PACKAGE_CACHE_DIR = '/var/lib/leapp/persistent_package_cache' + DEDICATED_LEAPP_PART_URL = 'https://access.redhat.com/solutions/7011704' ++FMT_LIST_SEPARATOR = '\n - ' + + + def _check_deprecated_rhsm_skip(): +@@ -152,9 +154,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): # Import the RHEL X+1 GPG key to be able to verify the installation of initial packages try: # Import also any other keys provided by the customer in the same directory @@ -5764,7 +6501,7 @@ index 55877d05..0b7a5b3a 100644 except CalledProcessError as exc: raise StopActorExecutionError( message=( -@@ -641,6 +642,7 @@ def _prep_repository_access(context, target_userspace): +@@ -641,6 +644,7 @@ def _prep_repository_access(context, target_userspace): run(["chroot", target_userspace, "/bin/bash", "-c", "su - -c update-ca-trust"]) if not rhsm.skip_rhsm(): @@ -5772,6 +6509,443 @@ index 55877d05..0b7a5b3a 100644 run(['rm', '-rf', os.path.join(target_etc, 'rhsm')]) context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm')) +@@ -777,7 +781,7 @@ def _inhibit_on_duplicate_repos(repofiles): + list_separator_fmt = '\n - ' + api.current_logger().warning( + 'The following repoids are defined multiple times:{0}{1}' +- .format(list_separator_fmt, list_separator_fmt.join(duplicates)) ++ .format(list_separator_fmt, list_separator_fmt.join(sorted(duplicates))) + ) + + reporting.create_report([ +@@ -785,7 +789,7 @@ def _inhibit_on_duplicate_repos(repofiles): + reporting.Summary( + 'The following repositories are defined multiple times inside the' + ' "upgrade" container:{0}{1}' +- .format(list_separator_fmt, list_separator_fmt.join(duplicates)) ++ .format(list_separator_fmt, list_separator_fmt.join(sorted(duplicates))) + ), + reporting.Severity(reporting.Severity.MEDIUM), + reporting.Groups([reporting.Groups.REPOSITORY]), +@@ -814,21 +818,19 @@ def _get_all_available_repoids(context): + return set(repoids) + + +-def _get_rhsm_available_repoids(context): +- target_major_version = get_target_major_version() ++def _inhibit_if_no_base_repos(distro_repoids): + # FIXME: check that required repo IDs (baseos, appstream) + # + or check that all required RHEL repo IDs are available. +- if rhsm.skip_rhsm(): +- return set() +- # Get the RHSM repos available in the target RHEL container +- # TODO: very similar thing should happens for all other repofiles in container +- # +- repoids = rhsm.get_available_repo_ids(context) ++ ++ target_major_version = get_target_major_version() + # NOTE(ivasilev) For the moment at least AppStream and BaseOS repos are required. While we are still + # contemplating on what can be a generic solution to checking this, let's introduce a minimal check for + # at-least-one-appstream and at-least-one-baseos among present repoids +- if not repoids or all("baseos" not in ri for ri in repoids) or all("appstream" not in ri for ri in repoids): ++ no_baseos = all("baseos" not in ri for ri in distro_repoids) ++ no_appstream = all("appstream" not in ri for ri in distro_repoids) ++ if no_baseos or no_appstream: + reporting.create_report([ ++ # TODO: Make the report distro agnostic + reporting.Title('Cannot find required basic RHEL target repositories.'), + reporting.Summary( + 'This can happen when a repository ID was entered incorrectly either while using the --enablerepo' +@@ -860,21 +862,6 @@ def _get_rhsm_available_repoids(context): + title='Preparing for the upgrade') + ]) + raise StopActorExecution() +- return set(repoids) +- +- +-def _get_rhui_available_repoids(context, cloud_repo): +- repofiles = repofileutils.get_parsed_repofiles(context) +- +- # TODO: same refactoring as Issue #486? +- _inhibit_on_duplicate_repos(repofiles) +- repoids = [] +- for rfile in repofiles: +- if rfile.file == cloud_repo and rfile.data: +- repoids = [repo.repoid for repo in rfile.data] +- repoids.sort() +- break +- return set(repoids) + + + def get_copy_location_from_copy_in_task(context_basepath, copy_task): +@@ -885,88 +872,109 @@ def get_copy_location_from_copy_in_task(context_basepath, copy_task): + return copy_task.dst + + +-def _get_rh_available_repoids(context, indata): ++def _get_rhui_available_repoids(context, rhui_info): + """ +- RH repositories are provided either by RHSM or are stored in the expected repo file provided by +- RHUI special packages (every cloud provider has itw own rpm). ++ Get repoids provided by the RHUI target clients ++ ++ :rtype: set[str] + """ ++ # If we are upgrading a RHUI system, check what repositories are provided by the (already installed) target clients ++ setup_info = rhui_info.target_client_setup_info ++ target_content_access_files = set() ++ if setup_info.bootstrap_target_client: ++ target_content_access_files = _query_rpm_for_pkg_files(context, rhui_info.target_client_pkg_names) + +- rh_repoids = _get_rhsm_available_repoids(context) ++ def is_repofile(path): ++ return os.path.dirname(path) == '/etc/yum.repos.d' and os.path.basename(path).endswith('.repo') + +- # If we are upgrading a RHUI system, check what repositories are provided by the (already installed) target clients +- if indata and indata.rhui_info: +- setup_info = indata.rhui_info.target_client_setup_info +- target_content_access_files = set() +- if setup_info.bootstrap_target_client: +- target_content_access_files = _query_rpm_for_pkg_files(context, indata.rhui_info.target_client_pkg_names) ++ def extract_repoid_from_line(line): ++ return line.split(':', 1)[1].strip() + +- def is_repofile(path): +- return os.path.dirname(path) == '/etc/yum.repos.d' and os.path.basename(path).endswith('.repo') ++ target_ver = api.current_actor().configuration.version.target ++ setup_tasks = rhui_info.target_client_setup_info.preinstall_tasks.files_to_copy_into_overlay + +- def extract_repoid_from_line(line): +- return line.split(':', 1)[1].strip() ++ yum_repos_d = context.full_path('/etc/yum.repos.d') ++ all_repofiles = {os.path.join(yum_repos_d, path) for path in os.listdir(yum_repos_d) if path.endswith('.repo')} ++ api.current_logger().debug('(RHUI Setup) All available repofiles: {0}'.format(' '.join(all_repofiles))) + +- target_ver = api.current_actor().configuration.version.target +- setup_tasks = indata.rhui_info.target_client_setup_info.preinstall_tasks.files_to_copy_into_overlay ++ target_access_repofiles = { ++ context.full_path(path) for path in target_content_access_files if is_repofile(path) ++ } + +- yum_repos_d = context.full_path('/etc/yum.repos.d') +- all_repofiles = {os.path.join(yum_repos_d, path) for path in os.listdir(yum_repos_d) if path.endswith('.repo')} +- api.current_logger().debug('(RHUI Setup) All available repofiles: {0}'.format(' '.join(all_repofiles))) ++ # Exclude repofiles used to setup the target rhui access as on some platforms the repos provided by ++ # the client are not sufficient to install the client into target userspace (GCP) ++ rhui_setup_repofile_tasks = [task for task in setup_tasks if task.src.endswith('repo')] ++ rhui_setup_repofiles = ( ++ get_copy_location_from_copy_in_task(context.base_dir, copy) for copy in rhui_setup_repofile_tasks ++ ) ++ rhui_setup_repofiles = {context.full_path(repofile) for repofile in rhui_setup_repofiles} + +- target_access_repofiles = { +- context.full_path(path) for path in target_content_access_files if is_repofile(path) +- } ++ foreign_repofiles = all_repofiles - target_access_repofiles - rhui_setup_repofiles + +- # Exclude repofiles used to setup the target rhui access as on some platforms the repos provided by +- # the client are not sufficient to install the client into target userspace (GCP) +- rhui_setup_repofile_tasks = [task for task in setup_tasks if task.src.endswith('repo')] +- rhui_setup_repofiles = ( +- get_copy_location_from_copy_in_task(context.base_dir, copy) for copy in rhui_setup_repofile_tasks +- ) +- rhui_setup_repofiles = {context.full_path(repofile) for repofile in rhui_setup_repofiles} ++ api.current_logger().debug( ++ 'The following repofiles are considered as unknown to' ++ ' the target RHUI content setup and will be ignored: {0}'.format(' '.join(foreign_repofiles)) ++ ) + +- foreign_repofiles = all_repofiles - target_access_repofiles - rhui_setup_repofiles ++ # Rename non-client repofiles so they will not be recognized when running dnf repolist ++ for foreign_repofile in foreign_repofiles: ++ os.rename(foreign_repofile, '{0}.back'.format(foreign_repofile)) + +- api.current_logger().debug( +- 'The following repofiles are considered as unknown to' +- ' the target RHUI content setup and will be ignored: {0}'.format(' '.join(foreign_repofiles)) ++ rhui_repoids = set() ++ try: ++ dnf_cmd = [ ++ 'dnf', 'repolist', ++ '--releasever', target_ver, '-v', ++ '--enablerepo', '*', ++ '--disablerepo', '*-source-*', ++ '--disablerepo', '*-debug-*', ++ ] ++ repolist_result = context.call(dnf_cmd)['stdout'] ++ repoid_lines = [line for line in repolist_result.split('\n') if line.startswith('Repo-id')] ++ rhui_repoids.update({extract_repoid_from_line(line) for line in repoid_lines}) ++ ++ except CalledProcessError as err: ++ details = {'err': err.stderr, 'details': str(err)} ++ raise StopActorExecutionError( ++ message='Failed to retrieve repoids provided by target RHUI clients.', ++ details=details + ) + +- # Rename non-client repofiles so they will not be recognized when running dnf repolist ++ finally: ++ # Revert the renaming of non-client repofiles + for foreign_repofile in foreign_repofiles: +- os.rename(foreign_repofile, '{0}.back'.format(foreign_repofile)) ++ os.rename('{0}.back'.format(foreign_repofile), foreign_repofile) + +- try: +- dnf_cmd = [ +- 'dnf', 'repolist', +- '--releasever', target_ver, '-v', +- '--enablerepo', '*', +- '--disablerepo', '*-source-*', +- '--disablerepo', '*-debug-*', +- ] +- repolist_result = context.call(dnf_cmd)['stdout'] +- repoid_lines = [line for line in repolist_result.split('\n') if line.startswith('Repo-id')] +- rhui_repoids = {extract_repoid_from_line(line) for line in repoid_lines} +- rh_repoids.update(rhui_repoids) +- +- except CalledProcessError as err: +- details = {'err': err.stderr, 'details': str(err)} +- raise StopActorExecutionError( +- message='Failed to retrieve repoids provided by target RHUI clients.', +- details=details +- ) ++ return rhui_repoids + +- finally: +- # Revert the renaming of non-client repofiles +- for foreign_repofile in foreign_repofiles: +- os.rename('{0}.back'.format(foreign_repofile), foreign_repofile) + +- api.current_logger().debug( +- 'The following repofiles are considered as provided by RedHat: {0}'.format(' '.join(rh_repoids)) +- ) +- return rh_repoids ++def _get_distro_available_repoids(context, indata): ++ """ ++ Get repoids provided by the distribution ++ ++ On RHEL: RH repositories are provided either by RHSM or are stored in the ++ expected repo file provided by RHUI special packages (every cloud ++ provider has itw own rpm). ++ On other: Repositories are provided in specific repofiles (e.g. centos.repo ++ and centos-addons.repo on CS) ++ ++ :return: A set of repoids provided by distribution ++ :rtype: set[str] ++ """ ++ distro_repoids = distro.get_target_distro_repoids(context) ++ distro_id = get_distro_id() ++ rhel_and_rhsm = distro_id == 'rhel' and not rhsm.skip_rhsm() ++ if distro_id != 'rhel' or rhel_and_rhsm: ++ _inhibit_if_no_base_repos(distro_repoids) ++ ++ if indata and indata.rhui_info: ++ rhui_repoids = _get_rhui_available_repoids(context, indata.rhui_info) ++ distro_repoids.extend(rhui_repoids) + ++ return set(distro_repoids) + ++ ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + def gather_target_repositories(context, indata): + """ + Get available required target repositories and inhibit or raise error if basic checks do not pass. +@@ -984,17 +992,31 @@ def gather_target_repositories(context, indata): + :param context: An instance of a mounting.IsolatedActions class + :type context: mounting.IsolatedActions class + :return: List of target system repoids +- :rtype: List(string) ++ :rtype: set[str] + """ +- rh_available_repoids = _get_rh_available_repoids(context, indata) +- all_available_repoids = _get_all_available_repoids(context) + +- target_repoids = [] +- missing_custom_repoids = [] ++ distro_repoids = _get_distro_available_repoids(context, indata) ++ if distro_repoids: ++ api.current_logger().info( ++ "The following repoids are considered as provided by the '{}' distribution:{}{}".format( ++ get_distro_id(), ++ FMT_LIST_SEPARATOR, ++ FMT_LIST_SEPARATOR.join(sorted(distro_repoids)), ++ ) ++ ) ++ else: ++ api.current_logger().warning( ++ "No repoids provided by the {} distribution have been discovered".format(get_distro_id()) ++ ) ++ ++ all_repoids = _get_all_available_repoids(context) ++ ++ target_repoids = set() ++ missing_custom_repoids = set() + for target_repo in api.consume(TargetRepositories): +- for rhel_repo in target_repo.rhel_repos: +- if rhel_repo.repoid in rh_available_repoids: +- target_repoids.append(rhel_repo.repoid) ++ for distro_repo in target_repo.distro_repos: ++ if distro_repo.repoid in distro_repoids: ++ target_repoids.add(distro_repo.repoid) + else: + # TODO: We shall report that the RHEL repos that we deem necessary for + # the upgrade are not available; but currently it would just print bunch of +@@ -1003,12 +1025,16 @@ def gather_target_repositories(context, indata): + # of the upgrade. Let's skip it for now until it's clear how we will deal + # with it. + pass ++ + for custom_repo in target_repo.custom_repos: +- if custom_repo.repoid in all_available_repoids: +- target_repoids.append(custom_repo.repoid) ++ if custom_repo.repoid in all_repoids: ++ target_repoids.add(custom_repo.repoid) + else: +- missing_custom_repoids.append(custom_repo.repoid) +- api.current_logger().debug("Gathered target repositories: {}".format(', '.join(target_repoids))) ++ missing_custom_repoids.add(custom_repo.repoid) ++ api.current_logger().debug( ++ "Gathered target repositories: {}".format(", ".join(sorted(target_repoids))) ++ ) ++ + if not target_repoids: + target_major_version = get_target_major_version() + reporting.create_report([ +@@ -1054,7 +1080,7 @@ def gather_target_repositories(context, indata): + ' while using the --enablerepo option of leapp, or in a third party actor that produces a' + ' CustomTargetRepositoryMessage.\n' + 'The following repositories IDs could not be found in the target configuration:\n' +- '- {}\n'.format('\n- '.join(missing_custom_repoids)) ++ '- {}\n'.format('\n- '.join(sorted(missing_custom_repoids))) + ), + reporting.Groups([reporting.Groups.REPOSITORY]), + reporting.Groups([reporting.Groups.INHIBITOR]), +@@ -1071,7 +1097,7 @@ def gather_target_repositories(context, indata): + )) + ]) + raise StopActorExecution() +- return set(target_repoids) ++ return target_repoids + + + def _install_custom_repofiles(context, custom_repofiles): +diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py b/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py +index 7853a7ad..2ae194d7 100644 +--- a/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py ++++ b/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py +@@ -11,9 +11,9 @@ import pytest + from leapp import models, reporting + from leapp.exceptions import StopActorExecution, StopActorExecutionError + from leapp.libraries.actor import userspacegen +-from leapp.libraries.common import overlaygen, repofileutils, rhsm ++from leapp.libraries.common import distro, overlaygen, repofileutils, rhsm + from leapp.libraries.common.config import architecture +-from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked, produce_mocked ++from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, logger_mocked, produce_mocked + from leapp.libraries.stdlib import api, CalledProcessError + from leapp.utils.deprecation import suppress_deprecation + +@@ -1072,6 +1072,7 @@ def test_consume_data(monkeypatch, raised, no_rhsm, testdata): + + + @pytest.mark.skip(reason="Currently not implemented in the actor. It's TODO.") ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories(monkeypatch): + monkeypatch.setattr(userspacegen.api, 'current_actor', CurrentActorMocked()) + # The available RHSM repos +@@ -1104,6 +1105,7 @@ def test_gather_target_repositories_none_available(monkeypatch): + assert inhibitors[0].get('title', '') == 'Cannot find required basic RHEL target repositories.' + + ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories_rhui(monkeypatch): + + indata = testInData( +@@ -1113,7 +1115,9 @@ def test_gather_target_repositories_rhui(monkeypatch): + monkeypatch.setattr(userspacegen.api, 'current_actor', CurrentActorMocked()) + monkeypatch.setattr(userspacegen, '_get_all_available_repoids', lambda x: []) + monkeypatch.setattr( +- userspacegen, '_get_rh_available_repoids', lambda x, y: ['rhui-1', 'rhui-2', 'rhui-3'] ++ userspacegen, ++ "_get_distro_available_repoids", ++ lambda dummy_context, dummy_indata: {"rhui-1", "rhui-2", "rhui-3"}, + ) + monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True) + monkeypatch.setattr( +@@ -1122,6 +1126,10 @@ def test_gather_target_repositories_rhui(monkeypatch): + rhel_repos=[ + models.RHELTargetRepository(repoid='rhui-1'), + models.RHELTargetRepository(repoid='rhui-2') ++ ], ++ distro_repos=[ ++ models.DistroTargetRepository(repoid='rhui-1'), ++ models.DistroTargetRepository(repoid='rhui-2') + ] + ) + ]) +@@ -1130,6 +1138,7 @@ def test_gather_target_repositories_rhui(monkeypatch): + assert target_repoids == set(['rhui-1', 'rhui-2']) + + ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories_baseos_appstream_not_available(monkeypatch): + # If the repos that Leapp identifies as required for the upgrade (based on the repo mapping and PES data) are not + # available, an exception shall be raised +@@ -1188,6 +1197,54 @@ def test_gather_target_repositories_baseos_appstream_not_available(monkeypatch): + assert inhibitors[0].get('title', '') == 'Cannot find required basic RHEL target repositories.' + + ++def test__get_distro_available_repoids_norhsm_norhui(monkeypatch): ++ """ ++ Empty set should be returned when on rhel and skip_rhsm == True. ++ """ ++ monkeypatch.setattr( ++ userspacegen.api, "current_actor", CurrentActorMocked(release_id="rhel") ++ ) ++ monkeypatch.setattr(userspacegen.api.current_actor(), 'produce', produce_mocked()) ++ ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True) ++ monkeypatch.setattr(distro, 'get_target_distro_repoids', lambda ctx: []) ++ ++ indata = testInData(_PACKAGES_MSGS, None, None, _XFS_MSG, _STORAGEINFO_MSG, None) ++ # NOTE: context is not used without rhsm, for simplicity setting to None ++ repoids = userspacegen._get_distro_available_repoids(None, indata) ++ assert repoids == set() ++ ++ ++@pytest.mark.parametrize( ++ "distro_id,skip_rhsm", [("rhel", False), ("centos", True), ("almalinux", True)] ++) ++def test__get_distro_available_repoids_nobaserepos_inhibit( ++ monkeypatch, distro_id, skip_rhsm ++): ++ """ ++ Test that get_distro_available repoids reports and raises if there are no base repos. ++ """ ++ monkeypatch.setattr( ++ userspacegen.api, "current_actor", CurrentActorMocked(release_id=distro_id) ++ ) ++ monkeypatch.setattr(userspacegen.api.current_actor(), 'produce', produce_mocked()) ++ monkeypatch.setattr(reporting, "create_report", create_report_mocked()) ++ ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: skip_rhsm) ++ monkeypatch.setattr(distro, 'get_target_distro_repoids', lambda ctx: []) ++ ++ indata = testInData(_PACKAGES_MSGS, None, None, _XFS_MSG, _STORAGEINFO_MSG, None) ++ with pytest.raises(StopActorExecution): ++ # NOTE: context is not used without rhsm, for simplicity setting to None ++ userspacegen._get_distro_available_repoids(None, indata) ++ ++ # TODO adjust the asserts when the report is made distro agnostic ++ assert reporting.create_report.called == 1 ++ report = reporting.create_report.reports[0] ++ assert "Cannot find required basic RHEL target repositories" in report["title"] ++ assert reporting.Groups.INHIBITOR in report["groups"] ++ ++ + def mocked_consume_data(): + packages = {'dnf', 'dnf-command(config-manager)', 'pkgA', 'pkgB'} + rhsm_info = _RHSMINFO_MSG diff --git a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py b/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py index 6377f767..4c5420f6 100644 --- a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py @@ -6233,18 +7407,23 @@ index 22e0fd7d..47ca28d5 100644 } } diff --git a/repos/system_upgrade/common/libraries/distro.py b/repos/system_upgrade/common/libraries/distro.py -index 2ed5eacd..219d31d1 100644 +index 2ed5eacd..dc3860c9 100644 --- a/repos/system_upgrade/common/libraries/distro.py +++ b/repos/system_upgrade/common/libraries/distro.py -@@ -3,6 +3,7 @@ import os +@@ -2,7 +2,12 @@ import json + import os from leapp.exceptions import StopActorExecutionError ++from leapp.libraries.common import repofileutils, rhsm ++from leapp.libraries.common.config import get_distro_id ++from leapp.libraries.common.config.architecture import ARCH_ACCEPTED, ARCH_X86_64 ++from leapp.libraries.common.config.version import get_target_major_version from leapp.libraries.stdlib import api +from leapp.models import VendorSignatures def get_distribution_data(distribution): -@@ -11,8 +12,14 @@ def get_distribution_data(distribution): +@@ -11,8 +16,201 @@ def get_distribution_data(distribution): distribution_config = os.path.join(distributions_path, distribution, 'gpg-signatures.json') if os.path.exists(distribution_config): with open(distribution_config) as distro_config_file: @@ -6256,10 +7435,197 @@ index 2ed5eacd..219d31d1 100644 details={'Problem': 'Distribution {} was not found in {}.'.format(distribution, distributions_path)}) + + # Extend with Vendors signatures -+ for siglist in api.consume(VendorSignatures): ++ for siglist in api.consume(VendorSignatures): + distro_config_json["keys"].extend(siglist.sigs) + + return distro_config_json ++ ++# distro -> major_version -> repofile -> tuple of architectures where it's present ++_DISTRO_REPOFILES_MAP = { ++ 'rhel': { ++ '8': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ '9': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ '10': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ }, ++ 'centos': { ++ '8': { ++ # TODO is this true on all archs? ++ 'CentOS-Linux-AppStream.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-BaseOS.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-ContinuousRelease.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Debuginfo.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Devel.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Extras.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-FastTrack.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-HighAvailability.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Media.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Plus.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-PowerTools.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Sources.repo': ARCH_ACCEPTED, ++ }, ++ '9': { ++ '/etc/yum.repos.d/centos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/centos-addons.repo': ARCH_ACCEPTED, ++ }, ++ '10': { ++ '/etc/yum.repos.d/centos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/centos-addons.repo': ARCH_ACCEPTED, ++ }, ++ }, ++ 'almalinux': { ++ '8': { ++ # TODO is this true on all archs? ++ '/etc/yum.repos.d/almalinux-ha.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-nfv.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-powertools.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-resilientstorage.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-rt.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux.repo': ARCH_ACCEPTED, ++ }, ++ '9': { ++ '/etc/yum.repos.d/almalinux-appstream.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-baseos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-crb.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-extras.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-highavailability.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-resilientstorage.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ # RT and NFV are only on x86_64 on almalinux 9 ++ '/etc/yum.repos.d/almalinux-nfv.repo': (ARCH_X86_64,), ++ '/etc/yum.repos.d/almalinux-rt.repo': (ARCH_X86_64,), ++ }, ++ '10': { ++ # no resilientstorage on 10 ++ '/etc/yum.repos.d/almalinux-appstream.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-baseos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-crb.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-extras.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-highavailability.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ # RT and NFV are only on x86_64 on almalinux 10 ++ '/etc/yum.repos.d/almalinux-nfv.repo': (ARCH_X86_64,), ++ '/etc/yum.repos.d/almalinux-rt.repo': (ARCH_X86_64,), ++ }, ++ }, ++} ++ ++ ++def _get_distro_repofiles(distro, major_version, arch): ++ """ ++ Get distribution provided repofiles. ++ ++ Note that this does not perform any validation, the caller must check ++ whether the files exist. ++ ++ :param distro: The distribution to get repofiles for. ++ :type distro: str ++ :param major_version: The major version to get repofiles for. ++ :type major_version: str ++ :param arch: The architecture to get repofiles for. ++ :type arch: str ++ :return: A list of paths to repofiles provided by distribution ++ :rtype: list[str] or None if no repofiles are mapped for the arguments ++ """ ++ ++ distro_repofiles = _DISTRO_REPOFILES_MAP.get(distro) ++ if not distro_repofiles: ++ return None ++ ++ version_repofiles = distro_repofiles.get(major_version, {}) ++ if not version_repofiles: ++ return None ++ ++ return [repofile for repofile, archs in version_repofiles.items() if arch in archs] ++ ++ ++def get_target_distro_repoids(context): ++ """ ++ Get repoids defined in distro provided repofiles ++ ++ See the generic :func:`_get_distro_repoids` for more details. ++ ++ :param context: An instance of mounting.IsolatedActions class ++ :type context: mounting.IsolatedActions ++ :return: Repoids of distribution provided repositories ++ :type: list[str] ++ """ ++ ++ return get_distro_repoids( ++ context, ++ get_distro_id(), ++ get_target_major_version(), ++ api.current_actor().configuration.architecture ++ ) ++ ++ ++def get_distro_repoids(context, distro, major_version, arch): ++ """ ++ Get repoids defined in distro provided repofiles ++ ++ On RHEL with RHSM this delegates to rhsm.get_available_repo_ids. ++ ++ Repofiles installed by RHUI client packages are not covered by this ++ function. ++ ++ :param context: An instance of mounting.IsolatedActions class ++ :type context: mounting.IsolatedActions ++ :param distro: The distro whose repoids to return ++ :type distro: str ++ :param major_version: The major version to get distro repoids for. ++ :type major_version: str ++ :param arch: The architecture to get distro repoids for. ++ :type arch: str ++ :return: Repoids of distribution provided repositories ++ :type: list[str] ++ """ ++ ++ if distro == 'rhel': ++ if rhsm.skip_rhsm(): ++ return [] ++ # Kept this todo here from the original code from ++ # userspacegen._get_rh_available_repoids: ++ # Get the RHSM repos available in the target RHEL container ++ # TODO: very similar thing should happens for all other repofiles in container ++ return rhsm.get_available_repo_ids(context) ++ ++ repofiles = repofileutils.get_parsed_repofiles(context) ++ distro_repofiles = _get_distro_repofiles(distro, major_version, arch) ++ if not distro_repofiles: ++ # TODO: a different way of signaling an error would be preferred (e.g. returning None), ++ # but since rhsm.get_available_repo_ids also raises StopActorExecutionError, ++ # let's make it easier for the caller for now and use it too ++ raise StopActorExecutionError( ++ "No known distro provided repofiles mapped", ++ details={ ++ "details": "distro: {}, major version: {}, architecture: {}".format( ++ distro, major_version, arch ++ ) ++ }, ++ ) ++ ++ distro_repoids = [] ++ for rfile in repofiles: ++ if rfile.file in distro_repofiles: ++ ++ if not os.path.exists(context.full_path(rfile.file)): ++ api.current_logger().debug( ++ "Expected distribution provided repofile does not exists: {}".format( ++ rfile ++ ) ++ ) ++ continue ++ ++ if rfile.data: ++ distro_repoids.extend([repo.repoid for repo in rfile.data]) ++ ++ return sorted(distro_repoids) diff --git a/repos/system_upgrade/common/libraries/dnfplugin.py b/repos/system_upgrade/common/libraries/dnfplugin.py index 4f0c3a99..0f31f101 100644 --- a/repos/system_upgrade/common/libraries/dnfplugin.py @@ -6321,6 +7687,19 @@ index c9c3f1fc..96907be0 100644 def is_nogpgcheck_set(): +diff --git a/repos/system_upgrade/common/libraries/overlaygen.py b/repos/system_upgrade/common/libraries/overlaygen.py +index 867e3559..a048af2b 100644 +--- a/repos/system_upgrade/common/libraries/overlaygen.py ++++ b/repos/system_upgrade/common/libraries/overlaygen.py +@@ -710,7 +710,7 @@ def _create_mount_disk_image_old(disk_images_directory, path): + try: + utils.call_with_oserror_handled(cmd=['/sbin/mkfs.ext4', '-F', diskimage_path]) + except CalledProcessError as e: +- api.current_logger().error('Failed to create ext4 filesystem in %s', exc_info=True) ++ api.current_logger().error('Failed to create ext4 filesystem in %s', diskimage_path, exc_info=True) + raise StopActorExecutionError( + message=str(e) + ) diff --git a/repos/system_upgrade/common/libraries/repomaputils.py b/repos/system_upgrade/common/libraries/repomaputils.py new file mode 100644 index 00000000..39b7d662 @@ -6468,6 +7847,211 @@ index 00000000..39b7d662 + ) + + return combined_repomapping +diff --git a/repos/system_upgrade/common/libraries/tests/test_distro.py b/repos/system_upgrade/common/libraries/tests/test_distro.py +new file mode 100644 +index 00000000..8e866455 +--- /dev/null ++++ b/repos/system_upgrade/common/libraries/tests/test_distro.py +@@ -0,0 +1,199 @@ ++import json ++import os ++ ++import pytest ++ ++from leapp.actors import StopActorExecutionError ++from leapp.libraries.common import distro, repofileutils, rhsm ++from leapp.libraries.common.config.architecture import ARCH_ACCEPTED, ARCH_ARM64, ARCH_PPC64LE, ARCH_S390X, ARCH_X86_64 ++from leapp.libraries.common.distro import _get_distro_repofiles, get_distribution_data, get_distro_repoids ++from leapp.libraries.common.testutils import CurrentActorMocked ++from leapp.libraries.stdlib import api ++from leapp.models import RepositoryData, RepositoryFile ++ ++_RHEL_REPOFILES = ['/etc/yum.repos.d/redhat.repo'] ++_CENTOS_REPOFILES = [ ++ "/etc/yum.repos.d/centos.repo", "/etc/yum.repos.d/centos-addons.repo" ++] ++ ++_CUR_DIR = os.path.dirname(os.path.abspath(__file__)) ++ ++ ++@pytest.mark.parametrize('distro', ['rhel', 'centos']) ++def test_get_distribution_data(monkeypatch, distro): ++ common_path = os.path.join(_CUR_DIR, "../../files/", 'distro') ++ monkeypatch.setattr( ++ api, ++ "get_common_folder_path", ++ lambda folder: common_path ++ ) ++ data_path = os.path.join(common_path, distro, "gpg-signatures.json") ++ ++ def exists_mocked(path): ++ assert path == data_path ++ return True ++ ++ monkeypatch.setattr(os.path, 'exists', exists_mocked) ++ ret = get_distribution_data(distro) ++ ++ with open(data_path) as fp: ++ assert ret == json.load(fp) ++ ++ ++@pytest.mark.parametrize('distro', ['rhel', 'centos']) ++def test_get_distribution_data_not_exists(monkeypatch, distro): ++ common_path = os.path.join(_CUR_DIR, "../../files/", 'distro') ++ monkeypatch.setattr( ++ api, ++ "get_common_folder_path", ++ lambda folder: common_path ++ ) ++ data_path = os.path.join(common_path, distro, "gpg-signatures.json") ++ ++ def exists_mocked(path): ++ assert path == data_path ++ return False ++ ++ monkeypatch.setattr(os.path, 'exists', exists_mocked) ++ ++ with pytest.raises(StopActorExecutionError) as err: ++ get_distribution_data(distro) ++ assert 'Cannot find distribution signature configuration.' in err ++ ++ ++def test_get_distro_repofiles(monkeypatch): ++ """ ++ Test the functionality, not the data. ++ """ ++ test_map = { ++ 'distro1': { ++ '8': { ++ 'repofile1': ARCH_ACCEPTED, ++ 'repofile2': [ARCH_X86_64], ++ }, ++ '9': { ++ 'repofile3': ARCH_ACCEPTED, ++ }, ++ }, ++ 'distro2': { ++ '8': {}, ++ '9': { ++ 'repofile2': [ARCH_X86_64], ++ 'repofile3': [ARCH_ARM64, ARCH_S390X, ARCH_PPC64LE], ++ }, ++ }, ++ } ++ monkeypatch.setattr(distro, '_DISTRO_REPOFILES_MAP', test_map) ++ ++ # mix of all and specific arch ++ repofiles = _get_distro_repofiles('distro1', '8', ARCH_X86_64) ++ assert repofiles == ['repofile1', 'repofile2'] ++ ++ # match all but not x86_64 ++ repofiles = _get_distro_repofiles('distro1', '8', ARCH_ARM64) ++ assert repofiles == ['repofile1'] ++ ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_X86_64) ++ assert repofiles == ['repofile2'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_ARM64) ++ assert repofiles == ['repofile3'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_S390X) ++ assert repofiles == ['repofile3'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_PPC64LE) ++ assert repofiles == ['repofile3'] ++ ++ # version not mapped ++ repofiles = _get_distro_repofiles('distro2', '8', ARCH_X86_64) ++ assert repofiles is None ++ ++ # distro not mapped ++ repofiles = _get_distro_repofiles('distro42', '8', ARCH_X86_64) ++ assert repofiles is None ++ ++ ++def _make_repo(repoid): ++ return RepositoryData(repoid=repoid, name='name {}'.format(repoid)) ++ ++ ++def _make_repofile(rfile, data=None): ++ if data is None: ++ data = [_make_repo("{}-{}".format(rfile.split("/")[-1], i)) for i in range(3)] ++ return RepositoryFile(file=rfile, data=data) ++ ++ ++def _make_repofiles(rfiles): ++ return [_make_repofile(rfile) for rfile in rfiles] ++ ++ ++@pytest.mark.parametrize('other_rfiles', [ ++ [], ++ [_make_repofile("foo")], ++ _make_repofiles(["foo", "bar"]), ++]) ++@pytest.mark.parametrize( ++ "distro_id,skip_rhsm,distro_rfiles", ++ [ ++ ("rhel", True, []), ++ ("rhel", True, _make_repofiles(_RHEL_REPOFILES)), ++ ("rhel", False, _make_repofiles(_RHEL_REPOFILES)), ++ ("centos", True, []), ++ ("centos", True, _make_repofiles(_CENTOS_REPOFILES)), ++ ] ++) ++def test_get_distro_repoids( ++ monkeypatch, distro_id, skip_rhsm, distro_rfiles, other_rfiles ++): ++ """ ++ Tests that the correct repoids are returned ++ ++ This is a little ugly because on RHEL the get_distro_repoids function still ++ delegates to rhsm.get_available_repo_ids and also has different behavior ++ with skip_rhsm ++ """ ++ current_actor = CurrentActorMocked(release_id=distro_id if distro_id else 'rhel') ++ monkeypatch.setattr(api, 'current_actor', current_actor) ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: skip_rhsm) ++ ++ repofiles = other_rfiles ++ if distro_rfiles: ++ repofiles.extend(distro_rfiles) ++ monkeypatch.setattr(repofileutils, 'get_parsed_repofiles', lambda x: repofiles) ++ ++ distro_repoids = [] ++ for rfile in distro_rfiles: ++ distro_repoids.extend([repo.repoid for repo in rfile.data] if rfile else []) ++ distro_repoids.sort() ++ ++ monkeypatch.setattr(rhsm, 'get_available_repo_ids', lambda _: distro_repoids) ++ monkeypatch.setattr(os.path, 'exists', lambda f: f in _CENTOS_REPOFILES) ++ ++ class MockedContext: ++ def full_path(self, path): ++ return path ++ ++ repoids = get_distro_repoids(MockedContext(), distro_id, '9', 'x86_64') ++ ++ if distro_id == 'rhel' and skip_rhsm: ++ assert repoids == [] ++ else: ++ assert sorted(repoids) == distro_repoids ++ ++ ++@pytest.mark.parametrize('other_rfiles', [ ++ [], ++ [_make_repofile("foo")], ++ _make_repofiles(["foo", "bar"]), ++]) ++def test_get_distro_repoids_no_distro_repofiles(monkeypatch, other_rfiles): ++ """ ++ Test that exception is thrown when there are no known distro provided repofiles. ++ """ ++ ++ def mocked_get_distro_repofiles(*args): ++ return [] ++ ++ monkeypatch.setattr(distro, '_get_distro_repofiles', mocked_get_distro_repofiles) ++ monkeypatch.setattr(repofileutils, "get_parsed_repofiles", lambda x: other_rfiles) ++ ++ with pytest.raises(StopActorExecutionError): ++ get_distro_repoids(None, 'somedistro', '8', 'x86_64') diff --git a/repos/system_upgrade/common/models/activevendorlist.py b/repos/system_upgrade/common/models/activevendorlist.py new file mode 100644 index 00000000..de4056fb @@ -6523,10 +8107,34 @@ index 7e2870d0..05d4e941 100644 modules_to_reset = fields.List(fields.Model(Module), default=[]) diff --git a/repos/system_upgrade/common/models/targetrepositories.py b/repos/system_upgrade/common/models/targetrepositories.py -index 02c6c5e5..f9fd4238 100644 +index 02c6c5e5..e1d44d80 100644 --- a/repos/system_upgrade/common/models/targetrepositories.py +++ b/repos/system_upgrade/common/models/targetrepositories.py -@@ -21,6 +21,12 @@ class CustomTargetRepository(TargetRepositoryBase): +@@ -1,4 +1,5 @@ + from leapp.models import fields, Model ++from leapp.reporting import deprecated + from leapp.topics import TransactionTopic + + +@@ -11,33 +12,66 @@ class UsedTargetRepository(TargetRepositoryBase): + pass + + ++@deprecated( ++ since="2025-07-23", ++ message="This model is deprecated, use DistroTargetRepository instead.", ++) + class RHELTargetRepository(TargetRepositoryBase): + pass + + ++class DistroTargetRepository(TargetRepositoryBase): ++ pass ++ ++ + class CustomTargetRepository(TargetRepositoryBase): + name = fields.Nullable(fields.String()) + baseurl = fields.Nullable(fields.String()) enabled = fields.Boolean(default=True) @@ -6539,6 +8147,44 @@ index 02c6c5e5..f9fd4238 100644 class TargetRepositories(Model): """ Repositories supposed to be used during the IPU process + + The list of the actually used repositories could be just subset +- of these repositoies. In case of `custom_repositories`, all such repositories ++ of these repositories. In case of `custom_repositories`, all such repositories + must be available otherwise the upgrade is inhibited. But in case of +- `rhel_repos`, only BaseOS and Appstream repos are required now. If others ++ `distro_repos`, only BaseOS and Appstream repos are required now. If others + are missing, upgrade can still continue. ++ ++ Note: `rhel_repos` are deprecated, use `distro_repos` instead. + """ + topic = TransactionTopic ++ ++ # DEPRECATED: this has been superseded by distro_repos + rhel_repos = fields.List(fields.Model(RHELTargetRepository)) + """ + Expected target YUM RHEL repositories provided via RHSM + ++ DEPRECATED - use distro_repos instead. ++ ++ These repositories are stored inside /etc/yum.repos.d/redhat.repo and ++ are expected to be used based on the provided repositories mapping. ++ """ ++ ++ distro_repos = fields.List(fields.Model(DistroTargetRepository)) ++ """ ++ Expected target DNF repositories provided by the distribution. ++ ++ On RHEL these are the repositories provided via RHSM. + These repositories are stored inside /etc/yum.repos.d/redhat.repo and + are expected to be used based on the provided repositories mapping. ++ ++ On other distributions, such as Centos Stream these are repositories ++ in /etc/yum.repos.d/ that are provided by the distribution and are expected ++ to be used based on the provided repositories mapping. + """ + + custom_repos = fields.List(fields.Model(CustomTargetRepository), default=[]) diff --git a/repos/system_upgrade/common/models/vendorsignatures.py b/repos/system_upgrade/common/models/vendorsignatures.py new file mode 100644 index 00000000..f456aec5 @@ -6618,6 +8264,34 @@ index c076fe6b..2455a2f6 100644 UPGRADE_BLS_DIR = '/boot/upgrade-loader' CONTAINER_DOWNLOAD_DIR = '/tmp_pkg_download_dir' +diff --git a/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py b/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py +index 46af07c1..7558b307 100644 +--- a/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py ++++ b/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py +@@ -1,4 +1,5 @@ + import errno ++import sys + import textwrap + + import pytest +@@ -57,7 +58,16 @@ def test_no_conf(monkeypatch): + assert not api.produce.called + + +-@pytest.mark.skipif(not nmconnscanner.libnm_available, reason="NetworkManager g-ir not installed") ++@pytest.mark.skipif( ++ sys.version_info.major != 3 or sys.version_info.minor != 6, ++ # On Python > 3.6 the GLib and NM libraries apparently behave differently and ++ # the test fails. Let's skip it since the actor it's only ever run with ++ # Python3.6 (el8toel9 repo and FactsPhase) ++ reason="Only runs on Python 3.6", ++) ++@pytest.mark.skipif( ++ not nmconnscanner.libnm_available, reason="NetworkManager g-ir not installed" ++) + def test_nm_conn(monkeypatch): + """ + Check a basic keyfile diff --git a/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py b/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py index daa7b2ca..dd604d8b 100644 --- a/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py @@ -6649,3 +8323,332 @@ index daa7b2ca..dd604d8b 100644 def get_workaround_efi_info(): +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py +index 0a86fa7b..cb95026c 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py +@@ -15,8 +15,8 @@ def check_config(model): + 'SSSD\'s sss_ssh_knownhostsproxy tool is replaced by the more ' + 'reliable sss_ssh_knownhosts tool. SSH\'s configuration will be updated ' + 'to reflect this by updating every mention of sss_ssh_knownhostsproxy by ' +- 'the corresponding mention of sss_ssh_knownhosts, even those commented out.\n' +- 'SSSD\'s ssh service will be enabled if not already done.\n' ++ 'the corresponding mention of sss_ssh_knownhosts, even those commented out. ' ++ 'SSSD\'s ssh service will be enabled if not already done.\n\n' + 'The following files will be updated:{}{}'.format( + FMT_LIST_SEPARATOR, + FMT_LIST_SEPARATOR.join(model.sssd_config_files + model.ssh_config_files) +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py +index 0ae9d93f..7d343229 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py +@@ -19,7 +19,10 @@ def _does_file_contain_expression(file_path, expression): + ) + return False + except OSError as e: +- raise StopActorExecutionError('Could not open file ' + file_path, details={'details': str(e)}) ++ raise StopActorExecutionError( ++ 'Could not open configuration file', ++ details={'details': 'Coudn\'t open {} file with error: {}.'.format(file_path, str(e))} ++ ) + + + def _look_for_files(expression: str, path_list: list[str]) -> list[str]: +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py +index 6d745ead..5b96bcc6 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py +@@ -1,7 +1,7 @@ + import os + import re + +-from leapp.exceptions import StopActorExecutionError ++from leapp.libraries.stdlib import api + + + def _process_knownhosts(line: str) -> str: +@@ -29,30 +29,26 @@ def _process_enable_svc(line: str) -> str: + + + def _update_file(filename, process_function): +- newname = filename + '.new' +- oldname = filename + '.old' ++ newname = '{}.leappnew'.format(filename) ++ oldname = '{}.leappsave'.format(filename) + try: +- with open(filename, 'r') as input_file, open(newname, 'x') as output_file: ++ with open(filename, 'r') as input_file, open(newname, 'w') as output_file: + istat = os.fstat(input_file.fileno()) + os.fchmod(output_file.fileno(), istat.st_mode) + for line in input_file: + try: + output_file.write(process_function(line)) + except OSError as e: +- raise StopActorExecutionError('Failed to write to {}'.format(newname), +- details={'details': str(e)}) ++ api.current_logger().warning('Failed to write to {}'.format(newname), details={'details': str(e)}) + +- except FileExistsError as e: +- raise StopActorExecutionError('Temporary file already exists: {}'.format(newname), +- details={'details': str(e)}) + except OSError as e: + try: + os.unlink(newname) + except FileNotFoundError: + pass +- raise StopActorExecutionError('Failed to access the required files', details={'details': str(e)}) ++ api.current_logger().error('Failed to access the required files', details={'details': str(e)}) + +- # Let's make sure the old configuration is preserverd if something goes wrong ++ # Let's make sure the old configuration is preserved if something goes wrong + os.replace(filename, oldname) + os.replace(newname, filename) + os.unlink(oldname) +diff --git a/utils/container-builds/Containerfile.centos7 b/utils/container-builds/Containerfile.centos7 +deleted file mode 100644 +index af00eddb..00000000 +--- a/utils/container-builds/Containerfile.centos7 ++++ /dev/null +@@ -1,15 +0,0 @@ +-FROM centos:7 +- +-VOLUME /repo +- +-# mirror.centos.org is dead, comment out mirrorlist and set baseurl to vault.centos.org +-RUN sed -i s/mirror.centos.org/vault.centos.org/ /etc/yum.repos.d/CentOS-*.repo +-RUN sed -i s/^#\s*baseurl=http/baseurl=http/ /etc/yum.repos.d/CentOS-*.repo +-RUN sed -i s/^mirrorlist=http/#mirrorlist=http/ /etc/yum.repos.d/CentOS-*.repo +- +-RUN yum update -y && \ +- yum install -y rpm-build python-devel make git +- +-WORKDIR /repo +-ENV DIST_VERSION 7 +-ENTRYPOINT make _build_local +diff --git a/utils/container-builds/Containerfile.ubi8 b/utils/container-builds/Containerfile.el8 +similarity index 100% +rename from utils/container-builds/Containerfile.ubi8 +rename to utils/container-builds/Containerfile.el8 +diff --git a/utils/container-builds/Containerfile.ubi9 b/utils/container-builds/Containerfile.el9 +similarity index 100% +rename from utils/container-builds/Containerfile.ubi9 +rename to utils/container-builds/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.el8 b/utils/container-tests/Containerfile.el8 +new file mode 100644 +index 00000000..b92e8742 +--- /dev/null ++++ b/utils/container-tests/Containerfile.el8 +@@ -0,0 +1,24 @@ ++FROM centos:8 ++ ++RUN sed -i s/mirror.centos.org/vault.centos.org/ /etc/yum.repos.d/CentOS-*.repo ++RUN sed -i s/^#\s*baseurl=http/baseurl=http/ /etc/yum.repos.d/CentOS-*.repo ++RUN sed -i s/^mirrorlist=http/#mirrorlist=http/ /etc/yum.repos.d/CentOS-*.repo ++ ++VOLUME /repo ++ ++RUN dnf update -y && \ ++ dnf install -y git make rsync \ ++ python3-virtualenv python3-setuptools python3-pip \ ++ python3-gobject NetworkManager-libnm ++ ++ENV PYTHON_VENV python3.6 ++ ++COPY . /repocopy ++ ++WORKDIR /repocopy ++ ++RUN rm -rf tut* ++ ++RUN make clean && make install-deps-fedora ++ ++WORKDIR / +diff --git a/utils/container-tests/Containerfile.rhel9 b/utils/container-tests/Containerfile.el9 +similarity index 100% +rename from utils/container-tests/Containerfile.rhel9 +rename to utils/container-tests/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.f34 b/utils/container-tests/Containerfile.f42 +similarity index 84% +rename from utils/container-tests/Containerfile.f34 +rename to utils/container-tests/Containerfile.f42 +index a9346635..46f0f63a 100644 +--- a/utils/container-tests/Containerfile.f34 ++++ b/utils/container-tests/Containerfile.f42 +@@ -1,11 +1,11 @@ +-FROM fedora:34 ++FROM fedora:42 + + VOLUME /repo + + RUN dnf update -y && \ + dnf install -y findutils make rsync python3-gobject-base NetworkManager-libnm + +-ENV PYTHON_VENV python3.9 ++ENV PYTHON_VENV python3.13 + + COPY . /repocopy + +diff --git a/utils/container-tests/Containerfile.rhel7 b/utils/container-tests/Containerfile.rhel7 +deleted file mode 100644 +index 0a0c384a..00000000 +--- a/utils/container-tests/Containerfile.rhel7 ++++ /dev/null +@@ -1,24 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /repo +- +-RUN yum update -y && \ +- yum install -y python-virtualenv python-setuptools make git rsync +- +-# see ./Containerfile.ubi7 for explanation +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-ENV PYTHON_VENV python2.7 +- +-COPY . /repocopy +- +-WORKDIR /repocopy +- +-RUN rm -rf tut* +- +-RUN make clean && make install-deps +- +-WORKDIR / +- +diff --git a/utils/container-tests/Containerfile.rhel8 b/utils/container-tests/Containerfile.rhel8 +deleted file mode 100644 +index 6f21839b..00000000 +--- a/utils/container-tests/Containerfile.rhel8 ++++ /dev/null +@@ -1,18 +0,0 @@ +-FROM registry.access.redhat.com/ubi8/ubi:latest +- +-VOLUME /repo +- +-RUN dnf update -y && \ +- dnf install -y python3-virtualenv python3-setuptools python3-pip make git rsync +- +-ENV PYTHON_VENV python3.6 +- +-COPY . /repocopy +- +-WORKDIR /repocopy +- +-RUN rm -rf tut* +- +-RUN make clean && make install-deps-fedora +- +-WORKDIR / +diff --git a/utils/container-tests/Containerfile.ubi7 b/utils/container-tests/Containerfile.ubi7 +deleted file mode 100644 +index 44625a76..00000000 +--- a/utils/container-tests/Containerfile.ubi7 ++++ /dev/null +@@ -1,25 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /payload +- +-RUN yum update -y && \ +- yum install python-virtualenv python-setuptools make git -y +- +-# NOTE(ivasilev,pstodulk) We need at least pip v10.0.1, however centos:7 +-# provides just v8.1.2 (via EPEL). So do this: install epel repos -> install +-# python2-pip -> use pip to update to specific pip version we require. period +-# NOTE(pstodulk) I see we take care about pip for py3 inside the Makefile, +-# however I am afraid of additional possible troubles in future because of the +-# archaic pip3 version (v9.0.1). As we want to run tests for Py2 and Py3 in ci +-# always anyway, let's put py3 installation here as well.. +-# Dropped Python3 as it is now added in its own container on RHEL8 +- +-# This is some trickery: We install python27-python-pip from the scl, use the scl to bootstrap the python +-# module of pip version 20.3.0 and then make it update to 20.3.4 resulting the 'pip' command to be available. +-# The --target approach doesn't add it, but at least we now have pip 20.3.4 installed ;-) +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/Containerfile.ubi7-lint b/utils/container-tests/Containerfile.ubi7-lint +deleted file mode 100644 +index ed548985..00000000 +--- a/utils/container-tests/Containerfile.ubi7-lint ++++ /dev/null +@@ -1,25 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /payload +- +-RUN yum update -y && \ +- yum install python-virtualenv python-setuptools make git -y +- +-# NOTE(ivasilev,pstodulk) We need at least pip v10.0.1, however centos:7 +-# provides just v8.1.2 (via EPEL). So do this: install epel repos -> install +-# python2-pip -> use pip to update to specific pip version we require. period +-# NOTE(pstodulk) I see we take care about pip for py3 inside the Makefile, +-# however I am afraid of additional possible troubles in future because of the +-# archaic pip3 version (v9.0.1). As we want to run tests for Py2 and Py3 in ci +-# always anyway, let's put py3 installation here as well.. +-# Dropped Python3 as it is now added in its own container on RHEL8 +- +-# This is some trickery: We install python27-python-pip from the scl, use the scl to bootstrap the python +-# module of pip version 20.3.0 and then make it update to 20.3.4 resulting the 'pip' command to be available. +-# The --target approach doesn't add it, but at least we now have pip 20.3.4 installed ;-) +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make lint +diff --git a/utils/container-tests/Containerfile.ubi8 b/utils/container-tests/Containerfile.ubi8 +deleted file mode 100644 +index 4da60c18..00000000 +--- a/utils/container-tests/Containerfile.ubi8 ++++ /dev/null +@@ -1,9 +0,0 @@ +-FROM registry.access.redhat.com/ubi8/ubi:latest +- +-VOLUME /payload +- +-RUN dnf update -y && \ +- dnf install python3-virtualenv python3-setuptools python3-pip make git -y +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/ci/Containerfile.el8 b/utils/container-tests/ci/Containerfile.el8 +new file mode 100644 +index 00000000..4a19092e +--- /dev/null ++++ b/utils/container-tests/ci/Containerfile.el8 +@@ -0,0 +1,15 @@ ++FROM centos:8 ++ ++RUN sed -i s/mirror.centos.org/vault.centos.org/ /etc/yum.repos.d/CentOS-*.repo ++RUN sed -i s/^#\s*baseurl=http/baseurl=http/ /etc/yum.repos.d/CentOS-*.repo ++RUN sed -i s/^mirrorlist=http/#mirrorlist=http/ /etc/yum.repos.d/CentOS-*.repo ++ ++VOLUME /payload ++ ++RUN dnf update -y && \ ++ dnf install -y make git \ ++ python3-virtualenv python3-setuptools python3-pip \ ++ python3-gobject NetworkManager-libnm ++ ++WORKDIR /payload ++ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/Containerfile.ubi8-lint b/utils/container-tests/ci/Containerfile.el8-lint +similarity index 100% +rename from utils/container-tests/Containerfile.ubi8-lint +rename to utils/container-tests/ci/Containerfile.el8-lint +diff --git a/utils/container-tests/Containerfile.ubi9 b/utils/container-tests/ci/Containerfile.el9 +similarity index 100% +rename from utils/container-tests/Containerfile.ubi9 +rename to utils/container-tests/ci/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.ubi9-lint b/utils/container-tests/ci/Containerfile.el9-lint +similarity index 100% +rename from utils/container-tests/Containerfile.ubi9-lint +rename to utils/container-tests/ci/Containerfile.el9-lint diff --git a/SPECS/leapp-repository.spec b/SPECS/leapp-repository.spec index 058dd24..331a7b5 100644 --- a/SPECS/leapp-repository.spec +++ b/SPECS/leapp-repository.spec @@ -53,7 +53,7 @@ py2_byte_compile "%1" "%2"} Epoch: 1 Name: leapp-repository Version: 0.23.0 -Release: 1%{?dist}.elevate.2 +Release: 1%{?dist}.elevate.3 Summary: Repositories for leapp License: ASL 2.0 @@ -350,6 +350,9 @@ fi %changelog +* Wed Oct 15 2025 Yuriy Kohut - 0.23.0-1.elevate.3 +- ELevate vendors support for upstream 0.23.0-1 version (e749dbc430099ac0d0cb06fb9dff4ec458d359b3) + * Tue Sep 30 2025 Yuriy Kohut - 0.23.0-1.elevate.2 - ELevate vendors support for upstream 0.23.0-1 version (47fce173e75408d9a7a26225d389161caf72e244)